2017-03-09 89 views
2

contentChildren與其「父」之間的首選通信方式是什麼?Angular 2:contentChildren communication

更新:孩子可能不是直接父...

鑑於兒童的隨機列表,由一組包裝:

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

的子組件:

@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? 
    } 

} 

父組件:

@Component({ 
    selector: 'child-group', 
    template: '<ng-content></ng-content>', 
    styleUrls: ['child-group.component.scss'], 
}) 
export class ChildGroupComponent implements AfterContentInit { 
    @ContentChildren(ChildComponent) childrenList: QueryList<ChildComponent>; 

    constructor() { 
    } 

    ngAfterContentInit() { 
     //How to invoke doSomething() on all children? 
     childrenList... 

     //How can I get notification from one or all children, that it did something, or its state has changed. 
     childrenList... 
    } 
} 

如何從ChildGroup中調用子方法?一個孩子怎麼能把信息發回給ChildGroup?

UPDATE:

在下面我提到的,當我嘗試調用對孩子沒有什麼方法正在發生的意見。那麼事實證明,我需要訂閱的變化,等待孩子......然後我就能夠調用

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

你可以在child上創建一個函數,你可以調用childrenList循環,類似的,你可以創建一個你可以在父類中訂閱的eventemitter。 –

回答

3

以前的答案是完全正確的,使用@Output和循環通過你的QueryList是要走的路,但如果像你所說,你的孩子是不是直接的,你可以使用一個服務作爲通信香奈兒。

這裏是一個非常基本的蹲跳者演示這個:http://plnkr.co/edit/VuYiz7gVB42PEnnk2d8C(我不是專家,所以也許這可能會得到改善)。

基本上,當你點擊你的孩子組成的一個按鈕,它使用:

this.myService.sendToParent(this.random); 

通過服務發送消息到父。在此功能,該服務通過可觀察到的將消息發送到父:

this.parentSubject.next(value); 

此前,父母訂閱此觀察到:

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

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

正如你所看到的,當它接收到一個新的價值,它使用功能sendToChildren通過服務向他的所有子女發送消息(當時適用相同的原則)。當孩子接收到消息時,它會更改最終顯示在組件中的值。

+0

謝謝你的詳細答覆。我如何確保所使用的服務對於特定組是唯一的?這是viewProvider會進來嗎? – Thibs

+0

我編輯了我的蹦牀,告訴你如何做到這一點。基本上,我不是在應用程序模塊中導入提供程序,而是將它導入到父組件中,這樣就爲該類型的每個組件創建了一個新的服務實例。欲瞭解更多信息,請參閱這個真棒回答:http://stackoverflow.com/questions/35888434/what-are-viewproviders-in-angular-2-and-what-is-the-difference-bw-providers-vs – ssougnez

+0

也許我應該爲此啓動一個新問題,但是當我將提供程序移動到父級時,出現此錯誤:未處理的Promise拒絕:沒有MyService提供程序! ;區域:角度;任務:Promise.then - 我今天碰到了Angular 4,不知道那裏是否有區別。但是,在我的應用程序中,我使用延遲加載,並且此父/子是模塊的一部分,我只將它導入父組件,這確實是我需要導入它的唯一位置?不知道我去哪裏錯了......謝謝 – Thibs

3

爲您的孩子父母的情況下,一個@Output事件發射器是你最好的選擇。您的子組件正在將內部操作(用戶單擊某處)轉換爲該組件的任何用戶都可以監聽的業務相關事件。

至於父母打電話的孩子,你已經是你的榜樣的大部分方式。只需遍歷QueryList並調用您希望在您的子組件上使用的任何方法即可。

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

我忘記了顯示孩子可能是也可能不是直系父母,那麼@Ouput仍然會工作嗎?我會更新我的問題.. – Thibs

+0

如果它不是一個直接的孩子,那麼不是,你必須手動將事件向上拉鍊,或使用服務來中介通信 – snorkpete

+0

感謝您的答覆。我試着調用callMethod(),但沒有任何反應。註銷this.childrenList.length結果爲0 .. 對於服務,我怎麼能保證該服務對於這組子/只是唯一的,因爲我可以在頁面上有多個子組。甚至嵌套... – Thibs