Angular async *ngFor 选择后不工作
Angular async *ngFor not working after selection
与 angular 和 observables 作斗争。
我有一个这样的可观察对象:
private searchResults: Observable<any[]>;
我用这样的方式来填充它:
this.searchResults = this.searchTerms.pipe(
map((event: any) => event.target.value),
debounceTime(300),
distinctUntilChanged(),
filter((term: string) => term && term.length >= 3),
flatMap((term: string) => this.http.get<any[]>(`https://my-cool-rest.api/${term}`))
)
(注意:searchTerms 是 Subject<string>()
并在 html 上实现,例如:<input type="text" (keyup)="searchTerms.next($event)"/>
)
目前一切正常,一切正常。
当我收到结果时,我会在一个简单的 UL 中显示它们
<ul>
<li *ngFor="let result of searchResults | async">
<a (click)="selectItem(result.id)>{{ result.name }}</a>
</li>
</ul>
点击一个项目将调用 selectItem
函数,将结果写入控制台并清除 searchResults
:
selectItem(result: string) {
if (result) {
console.log(result);
this.searchResults = Observable.of([]);
}
}
再一次,一切正常。
但是如果我重复这个过程来搜索其他关键字,*ngFor
不再显示结果。
为了完全安全,我订阅了 searchResults
(例如:在构造函数中)以记录它
constructor() {
this.searchResults.subscribe(data => console.log(data));
}
你猜怎么着?很有魅力
我想这是我不理解的 angular (5+) 行为。
提前致谢!
正如 undefined 用户所指出的,您正在用这一行覆盖流:
this.searchResults = Observable.of([]);
所以如果你想重置数组,你有两个选择:
- 将 "search" 输入设置为空字符串,但我会触发另一个请求
- 利用 observables 和流组合
我认为第二个想法更好,以下是实施方法:
import { merge } from 'rxjs/observable/merge';
import { mapTo } from 'rxjs/operators';
private searchResults: Observable<any[]>;
private resetResults$ = new Subject();
this.searchResults = merge(
// every time the reset stream receive a new value,
// merge it into the searchResults and no matter what
// the value is merge an empty array
resetResults$.pipe(mapTo([])),
this.searchTerms.pipe(
map((event: any) => event.target.value),
debounceTime(300),
distinctUntilChanged(),
filter((term: string) => term && term.length >= 3),
flatMap((term: string) => this.http.get<any[]>(`https://my-cool-rest.api/${term}`))
)
)
selectItem(result: string) {
if (result) {
// send a new value to the reset stream
this.resetResults$.next();
}
}
与 angular 和 observables 作斗争。
我有一个这样的可观察对象:
private searchResults: Observable<any[]>;
我用这样的方式来填充它:
this.searchResults = this.searchTerms.pipe(
map((event: any) => event.target.value),
debounceTime(300),
distinctUntilChanged(),
filter((term: string) => term && term.length >= 3),
flatMap((term: string) => this.http.get<any[]>(`https://my-cool-rest.api/${term}`))
)
(注意:searchTerms 是 Subject<string>()
并在 html 上实现,例如:<input type="text" (keyup)="searchTerms.next($event)"/>
)
目前一切正常,一切正常。
当我收到结果时,我会在一个简单的 UL 中显示它们
<ul>
<li *ngFor="let result of searchResults | async">
<a (click)="selectItem(result.id)>{{ result.name }}</a>
</li>
</ul>
点击一个项目将调用 selectItem
函数,将结果写入控制台并清除 searchResults
:
selectItem(result: string) {
if (result) {
console.log(result);
this.searchResults = Observable.of([]);
}
}
再一次,一切正常。
但是如果我重复这个过程来搜索其他关键字,*ngFor
不再显示结果。
为了完全安全,我订阅了 searchResults
(例如:在构造函数中)以记录它
constructor() {
this.searchResults.subscribe(data => console.log(data));
}
你猜怎么着?很有魅力
我想这是我不理解的 angular (5+) 行为。
提前致谢!
正如 undefined 用户所指出的,您正在用这一行覆盖流:
this.searchResults = Observable.of([]);
所以如果你想重置数组,你有两个选择:
- 将 "search" 输入设置为空字符串,但我会触发另一个请求
- 利用 observables 和流组合
我认为第二个想法更好,以下是实施方法:
import { merge } from 'rxjs/observable/merge';
import { mapTo } from 'rxjs/operators';
private searchResults: Observable<any[]>;
private resetResults$ = new Subject();
this.searchResults = merge(
// every time the reset stream receive a new value,
// merge it into the searchResults and no matter what
// the value is merge an empty array
resetResults$.pipe(mapTo([])),
this.searchTerms.pipe(
map((event: any) => event.target.value),
debounceTime(300),
distinctUntilChanged(),
filter((term: string) => term && term.length >= 3),
flatMap((term: string) => this.http.get<any[]>(`https://my-cool-rest.api/${term}`))
)
)
selectItem(result: string) {
if (result) {
// send a new value to the reset stream
this.resetResults$.next();
}
}