Typeahead:如何强制进行变更检测

时间:2018-03-15 07:42:42

标签: ngx-bootstrap

我对 TypeAhead 有疑问,因为我不想污染git space backlog。

我根据异步演示设置了预先输入以使用我自己的observable(我提取谷歌预测数据)和类型工作,但是有刷新(或者更改检测)问题我在键入正确的地址,但突出显示的结果总是一两个字母后面的'在突出显示方面,或者由于搜索可能已经缩小而导致结果丢失。如果我例如向左或向右按​​键,组件会更新,这告诉我必须有一些检测问题。

如果有什么方法我可以强迫它检测变化?我已经尝试在异步后立即运行更改检测器,但这并没有帮助。谢谢堆

这是stackblitz代码 https://stackblitz.com/edit/angular-ufgm4x

要了解我很难理解延迟的位置,请尝试按照以下步骤操作:

  • 快速输入例如' 30曼尼'
  • 等待回复,等一下,让我们说3秒
  • 然后按' k'并且等待并且不要与应用程序交互...等待,然后仅在几秒钟后组件更新(匹配突出显示)。或者按“等”,稍等一下,然后与应用互动,您就会看到突出显示的内容。

这似乎不是谷歌地方查找响应时间,因为它们非常好。必须有别的东西。

这种奇怪的行为在搜索延迟

时特别明显



[typeaheadWaitMs]="1000"






export class TypeaheadComponent {
  asyncSelected: string;
  typeaheadLoading: boolean;
  typeaheadNoResults: boolean;
  dataSource: Observable<any>;

  constructor(private geocoder: GeocodeService,
              private chd: ChangeDetectorRef,
              private zone: NgZone) {
    this.dataSource = Observable.create((observer: any) => {
      // Runs on every search
      observer.next(this.asyncSelected);
    }).mergeMap((token: string) => this.geocoder.getSuggestions(token)).do(() => {
      setTimeout(() => {
          this.chd.detectChanges(); // --> Doesn't do anything
        }, 200);
    });
  }

  changeTypeaheadLoading(e: boolean): void {
    this.typeaheadLoading = e;
  }

  typeaheadOnSelect(e: TypeaheadMatch): void {
    console.log('Selected value: ', e.value);
  }
}
&#13;
&#13;
&#13;

&#13;
&#13;
public getSuggestions(keyword: string): Observable<object> {

    if (typeof google === 'undefined') {
      return new Observable<object>();
    }

    const autocompleter = new google.maps.places.AutocompleteService();
    return new Observable<object>((observer) => {
      // Prepare the callback for the autocomplete
      const onPredictionsReady = (predictions: any[]) => {
        observer.next(predictions || []);
        observer.complete();
      };
      // do the search
      autocompleter.getPlacePredictions({ input: keyword }, onPredictionsReady);
    });
  }
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,这是我如何解决的问题:

我的服务:

import {Injectable} from '@angular/core';
import {MapsAPILoader} from '@agm/core';
import {Observable} from 'rxjs/Rx';
import {} from 'googlemaps';

@Injectable()
export class GooglePlacesService {
  googleAutocompleteService;

  constructor(private mapsAPILoader: MapsAPILoader) {
    this.mapsAPILoader.load().then(() => {
      this.googleAutocompleteService = new google.maps.places.AutocompleteService();
    });
  }

  getPredictions(inputText: string) {
    const callback = this.googleAutocompleteService.getPlacePredictions.bind(this.googleAutocompleteService);

    const observable = Observable.bindCallback(callback, (predictions, status) => {
      if (status !== google.maps.places.PlacesServiceStatus.OK) {
        return [];
      } else {
        return predictions;
      }
    });

    return observable({
      input: inputText
    });
  }
}

我的组件(ts):

import {Component, NgZone, OnInit} from '@angular/core';
import {} from 'googlemaps';
import {Observable} from 'rxjs/Observable';
import AutocompletePrediction = google.maps.places.AutocompletePrediction;
import {GooglePlacesService} from '../../api/google-places.service';

@Component({
  selector: 'search-location-input',
  templateUrl: './search-location-input.component.html',
  styleUrls: ['./search-location-input.component.css']
})
export class SearchLocationInputComponent implements OnInit {
  inputText = '';
  predictions: Observable<AutocompletePrediction[]>;

  constructor(private googlePlacesService: GooglePlacesService,
              private ngZone: NgZone) {
  }

  ngOnInit() {
    this.predictions = Observable.create((observer: any) => {
      this.googlePlacesService.getPredictions(this.inputText)
        .subscribe((result: any) => {
          this.ngZone.run(() => observer.next(result));
        });
    });
  }

}

我的组件(html):

<input [(ngModel)]="inputText"
   [typeahead]="predictions"
   typeaheadOptionField="description"
   [typeaheadWaitMs]="200"
   type="text">