как установить время отката для вызова автозаполнения Google Map API вызова из Angular6 - PullRequest
0 голосов
/ 11 февраля 2019

Я сделал пользовательскую директиву для использования функции автозаполнения API Google и пытаюсь уменьшить количество вызовов API для Google для Вот мой код.

Пожалуйста, предложите мне что-то, чтобы установить видзадержки для меньшего вызова API на сервер Google для ввода автозавершения функции

этот код вызывает ввод API на букву, я хочу сделать это через 4-5 секунд или после ввода слова

//Google-place-directive.ts

import {
  Directive,
  ElementRef,
  OnInit,
  Output,
  EventEmitter
} from "@angular/core";

declare var google: any;

@Directive({
  selector: "[google-place]"
})
export class GooglePlacesDirective implements OnInit {
  @Output() onSelect: EventEmitter<any> = new EventEmitter();
  private element: HTMLInputElement;

  constructor(elRef: ElementRef) {
    //elRef will get a reference to the element where
    //the directive is placed
    this.element = elRef.nativeElement;
  }

  getFormattedAddress(place) {
    //@params: place - Google Autocomplete place object
    //@returns: location_obj - An address object in human readable format
    let location_obj = {};
    console.log(place);
    console.log(place.geometry.location.lat());
    console.log(place.geometry.location.lng());
    for (let i in place.address_components) {
      let item = place.address_components[i];

      location_obj["formatted_address"] = place.formatted_address;
      if (item["types"].indexOf("locality") > -1) {
        location_obj["locality"] = item["long_name"];
      } else if (item["types"].indexOf("administrative_area_level_1") > -1) {
        location_obj["admin_area_l1"] = item["short_name"];
      } else if (item["types"].indexOf("street_number") > -1) {
        location_obj["street_number"] = item["short_name"];
      } else if (item["types"].indexOf("route") > -1) {
        location_obj["route"] = item["long_name"];
      } else if (item["types"].indexOf("country") > -1) {
        location_obj["country"] = item["long_name"];
      } else if (item["types"].indexOf("postal_code") > -1) {
        location_obj["postal_code"] = item["short_name"];
      }
    }
    return location_obj;
  }

  ngOnInit() {
    const autocomplete = new google.maps.places.Autocomplete(this.element);
    //Event listener to monitor place changes in the input
    google.maps.event.addListener(autocomplete, "place_changed", () => {
      //Emit the new address object for the updated place
      this.onSelect.emit(this.getFormattedAddress(autocomplete.getPlace()));
    });
  }
}

// html похож на

 <input
                type="text"
                class="google-place-input"
                google-place
                (onSelect)="setAddress($event)"
                placeholder="Type to search.."
              />

Заранее спасибо

1 Ответ

0 голосов
/ 11 февраля 2019

Создайте Observable из события и затем примените debounceTime оператор

import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';

//create observable that emits 'place_changed' events
const source = fromEvent(autocomplete, 'place_changed');

//map to string with given event timestamp
const example = source.pipe(debounceTime(4000));

const subscribe = example.subscribe(val => console.log(val));

Кстати, 4-5 сек - это слишком много.Время отката - это время после последнего нажатия клавиши.

UPDATE # 1

Попробуйте добавить следующую директиву в поле ввода, где пользователь вводит свой запрос

debounce-time.directive.ts

import {AfterViewInit, Directive, ElementRef, forwardRef, Input, OnDestroy, Renderer2} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
import {fromEvent, Subject} from 'rxjs';
import {debounceTime, takeUntil} from 'rxjs/operators';

// tslint:disable:directive-selector
@Directive({
  selector: '[debounceTime]',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => DebounceTimeDirective),
    multi: true
  }]
})
export class DebounceTimeDirective extends Destroyable implements ControlValueAccessor, AfterViewInit, OnDestroy {
  protected destroyed$ = new Subject<boolean>();

  @Input()
  debounceTime: number;

  onChange = (_) => {};
  onTouched = () => {};

  constructor(private _elementRef: ElementRef, private renderer: Renderer2) {
    super();
  }

  ngAfterViewInit() {
    fromEvent(this._elementRef.nativeElement, 'keyup')
      .pipe(
        takeUntil(this.destroyed$),
        debounceTime(this.debounceTime)
      )
      .subscribe((event: any) => {
        this.onChange(event.target.value);
      });
  }

  ngOnDestroy(): void {
    this.destroyed$.next(true);
    this.destroyed$.complete();
  }

  writeValue(value: any): void {
    const normalizedValue = value === null || value === undefined ? '' : value;
    this.renderer.setProperty(this._elementRef.nativeElement, 'value', normalizedValue);
  }

  registerOnChange(fn: () => any): void { this.onChange = fn; }
  registerOnTouched(fn: () => any): void { this.onTouched = fn; }
}

your-template.html

<input [debounceTime]="4000" ... />
...