angular - 如何处理 rxjs 和 angular 5 中的 Observables,bootstrap typeahead 实现的问题
问题描述
我正在尝试在角度 5 中实现自动完成(引导输入)。
经过几次代码重构,我得到了迄今为止最好的结果。但是在发出新值(在输入中输入新术语)之后,它出现了这个错误......
TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
at Object.subscribeToResult (subscribeToResult.js:74)
at SwitchMapSubscriber.push../node_modules/rxjs/operators/switchMap.js.SwitchMapSubscriber._innerSub (switchMap.js:103)
at SwitchMapSubscriber.push../node_modules/rxjs/operators/switchMap.js.SwitchMapSubscriber._next (switchMap.js:96)
at SwitchMapSubscriber.push../node_modules/rxjs/Subscriber.js.Subscriber.next (Subscriber.js:90)
at DistinctUntilChangedSubscriber.push../node_modules/rxjs/operators/distinctUntilChanged.js.DistinctUntilChangedSubscriber._next (distinctUntilChanged.js:103)
at DistinctUntilChangedSubscriber.push../node_modules/rxjs/Subscriber.js.Subscriber.next (Subscriber.js:90)
at DebounceTimeSubscriber.push../node_modules/rxjs/operators/debounceTime.js.DebounceTimeSubscriber.debouncedNext (debounceTime.js:98)
at AsyncAction.dispatchNext (debounceTime.js:114)
at AsyncAction.push../node_modules/rxjs/scheduler/AsyncAction.js.AsyncAction._execute (AsyncAction.js:111)
at AsyncAction.push../node_modules/rxjs/scheduler/AsyncAction.js.AsyncAction.execute (AsyncAction.js:86)
这是我的代码:
private searchTerm = new Subject<string>();
public termsArray: any = [];
constructor(private apiService: DataService){
const result$ = this.searchTerm
.debounceTime(100)
.distinctUntilChanged()
.switchMap(term => this.apiService.getSearchTest(term))
.subscribe(result => {
this.termsArray = result.suggestions as Array<any>;
console.log(this.termsArray);
}
, err => console.log(err))
}
autocompleteTest = (text$: Observable<string>) =>
text$.pipe(
debounceTime(300),
distinctUntilChanged(),
map(term => term.length < 1 ? []
: this.termsArray
.filter(v => v.toLowerCase().indexOf(term.toLowerCase()) > -1)
.slice(0, 10))
)
onKeyUpSearch(searchText: string){
if (searchText !== "") this.searchTerm.next(searchText);
}
解决方案
通常你有两件事
private searchTerm = new Subject<string>();
observableSearchTerm=this.searchTerm.asObservable()
您在 searchTerm 上创建“下一个”,但从 observable 订阅
onKeyUpSearch(searchText: string){
if (searchText !== "") this.searchTerm.next(searchText);
}
//But subscribe to the "Observable"
this.observableSearchTerm
.debounceTime(100)
.distinctUntilChanged()
.switchMap(term => this.apiService.getSearchTest(term))
.subscribe(result => {
...
}
注意 1:在 RxJs 6 (Angular 6) 中,您必须使用管道更改代码
this.observableSearchTerm.pipe(
debounceTime(100),
distinctUntilChanged(),
switchMap(term => this.apiService.getSearchTest(term))
).subscribe(result => {
...
}
NOTE2:您可以使用 FromControl 并直接订阅值更改
//In .html
<input type="text" [formControl]="control">
//In .ts
control:FormControl=new FormControl() //Define the control
//..after in ngOnInit
ngOnInit()
{
this.control.valueChanges.pipe(
debounceTime(100),
distinctUntilChanged(),
switchMap(term => this.apiService.getSearchTest(term)
).subscribe(result=>{
....
})
}
推荐阅读
- c++ - 在 C++ 中自动向下转换函数参数
- sql - 在 MS Access VBA 中用户输入的打印页数
- unity3d - Unity .GetParticles() 高 CPU 峰值
- python - 以数组中的某个值为条件
- r - 如何在 ggplot 背景(不是面板)上添加图像?
- typescript - 如何在 Typescript 中动态扩展(添加属性)泛型类作为参数?
- excel-formula - 是否有一个 Excel 公式可以从包含混合数据的列中的最后 25 行中提取数字?
- c# - 将获取datagridvie 中的值的代码缩短到文本框?
- python - 尽管两个查询集在 shell 中打印出相同的结果,但 Django 的 assertQuerysetEqual() 方法还是失败了?
- javascript - 通过从另一个元素查询的类名获取元素