2017-02-23 2 views
1

langsam mit angular 2 in den Griff zu bekommen, aber ich habe zu einem bestimmten Problem zu Sackgasse gekommen.Angular 2 => Benachrichtigen Sie eine Route Komponente eines Ereignisses in der App-Komponente

Wenn Sie diese Anordnung haben;

<parent> 
    <child/> 
</parent> 

kann ich das Kind von Änderungen in der übergeordneten benachrichtigen, indem Sie @Input() und lassen es zu Änderungen hören. Ich kann die Eltern über Änderungen in dem unterordneten Element informieren, indem Sie @Output() und EventEmiters verwenden.

Was ich jetzt ansehe, benachrichtigt eine geroutete Komponente (eine Komponente, die dynamisch geladen wird, wenn eine Verknüpfung geklickt wird) über ein bestimmtes Ereignis, das in der Haupt-appComponent passiert. Siehe Beispiel unten;

<app> 
    <button (click)='addEntity()>Add</button> 
    <router-outlet></router-outlet> 
</app> 

Ich mag die Komponente benachrichtigen können, die in die Router-Steckdose geladen wird, dass die Schaltfläche geklickt wurde.

Ein Beispiel für die Verwendung wäre mehrere Funktionen (Helden/Kontakte/Haustiere usw.) jeweils mit einem eigenen Dialog zum Hinzufügen einer Entität. Abhängig von der ausgewählten Route müsste sie die ausgewählte Merkmalskomponente (z. B. ContactComponent) benachrichtigen, um ihre spezifische Detailkomponente/Ansicht/Schablone (z. B. Kontakt-Detail-Komponente) anzuzeigen.

Was ist der beste Weg, dies zu erreichen?

Prost

Antwort

3

Es gibt auch die Möglichkeit, nur einen geteilten Dienst zu verwenden, um zwischen verschiedenen Komponenten zu kommunizieren, z. über einen Kurierdienst wie folgt aus:

Messenger

import { Injectable } from '@angular/core'; 
import { BehaviorSubject } from 'rxjs'; 
import { Observable } from 'rxjs/Rx'; 

@Injectable() 
export class MessengerService { 
    private messageSource: BehaviorSubject<boolean> = new BehaviorSubject(true); 
    public message = this.messageSource.asObservable(); 
    public buttonClicked(value: boolean) { 
     this.messageSource.next(value); 
    } 
} 

geordnete Komponente

export class ParentComponent { 
    constructor(private messengerService: MessengerService) { } 
    addEntity() { 
     this.messengerService.buttonClicked(true); 
    } 
} 

Kinder Komponente

import { Subscription } from 'rxjs/Rx'; 
export class ChildComponent implements OnInit, OnDestroy { 
    private messageSubscription: Subscription; 
    constructor(private messengerService: MessengerService) { } 
    ngOnInit() { 
     this.messageSubscription = this.messengerService.message.subscribe(m => { 
      // Act upon the click event 
     }); 
    } 
    ngOnDestroy() { 
     this.messageSubscription.unsubscribe(); 
    } 
} 

Dies wäre ein sauberer Weg, um die Komponenten zu entkoppeln und sich auf einen Messenger-Service zu verlassen (den Sie in mehreren Komponenten abonnieren könnten, wo immer es benötigt wird)

+0

Es scheint, dass ein gemeinsamer Dienst der einzige Weg ist, dies zu erreichen. Ich habe irgendwo gelesen, dass Dienste keine Ereignisemitter verwenden sollten, was für mich die beste Option wäre, da ich keinen Zustand kommuniziere, sondern eine Absicht, dh addEntity sagt, dass der Benutzer den addEntity-Bildschirm sehen möchte, nicht die Sichtbarkeit von diesem Bildschirm (weil es möglicherweise bereits sichtbar ist). So oder so funktioniert das, es erscheint nur merkwürdig, da es so aussieht, als ob Sie ein Observable abonnieren, dessen Wert sich nie wirklich ändert. – Mark

+0

Dies löste ein Rand-Fall-Problem für mich, dass ich wirklich unsicher war, wie man sonst auf eine ordentliche Weise löst. Vielen Dank. – Sam

0

Nun, wenn ich das gut verstehen Ihre Frage versuchen: auf dem addEntity einen Rückgabewert setzen() -Methode kann ein String oder etwas sein, dass Sie die Art von Dingen wissen, die Sie hinzufügen (Helden/Kontakte/Haustiere). Dann auf der Hauptvorlage setzen eine lokale Variable, die die Rückkehr des addEntity() -Methode wie dies geschieht:

<button (click)='#type_added = addEntity()>Add</button> 

dann können Sie das wie folgt aus „#type_added“ lokale Variable auf die andere Komponente zu übergeben:

<router-outlet [added] = #type_added></router-outlet> 

und Sie müssen in Ihrer Router-outlet-Komponente (.ts) die Variable "added" mit der @Output angeben.

+0

Sind Sie sicher, dass das funktioniert? 'router-outlet' ist der [Selector der Komponente] (https: // angular.io/docs/ts/next/api/router/index/RouterOutlet-directive.html), in die Komponenten für untergeordnete Routen gerendert werden, keine benutzerdefinierte Komponente. – GeorgDangl

Verwandte Themen