2017-01-03 11 views
33

私はサーバーに行きオブジェクトをフェッチする親コンポーネントを持っています。"router-outlet"子コンポーネント(角2)にデータを渡す

// parent component 

@Component({ 
    selector : 'node-display', 
    template : ` 
     <router-outlet [node]="node"></router-outlet> 
    ` 
}) 

export class NodeDisplayComponent implements OnInit { 

    node: Node; 

    ngOnInit(): void { 
     this.nodeService.getNode(path) 
      .subscribe(
       node => { 
        this.node = node; 
       }, 
       err => { 
        console.log(err); 
       } 
      ); 
    } 

そして、私の子表示(いくつかの1)で

export class ChildDisplay implements OnInit{ 

    @Input() 
    node: Node; 

    ngOnInit(): void { 
     console.log(this.node); 
    } 

} 

それは私がちょうどルータコンセントにデータを挿入することができます考えていないようです。それは私がWebコンソールでエラーが出るようにこれはやや理にかなって

Can't bind to 'node' since it isn't a known property of 'router-outlet'. 

...見えますが、私はどうなるか、次の....

1) Grab the "node" data from the server, from within the parent component 
2) Pass the data I have retrieved from the server into the child router-outlet 

それはように見えるしていませんルータ出口も同じように機能します。

答えて

34

唯一の方法は、共有サービスを使用することです。

<router-outlet [node]="..."></router-outlet> 

は無効です。ルータによって追加されたコンポーネントは、兄弟として<router-outlet>に追加され、置き換えられません。

https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service

@Injectable() 
export class NodeService { 
    private node:Subject<Node> = new BehaviorSubject<Node>(); 
    node$ = this.node.asObservable(); 

    addNode(data:Node) { 
    this.node.next(data); 
    } 
} 
@Component({ 
    selector : 'node-display', 
    providers: [NodeService], 
    template : ` 
     <router-outlet></router-outlet> 
    ` 
}) 
export class NodeDisplayComponent implements OnInit { 
    constructor(private nodeService:NodeService) {} 
    node: Node; 
    ngOnInit(): void { 
     this.nodeService.getNode(path) 
      .subscribe(
       node => { 
        this.nodeService.addNode(node); 
       }, 
       err => { 
        console.log(err); 
       } 
      ); 
    } 
} 
export class ChildDisplay implements OnInit{ 
    constructor(nodeService:NodeService) { 
     nodeService.node$.subscribe(n => this.node = n); 
    } 
} 
+0

これは私のために働くように見えます。ちょっと混乱しているようですが、休憩です。 – Zack

+0

さて、私はちょうど別のメソッド "announceNewNode"を自分のノードサービスに追加しました。これは、子コンポーネントが更新するべき時を知ることができるようにします。次に、子コンポーネントのサービスを購読します。ありがとう! – Zack

+0

最後のクラスでは、 "$"です。タイプミス?私はそれへの参照を見つけることができません... – Gyromite

22

も参照してくださいGünters答えは、私はちょうど観測を使用せずに別の方法を指摘したい、素晴らしいです。

ここでは、これらのオブジェクトは参照渡しであることを覚えておく必要があります。そのため、親オブジェクトに影響を与えずに子オブジェクト内のオブジェクトを処理したい場合は、Güntherのソリューションを使用することをおすすめします。しかし、それは問題ではない、または実際に希望の動作、私は以下をお勧めします。あなたが値を割り当てることができ、あなたの親で

@Injectable() 
export class SharedService { 

    sharedNode = { 
     // properties 
    }; 
} 

は:
this.sharedService.sharedNode = this.node; 

そして、あなたの子供たち(と親)で

、あなたのコンストラクタ内の共有サービスを注入します。そのモジュールのコンポーネント全体にシングルトンサービスが必要な場合は、モジュールレベルのプロバイダ配列でサービスを提供することを忘れないでください。あるいは、プロバイダ のプロバイダ配列にというサービスだけを追加すると、親と子は同じサービスインスタンスを共有します。

node: Node; 

ngOnInit() { 
    this.node = this.sharedService.sharedNode;  
} 

そしてニューマンが親切に指摘したように、あなたはまた、HTMLテンプレート内this.sharedService.sharedNodeやゲッターを持つことができます。

get sharedNode(){ 
    return this.sharedService.sharedNode; 
} 
+1

もっと欲しい一度受け入れるよりも。 – Zack

+2

done ........... – Zack

+3

あなたはhtmlのsharedService.sharedNodeに直接バインドできます。このようにして、sharedNodeの更新は同期して保持されます。 – newman

5

サービス:

import {Injectable, EventEmitter} from "@angular/core";  

@Injectable() 
export class DataService { 
onGetData: EventEmitter = new EventEmitter(); 

getData() { 
    this.http.post(...params).map(res => { 
    this.onGetData.emit(res.json()); 
    }) 
} 

コンポーネント:

import {Component} from '@angular/core';  
import {DataService} from "../services/data.service";  

@Component() 
export class MyComponent { 
    constructor(private DataService:DataService) { 
    this.DataService.onGetData.subscribe(res => { 
     (from service on .emit()) 
    }) 
    } 

    //To send data to all subscribers from current component 
    sendData() { 
    this.DataService.onGetData.emit(--NEW DATA--); 
    } 
} 
+0

画像としてではなく、テキストとしてコードを入力してください。 – Rob

+0

これは最善の答えです。非常にきれいでクリーンな再利用。あなたは私の仲間を救った。データを送信し、それにサブライセンスを付けることは素晴らしい考えです。 – JavaFreak

+2

@JavaFreakとegor:この方法はお勧めしません。このようにしたい場合は、GünterのようにSubjectまたはBehaviorSubjectを代わりに使用してください。https://stackoverflow.com/a/36076701/6294072 – Alex

関連する問題