Angular2 - 在订阅可观察的

时间:2016-09-17 18:34:57

标签: angular typescript rxjs angular2-changedetection

我正在尝试设置可以搜索的项目目录。我的目录组件有几个可观察的订阅。每当更新搜索词时,它都会将该查询应用于项列表并返回匹配项。搜索功能位于一个单独的组件中,该组件执行过滤并向searchService发送一个值以指示它何时开始和停止搜索。我想通过单独的加载器订阅来利用这个值更改并更新" isLoading" boolean在搜索函数运行时显示微调器。

catalog.cmp.ts:

ngOnInit(){
    this.dataService.getData().subscribe((res) =>{
        this.stock = res;
        this.allstock = res;
    });

    this.searchsubscription = this.searchService.termUpdate$.subscribe(
            (item) => {
                this.searchTerm = item;
                //the following searches through the allstock array and returns the list to be displayed with ngFor
                this.stock = this.search.transform(this.allstock,{query:this.searchTerm})
            },
            (err) => {console.log(err)}
     );

     this.loadsubscription = this.searchService.loadUpdate$.subscribe(
         (res) => {
            this.toggleLoader(res)
         },
         (err) => {console.log(err)}
     );
}

toggleLoader()函数如下所示:

toggleLoader(state){
    this.isLoading = state;
    console.log("ISLOADING",this.isLoading)
}

search.service.ts:

export class SearchService {
private isLoading;
private searchTerm = '';
private termSource = new BehaviorSubject<any>('');
termUpdate$ = this.termSource.asObservable();
private loadSource = new BehaviorSubject<boolean>(false);
loadUpdate$ = this.loadSource.asObservable();

constructor(){}

setTerm(term){
    this.searchTerm = term;
    this.termSource.next(term);
    console.log(this.searchTerm, 'term updated')
}
getTerm(){
    return this.searchTerm;
}
setLoadState(state: boolean){
    this.isLoading = state;
    this.loadSource.next(state);
    console.log(this.isLoading, 'loading status')
}
getLoadState(){
    return this.isLoading;
}

}

在我的组件模板中,我有这个设置:

<div>{{isLoading}}, {{searchTerm}} <-- this part is for debugging
    <spinner *ngIf="isLoading"></spinner>
    <button (click)="toggleLoader(true)">true</button>
    <button (click)="toggleLoader(false)">false</button>
</div>
<span *ngIf="!isLoading">
    <div class="row"
    *ngFor="let item of stock| paginate: { itemsPerPage: 10, currentPage: p }">
    ...
    </div>
</span>

因此除了isLoading值之外,视图的每个方面都会更新。但isLoading的正确值在控制台中和正确的时间显示(当发送搜索项并且过滤器正在运行时为true,当返回新的库存数组时为false,并且为更新提供ng)。在视图中没有检测到更改。我的toggleLoader调试按钮会正确更新视图。

我尝试过在类似问题中发布的许多解决方案,例如在zone.run()中包装toggleLoader的主体,或者使用ChangeDetectorRef手动调用更改检测。我甚至可以尝试不使用loadsubscription,而是在我调用search.transform之前调用toggleLoader,并在完成后再调用toggleLoader,如下所示:

this.searchsubscription = this.searchService.termUpdate$.subscribe(
        (item) => {
            this.searchTerm = item;
            this.toggleLoader(true); //the console is still updated at the correct times with this method
            this.stock = this.search.transform(this.allstock,{query:this.searchTerm})
            this.toggleLoader(false);
        },
        (err) => {console.log(err)}
 );

最小的掠夺者:https://plnkr.co/edit/lD4gZq 注意:在完整的应用程序中,搜索栏不是目录的子组件,这就是搜索词更新通过外部服务进行访问的原因。

我一直在研究变更检测,并尝试解决这个问题一段时间,但老实说,我无法弄清楚为什么这种情况不起作用。任何帮助,将不胜感激。感谢。

0 个答案:

没有答案