更改检测在Angular 2

时间:2017-05-20 12:55:57

标签: javascript angular events directive

我使用此指令。但是,在setAddress事件输出中,我的组件中未检测到任何更改。视图未更新。我不明白。

对于测试,如果我删除google.maps.event.addListener以替换为简单的setTimeout来调用invokeEvent。它有效。

@Directive({
  selector: '[googleplace]',
  providers: [NgModel],
  host: {
    '(input)' : 'onInputChange()'
  }
})
export class GoogleplaceDirective  {
  @Output() setAddress: EventEmitter<any> = new EventEmitter();
  modelValue:any;
  autocomplete:any;
  private _el:HTMLElement;


  constructor(el: ElementRef,private model:NgModel) {
    this._el = el.nativeElement;
    this.modelValue = this.model;
    var input = this._el;
    this.autocomplete = new google.maps.places.Autocomplete(input, {});
    google.maps.event.addListener(this.autocomplete, 'place_changed', ()=> {
      var place = this.autocomplete.getPlace();
      this.invokeEvent(place);
    });
  }

  invokeEvent(place:Object) {
    this.setAddress.emit(place);
  }


  onInputChange() {
  }
}

在我的组件视图中

<input type="text" class="validation-address-input" style="margin-top: 100px;" [value]="form.customerAddress"
               (setAddress)="setCustomStartLocation($event)" googleplace>

在我的组件中

/**
     *
     * @param place
     */
    setCustomStartLocation(place: Object) {
        this.currentStep = 2;
    }

2 个答案:

答案 0 :(得分:3)

place_changed的处理程序在角度区域外运行。你需要像这样运行它:

constructor(..., private zone: NgZone) {
  ...
  google.maps.event.addListener(this.autocomplete, 'place_changed', ()=> {
    var place = this.autocomplete.getPlace();
    this.zone.run(() => this.invokeEvent(place)); // run inside angular zone
  });

答案 1 :(得分:0)

另一种可能的解决方案是注入ApplicationRef并调用tick()方法来运行更改检测周期:

export class GoogleplaceDirective  {

  constructor(private app: ApplicationRef, ...) {
    ...
  }

  invokeEvent(place:Object) {
    this.setAddress.emit(place);
    this.app.tick(); <-----------------------------------
  }

这实际上是区域正在做的事情:

_this._zone.onMicrotaskEmpty.subscribe({
    next: function () {
        _this._zone.run(function () {
            _this.tick();
        });
    }
});