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 に答える