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