使用observable,我想过滤并显示一个列表 . 仅当用户开始键入时才会触发输入 event
. 因此,列表不会显示在第一位 . 在 inputEvent
开始被触发之前,如何为可观察的 this.filterLocation$
分配默认值?
模板
<ng-template ngFor let-location [ngForOf]="filterLocation$ | async">
<a mat-list-item href="#">{{location}}</a>
</ng-template>
零件
ngAfterViewInit() {
const searchBox = document.querySelector('#search-input');
this.filterLocation$ = fromEvent(searchBox, 'input')
.pipe(
map((e: any) => {
const value = e.target.value;
return value ? this.locations
.filter(l => l.toLowerCase().includes(value.toLowerCase()))
: this.locations;
}),
startWith(this.locations)
)
}
}
使用 startWith
使列表最初显示 . 但抛出以下错误:
错误:ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后发生了变化 . 上一个值:'ngForOf:null' . 当前值:'ngForOf:name1,name2' .
1 回答
初始值可以通过
startWith
运算符提供给observable,因为它已在现在删除的答案中提到 .问题是
filterLocation$
在filterLocation$ | async
被评估为null
之后被分配得太迟了 . 由于更改发生在相同的刻度线上,因此会导致更改检测错误(尽管如果预期会出现ExpressionChangedAfterItHasBeenCheckedError
,则可将其视为警告) .解决方案是在触发更改检测之前将代码从
ngAfterViewInit
移动到ngOnInit
.这并不总是可行的 . 另一种方法是异步提供一个值,因此它不会干扰初始变化检测 .
通过使用
delay
运算符延迟整个observable(用户输入的可接受解决方案,因为它不是时间关键):或者通过使调度程序使初始值异步: