2017-03-09 4 views
2

contentChildrenとその親の間で通信するための好ましい方法は何ですか?角2:contentChildrenの通信

更新日:

<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

あなたはchildrenListにループを呼び出すことができる子に関数を作成することができます。同様に、親でサブスクライブするイベントエミッタを作成することもできます。 –

答えて

3

以前の回答は@Outputを使用して、完全に正確であるとあなたのQueryListをループして移動するための方法ですが、あなたが述べたように、あなたの子供が直接のものではありません、場合、あなたは通信シャネルなどのサービスを使用することができます。

ここには、これを示す非常に基本的なプランカがあります:http://plnkr.co/edit/VuYiz7gVB42PEnnk2d8C(私はobservablesのエキスパートではないので、これは改善できるかもしれません)。

あなたの子コンポーネントのボタンをクリックすると、基本的に、それは使用しています:

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

私はこれについて新しい質問を開始する必要がありますが、私は親でプロバイダを移動したときにこのエラーが発生します:Unhandled 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

私は子供が直接の親であるかもしれないし、そうでないかもしれないことを示すのを忘れてしまった。私は質問を更新します。 – Thibs

+0

もしそれが直接の子供でないなら、あなたは手動でチェーンの上にイベントをバブリングするか、サービスを使ってコミュニケーションを仲介する必要があります – snorkpete

+0

返事をありがとう。 callMethod()を呼び出そうとしましたが、何も起こりません。 this.childrenList.lengthをログアウトすると0が返されます。 サービスでは、ページに複数の子グループを持つことができるため、サービスがこの子グループ/グループのみに固有であることをどのように保証できますか。または入れ子にさえ... – Thibs

関連する問題