【发布时间】:2017-08-15 02:22:05
【问题描述】:
我正在开发一个使用 Ng-Bootstrap 的 typeahead directive 的 Angular 4 应用程序。在 Wikipedia 示例中,他们对 Wikipedia 进行 api 调用,并在 typeahead 框中显示结果。我正在尝试做同样的事情,但使用 Google Map 的地点自动完成服务。
按照 Wikipedia 示例,我创建了一个类似的服务,它返回一个包含自动完成位置的 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
按任意键或单击屏幕上的任意位置都会立即纠正它,但我不知道如何在第一次纠正它。
根据我的研究,Google 地图位置自动完成服务在 NgZone 之外运行并且没有触发重绘似乎是一个问题,但我没有任何常用策略来手动强制重绘(ApplicationRef.tick()、NgZone.run()、ChangeDetectorRef.detectChanges())。
任何建议将不胜感激!
编辑:具有类似行为的 Plunker: https://embed.plnkr.co/iy2Zhd5rEhBK2aVbBqsB/
【问题讨论】:
-
通常
NgZone.run()应该可以解决问题。您能否整理一个能重现该问题的 plunker,以便我们查看一下? -
你会推荐在哪里执行 NgZone.run()?
-
在调用外部 API(谷歌地图)的地方。再一次,有一个带有重现场景的 plunker 会让我们更快地找到答案:-)
-
所以我在 plunker 中得到了几乎完全相同的行为,除了预先输入在事件之前没有对齐,它只是直到事件才出现。尝试键入一个字符,等待一秒钟,然后按 shift 键之类的东西。预输入仅在那时出现。 embed.plnkr.co/iy2Zhd5rEhBK2aVbBqsB
标签: twitter-bootstrap angular google-maps-api-3 rxjs ng-bootstrap