Ng-Bootstrap Typeahead不正确的样式与谷歌地图放置自动完成

时间:2017-08-15 02:22:05

标签: twitter-bootstrap angular google-maps-api-3 rxjs ng-bootstrap

我正在开发一个使用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/

1 个答案:

答案 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;
}