我正在开发一个使用Ng-Bootstrap typeahead directive的Angular 4应用程序。在Wikipedia示例中,他们对Wikipedia进行api调用,并在typeahead框中显示结果。我试图做同样的事情,而是使用谷歌地图自动完成服务。
按照维基百科的例子,我创建了一个类似的服务,它返回一个包含自动完成位置的Rxjs Observable。
search(term: string) {
if (term === '') {
return Observable.of([]);
}
return Observable.create(observer => {
this.autocompleteService.getPlacePredictions({ input: term }, (results, status) => {
if (status == google.maps.places.PlacesServiceStatus.OK) {
observer.next(results.map(result => result.description));
observer.complete();
} else {
console.log('Error - ', results, ' & Status - ', status);
observer.next({});
observer.complete();
}
});
});
}
在控制器端,我的代码如下所示:
search = (text$: Observable<string>) =>
text$
.debounceTime(300)
.distinctUntilChanged()
.switchMap(term =>
this.service.search(term)
.do(() => this.searchFailed = false)
.catch(() => {
this.searchFailed = true;
return Observable.of([]);
}))
这种方法效果很好,但由于某种原因,预输条显示在错误的位置,直到某些内容触发重绘。
Note the gap between the input field and the typeahead on the top image
按任意键或点击屏幕上的任意位置即可立即纠正,但我无法在第一时间弄清楚如何更正。
根据我的研究,似乎可能是谷歌地图自动完成服务在NgZone之外运行并且不会触发重绘的问题,但是我对任何通常的手动强制策略都没有运气重绘(ApplicationRef.tick(),NgZone.run(),ChangeDetectorRef.detectChanges())。
任何建议都将不胜感激!
编辑:具有类似行为的Plunker: https://embed.plnkr.co/iy2Zhd5rEhBK2aVbBqsB/
答案 0 :(得分:1)
我明白了! NgZone最终做了这个伎俩,但我不得不将放在回调中,而不是把它包起来。
search(term: string) {
if (term === '') {
return Observable.of([]);
}
let result = Observable.create(observer => {
this.autocompleteService.getPlacePredictions({ input: term }, (results, status) => {
this.ngZone.run(() => {
if (status == google.maps.places.PlacesServiceStatus.OK) {
observer.next(results.map(result => result.description));
observer.complete();
} else {
console.log('Error - ', results, ' & Status - ', status);
observer.next({});
observer.complete();
}
});
});
});
return result;
}