Je souhaite essentiellement créer un composant de dialogue personnalisé que je peux utiliser de n'importe où dans mon application Angular2, quel que soit l'emplacement du composant utilisé dans l'arborescence de l'application. Pour plus de simplicité, appelons cela mon composant SayHello.

Considérez l'arborescence d'applications suivante: entrez la description de l'image ici

Supposons que je souhaite que SomeComponent.level3.component appelle la boîte de dialogue dans SayHello.component .

Dans Angular 1.x, j'injecterais RootScope dans un contrôleur et allumerais une boîte de dialogue de cette façon. Maintenant, je comprends (plus ou moins) que pour Angular2 vous pouvez faire remonter des événements (avec des émetteurs d'événements) dans l'arborescence des composants, mais il semble fastidieux de faire remonter un événement depuis SomeComponent.level3.component jusqu'à SayHello. .composant.

J'ai donc pensé créer un service SayHello que j'injecterais partout où je voulais éclairer ma boîte de dialogue. Voici une esquisse du code que j'ai formulé.

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
]);

Inutile de dire que cela ne fonctionne pas. Je n'obtiens aucune erreur, mais SayHello.component ne détecte aucun changement dans la valeur de «showdialog» ... donc rien ne se passe. Toute idée sur la manière de procéder correctement serait très appréciée.

8
brando 3 janv. 2016 à 04:39

2 réponses

Meilleure réponse

Comme mentionné dans un commentaire ci-dessus,

  • Mettez un observable dans le service (notez, pas un EventEmitter)
  • Placez une API / méthode showDialog () sur le service que d'autres composants peuvent appeler. La méthode showDialog () doit appeler next () pour envoyer un événement.
  • Votre composant de dialogue peut s'abonner à l'événement et s'afficher / s'afficher lorsqu'il reçoit un événement.

Pour encapsuler un observable dans un service, consultez cette réponse.

8
Community 23 mai 2017 à 11:46

Une alternative à l'utilisation d'un service consiste à créer dynamiquement le composant à l'aide de ViewContainerRef / createComponent décrit ici:

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

1
Alexander Taylor 7 déc. 2016 à 00:11