2017-03-09 3 views
2

Wie wird die Kommunikation zwischen contentChildren und seinem übergeordneten Element bevorzugt?Angular 2: contentChildren communication

AKTUALISIERT: Kind möglicherweise nicht direkt Eltern ...

eine zufällige Liste von Kindern gegeben, die von einer Gruppe eingewickelt:

<child-group> 
    <div>Some other content, child may not be direct parent...</div> 
    <child *ngFor="let item of data$ | async;"></child> 
</child-group> 

Das Kind Komponente:

@Component({ 
    selector: 'child', 
    template: '<button (click)="didSomethingTellGroup()"></button>', 
    styleUrls: ['child.component.scss'], 
}) 
export class ChildComponent implements OnInit { 

    constructor() { 
    } 

    ngOnInit() { 

    } 

    doSomething() { 
     console.log('Called from group component') 
    } 

    didSomethingTellGroup() { 
     //EventEmitter? 
     //Observable? 
    } 

} 

Die Hauptkomponente:

Wie kann ich eine Child-Methode von ChildGroup aufrufen? Und wie kann ein Kind Informationen an die ChildGroup zurücksenden?

UPDATE:

In den Kommentaren unten erwähnte ich, dass, wenn ich eine Methode auf dem Kind nichts zu berufen versuche vorging. Nun stellt sich heraus, dass ich zu den erforderlichen Änderungen abonnieren und für die Kinder warten ... dann war ich in der Lage

ngAfterContentInit() 
{ 
    this.childrenList.changes 
     .subscribe(list => { 
       list.forEach(c => c.doSomething()) 
      } 
     ); 
} 
+0

Sie können eine Funktion auf Kind erstellen, die Sie auf childrenList Schleife aufrufen können, in ähnlicher Weise können Sie einen eventemitter erstellen, die Sie in der übergeordneten abonnieren können. –

Antwort

3

Die bisherigen Antworten sind völlig korrekt, @Output mit und Schleife durch Ihre QueryList ist der Weg zu gehen, aber wenn, wie Sie erwähnt haben, Ihre Kinder sind nicht direkt diejenigen, könnten Sie einen Dienst als Kommunikations chanel zu verwenden .

Hier ist ein sehr einfaches Beispiel: http://plnkr.co/edit/VuYiz7gVB42PEnnk2d8C (Ich bin kein Experte für Observables, also vielleicht könnte dies verbessert werden).

Grundsätzlich, wenn Sie auf eine Schaltfläche Ihres Kindes Komponente klicken, wird es verwendet:

this.myService.sendToParent(this.random); 

Um eine Nachricht an die Eltern durch den Dienst zu senden. In dieser Funktion sendet der Dienst eine Nachricht über einen beobachtbaren dem Mutter:

this.parentSubject.next(value); 

Zuvor hatte die Eltern auf diese beobachtbaren gezeichnet:

this.service.getParentMessages().subscribe((data) => 
{ 
    alert('Something changed from a children: ' + data); 

    this.service.sendToChildren(data); 
}); 

Wie Sie sehen können, wenn sie einen neuen Wert erhält , verwendet es die Funktion sendToChildren, um eine Nachricht an alle seine Kinder durch den Dienst zu senden (das gleiche Prinzip gilt dann). Wenn Kinder Nachrichten erhalten, ändert sich ein Wert, der schließlich in der Komponente angezeigt wird.

+0

Danke für die ausführliche Antwort. Wie kann ich sicherstellen, dass der verwendete Service für die jeweilige Gruppe einzigartig ist? Ist dies der Ort, an dem der viewProvider eintrifft? – Thibs

+0

Ich habe meinen Plunker bearbeitet, um Ihnen zu zeigen, wie das geht. Anstatt den Provider im App-Modul zu importieren, importierte ich ihn im Wesentlichen in der übergeordneten Komponente. Auf diese Weise wird für jede Komponente dieses Typs eine neue Instanz des Service erstellt. Weitere Informationen finden Sie in dieser fantastischen Antwort: http://stackoverflow.com/questions/35888434/what-are-viewproviders-in-angular-2-and-what-is-the-difference-bw-providers-vs – ssougnez

+0

vielleicht Ich sollte dafür eine neue Frage starten, aber als ich den Provider in den Parent verschoben habe, habe ich diesen Fehler bekommen: Unhandled Promise Rejection: Kein Provider für MyService! ; Zone: eckig; Aufgabe: Promise.then - Ich bin heute auf Angular 4 gestoßen, nicht sicher, ob es da einen Unterschied gibt. Aber in meiner App verwende ich Lazy Loading und dieses Elternteil/Kind ist Teil eines Moduls, ich importiere es nur in der Elternkomponente, das ist in der Tat der einzige Ort, an dem ich es importieren muss? Nicht sicher, wo ich falsch liege ... danke – Thibs

3

für Ihr Kind zu Eltern Szenario aufzurufen, ein @Output Ereignis-Emitter ist die beste Wahl. Ihre untergeordnete Komponente konvertiert eine interne Aktion in sich (ein Benutzer klickt irgendwo) in ein geschäftsbezogenes Ereignis, auf das jeder Benutzer dieser Komponente warten kann.

Wie für Eltern anrufen Kind, Sie sind schon am meisten Weg dorthin mit Ihrem Beispiel. Überspringen Sie einfach die QueryList und rufen Sie die gewünschte Methode für Ihre untergeordneten Komponenten auf.

ngAfterContentInit() {  
    //How to invoke  doSomething() on all children? 
    this.childrenList.forEach (c => c.doSomething();) 
    ... 
} 
+0

Ich habe vergessen zu zeigen, dass das Kind direkt Eltern sein kann oder nicht, würde @Ouput immer noch funktionieren? Ich werde meine Frage aktualisieren .. – Thibs

+0

Wenn es kein direktes Kind ist, dann nein, müssen Sie entweder das Ereignis die Kette manuell sprudeln, oder verwenden Sie einen Dienst, um die Kommunikation zu vermitteln – snorkpete

+0

Danke für die Antworten. Ich habe versucht, CallMethod() aufzurufen, aber nichts passiert. Das Abmelden von this.childrenList.length führt zu 0 .. Wie kann ich für den Dienst garantieren, dass der Dienst nur für diese Gruppe von untergeordneten/Gruppen eindeutig ist, da ich mehr als eine untergeordnete Gruppe auf der Seite haben kann . Oder sogar verschachtelt ... – Thibs

Verwandte Themen