2

角度2を学習しようとする角度1のベテランです。私は自分自身とそのサブコンポーネントに注入される状態サービス(以下、MyState)を持つコンポーネントを持っています。私は次のように、トップレベルのコンポーネントで別のメンバーを更新し、サービスの状態の変更を監視したい:注入されたサービスのプロパティの検出を角度2で変更します。

import { Component, Input } from '@angular/core'; 

class Item { 
    constructor(public name: string) {} 
} 

class MyState { 
    selectedItems: Item[] = []; 
    addItem(item: Item) { 
    this.selectedItems.push(item); 
    } 
} 

// subcomponent 
@Component({ 
    selector: '[item]', 
    template: ` 
    <!-- state changed from subcomponent: --> 
    <button (click)="state.addItem(model)"> 
     select item {{model.name}} 
    </button> 
    ` 
}) 
class ItemComponent { 
    @Input() model: Item; 
    constructor(private state: MyState){} 
} 

// main component 
@Component({ 
    selector: 'items', 
    template: ` 
    <h1> Available Items: </h1> 
    <ul> 
     <li *ngFor="let item of items" item [model]="item"></li> 
    </ul> 
    <h1> Added Items: </h1> 
    <p>{{ addedItemsString }}</p> 
    `, 
    providers: [MyState], 
    directives: [ItemComponent] 
}) 
class ListComponent { 
    @Input() items: Item[]; 
    private addedItemsString: string = ''; 

    constructor(private state: MyState) { 
    // listen for changes to this.state.selectedItems to 
    // call this.updateAddedItemsString 
    } 

    updateAddedItemsString() { 
    this.addItemsString = this.state.selectedItems.map(i => i.name).join(', '); 
    } 
} 

私の質問は:どのように私はListComponentコンストラクタで擬似コードを実装する必要がありますか?確かに

は、addItemsStringメンバーは不自然であると確かにテンプレート自体で行われますが、私の質問のためにupdateAddedItemsStringListComponentの別のメンバーを更新し、より多くの複雑なものを行うことができることを前提とすることができます。

ありがとうございます!

+1

サービスで観測可能なものを使用して、変更をサブスクライブすることができます。 https://angular.io/docs/ts/latest/cookbook/component-communication.html –

+0

リード@GünterZöchbauerに感謝します!フォローアップの質問:Observable を州自体の財産として作成することは賢明ですか? – AndyPerlitch

答えて

2

あなたのサービスでBehaviorSubject<Item[]>を使用し、あなたのListComponentは、その観察可能な配列への変更をサブスクライブがあります。私は毎回next()が呼び出され、アレイ全体を発する

class MyState { 
    private _selectedItems: Item[] = []; 
    private _selectedItemsSource = new BehaviorSubject<Item[]>(this._selectedItems); 
    selectedItems$ = this._selectedItemsSource.asObservable(); 
    addItem(item: Item) { 
    this._selectedItems.push(item); 
    this._selectedItemsSource.next(this._selectedItems); 
    } 
} 

@Component({ 
    selector: 'items', 
    template: `<h1> Available Items: </h1> 
    <ul> 
     <li *ngFor="let item of items" item [model]="item"></li> 
    </ul> 
    <h1> Added Items: </h1> 
    <div>{{ addedItemsString }}</div>`, 
    providers: [MyState], 
    directives: [ItemComponent] 
}) 
class ListComponent { 
    @Input() items: Item[]; 
    private addedItemsString: string = ''; 
    constructor(private state: MyState) {} 
    ngOnInit() { 
    this.subscription = this.state.selectedItems$.subscribe(
     items => this.addedItemsString = items.map(i => i.name).join(', ')); 
    } 
    ngOnDestroy() { 
    // prevent memory leak when component is destroyed 
    this.subscription.unsubscribe(); 
    } 
} 

Plunker

。これにより、後でBehaviorSubjectにサブスクライブする他のコンポーネントが完全なリストを取得することが保証されます。この要件がない場合は、addItem()が呼び出されたときに新しい値だけを出力することができます。

+0

回答ありがとう@markrajcok。これは、BehaviorSubjectと同様にSubjectでも機能するようです。違いは何ですか? – AndyPerlitch

+2

[BehaviorSubjectのリンク](http://reactivex.io/rxjs/manual/overview.html#behaviorsubject)を参照してください。要約すると、BehaviorSubjectは「現在の値」の概念を持っているため、新しいObserverが購読するたびに、すぐに「現在の値」が受信されます。被験者はそれをしません。サブジェクトを使用して値を発行し、その後サブスクライブすると、新しいオブザーバは以前に発行された値を表示しません。将来の発行される値のみを取得します。現在の状態(新しい値ではなく)を共有しているように見えるので、私はBehaviorSubjectを提案しました。 –

+0

ありがとう、そのリンクを最初にフォローしなかったことを謝罪します。私を助けてくれました! – AndyPerlitch

関連する問題