我正在尝试设置可以搜索的项目目录。我的目录组件有一些对 observables 的订阅。每当更新搜索词时,它都会将该查询应用于项目列表并返回匹配的项目。搜索功能位于一个单独的组件中,该组件执行过滤并向 searchService 发送一个值以指示它何时开始和停止搜索。我想通过单独的加载程序订阅来利用此值更改,并更新“isLoading”布尔值以在搜索功能运行时显示微调器。
目录.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,当返回新的股票数组并且 ngfor 更新时为 false)。视图中没有检测到更改。但是,我的 toggleLoader 调试按钮将正确更新视图。
我已经尝试了许多类似问题中发布的解决方案,例如将 toggleLoader 的主体包装在 zone.run() 中或使用 ChangeDetectorRef 手动调用更改检测。我什至可以尝试不使用 loadsubscription,而是在调用 search.transform 之前调用 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 注意:在完整的应用程序中,搜索栏不是目录的子组件,这就是为什么搜索词更新要通过外部服务进行。
我一直在研究变更检测并试图解决这个问题一段时间,但老实说我无法弄清楚为什么这不起作用。任何帮助,将不胜感激。谢谢。