8

我基本上想创建一个自定义对话框组件,无论使用组件在应用程序树中的哪个位置,我都可以在 Angular2 应用程序的任何位置使用它。为简单起见,我们将其称为我的 SayHello 组件。

考虑以下应用程序树:在此处输入图像描述

因此,假设我希望SomeComponent.level3.component调用SayHello.component中的对话框。

在 Angular 1.x 中,我会将 RootScope 注入控制器并以这种方式点亮一个对话框。现在,我(或多或少)了解,对于 Angular2,您可以在组件树中冒泡事件(使用事件发射器),但是从 SomeComponent.level3.component 向上冒泡事件并向下到 SayHello 似乎很乏味。零件。

所以我想我会创建一个 SayHello 服务,我会在任何我想点亮我的对话框的地方注入它。这是我制定的代码的草图。

myApp.component.ts

import {SayHelloComponent} from "<<folder>>/sayHello.component";
import {BunchOfComponents} from "<<folder>>/bunchOfComponents";

@Component({
    directives: [SayHelloComponent],
    selector: "my-app",
    templateUrl: `<bunch-of-components>Within this component exists
                      SomeComponent.level3.component </bunch-of-components>
                      <say-hello showdialog="{{showDialog}}" message="{{message}}">
                      </say-hello>`

})
export class myAppComponent {
    showDialog = false;
    message = "";

    constructor(private sayHelloService: SayHelloService) {
        this.showDialog = sayHelloService.showDialog;
        this.message = sayHelloService.message;

    }
}

SayHelloService.ts

import {Injectable} from 'angular2/core';

@Injectable()
export class SayHelloService {
    public showDialog: boolean = false;
    public message: string ="";

    constructor() {

    }

}

SayHello.component.ts

import {Component} from "angular2/core";
import {SayHelloService} from "<<folder>>/SayHelloService";
@Component({
    directives: [],
    selector: "say-hello",
    template: "[do hello component]"
})
export class SayHelloComponent {
    @Input() showdialog: boolean;
    @Input() message: string;

       constructor(private sayHelloService: SayHelloService) {

    }
    //This idea here is to detect change in showDialog
    //If true then do an alert with the message
    ngOnChanges(changes: { [propName: string]: SimpleChange }) {
        var obj = changes["showdialog"];
        if (obj !== null) {
            if (changes["showdialog"].currentValue === true) {
                alert(this.message);
                this.sayHelloService.showDialog = false;
            }

        };
    }

}

SomeComponent.level3.component

import {Component} from "angular2/core";
import {SayHelloService} from "<<folder>>/SayelloService";

@Component({
    directives: [],
    selector: "some-component",
    template: "<button (click)='doHello()'>Do say hello</button>"
})
export class PageContactUsComponent {

    constructor(private sayHelloService: SayHelloService) {

    }


    doHello(): void {
        this.sayHelloService.message = "Hello world";
        this.sayHelloService.showDialog = true;
    }
}

appBoot.ts

import {bootstrap} from "angular2/platform/browser";
import {MyAppComponent} from "<<folder>/MyAppComponent";
import {SayHelloService} from "<<folder>>/SayHelloService";

bootstrap(MyAppComponent, [
    SayHelloService
]);

不用说,这是行不通的。我没有收到任何错误,但 SayHello.component 没有检测到“showdialog”值的任何变化……所以什么也没有发生。任何关于如何正确执行此操作的想法将不胜感激。

4

2 回答 2

8

正如上面评论中提到的,

  • 将 Observable 放入服务中(注意,不是 EventEmitter)
  • 将 showDialog() API/方法放在其他组件可以调用的服务上。showDialog() 方法应该调用 next() 来发送事件。
  • 您的对话框组件可以订阅事件并在收到事件时取消隐藏/显示自己。

要将 Observable 包装在服务中,请参阅此答案

于 2016-01-03T02:58:13.293 回答
1

使用服务的替代方法是使用此处描述的 ViewContainerRef/createComponent 动态创建组件:

https://www.lucidchart.com/techblog/2016/07/19/building-angular-2-components-on-the-fly-a-dialog-box-example/

于 2016-12-07T00:11:43.313 回答