2

Angular1在這裏嘗試學習angular2。我有一個具有狀態服務的組件(下面的MyState),它被注入到它自己及其子組件中。我想看關於該服務的狀態發生變化,然後更新在頂級組件另一名成員,具體如下:在angular2中更改對注入服務屬性的檢測

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成員是人爲的,並可以肯定是在模板本身來完成,但對於我的問題的緣故假設updateAddedItemsString可以做很多,更新的ListComponent不同的部件更復雜的東西。

在此先感謝!

+1

在您的服務中使用observable,然後您可以訂閱更改。 https://angular.io/docs/ts/latest/cookbook/component-communication.html –

+0

感謝領先@GünterZöchbauer!後續問題:創建一個Observable 作爲國家本身的財產是否可以接受? – AndyPerlitch

回答

2

使用BehaviorSubject<Item[]>在您服務,讓您的ListComponent訂閱變化可觀察的數組:

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

我發出整個陣列每次next()被稱爲。這可確保稍後訂閱BehaviorSubject的任何其他組件都將獲得完整列表。如果你沒有這個要求,當調用addItem()時,你可以只發出新的值。

+0

感謝您的答案@markrajcok。這似乎與Subject和BehaviorSubject一起工作。有什麼不同? – AndyPerlitch

+2

請參閱答案中提供的[行爲主題鏈接](http://reactivex.io/rxjs/manual/overview.html#behaviorsubject)。總之,BehaviorSubject具有「當前值」的概念,所以無論何時新Observer訂閱,它都會立即收到「當前值」。主題不會這樣做。如果您使用主題併發佈一個值,然後訂閱,則新的觀察者將不會看到之前發佈的值 - 它只會獲得未來發布的值。由於您似乎在分享當前狀態(而不僅僅是新值),因此我建議了BehaviorSubject。 –

+0

感謝您的支持,並且非常抱歉不要先關注該鏈接。幫助我出去了很多! – AndyPerlitch