出于某种原因退出角度4变化检测

时间:2017-10-13 18:29:22

标签: angular

我写了一个小指令来包装CanadaPost AddressComplete脚本(实际上是一个PostalCodeAnywhere PCA js脚本)。一切似乎都在起作用,除了我没有进行变换检测并且必须手动触发它。我想知道我的代码是否有任何问题,以及是否有更好的方法来解决这个问题。

import { Directive, ElementRef, Renderer, Output, Input, AfterViewInit, EventEmitter } from '@angular/core';
import { NgModel } from '@angular/forms';
import { Address } from './address';

declare var pca: any;

@Directive({
  selector: "[acAddressComplete]",
  providers: [NgModel]
})
export class AddressCompleteDirective implements AfterViewInit {

  @Output() setAddress: EventEmitter<any> = new EventEmitter();
  private addressComplete: any;
  private el: HTMLElement;

  constructor(private element: ElementRef, private model: NgModel, private renderer: Renderer) {
    this.el = element.nativeElement;
  }

  ngAfterViewInit() {
    //id of the input we attach to is set dynamically, so we have to wait till view is initialized
    this.addressComplete = new pca.Address([{ element: this.el.id, mode: pca.fieldMode.SEARCH }],
      {
        key: "xxxx-xxxx-xxxxx-xxxx",
        suppressAutocomplete: true
      });

    this.addressComplete.listen("populate", (address) => {
      this.setAddress.emit(address);
    });
  }

}

所以指令是在地址填充上发出事件。 这是父组件:

    import { Component, EventEmitter, Input, Output, ChangeDetectorRef, ViewChild, ViewChildren, 
             Renderer, ElementRef, QueryList } from '@angular/core';
    import { TranslateService } from '@ngx-translate/core';
    import { SelectItem } from 'primeng/primeng';
    import { Address } from './address';
    import { AddressCompleteDirective } from './address-complete.directive';

    @Component({
        selector: 'address',
        templateUrl: 'address.component.html'
    })
    export class AddressComponent {
        @Input() addressCompleteId: string;
        @ViewChild(AddressCompleteDirective) addressComplete: AddressCompleteDirective;
        @Output() onAddressPopulated = new EventEmitter<Address>();
        @ViewChildren('addressField') addressFields: QueryList<ElementRef>;

        constructor(private renderer: Renderer, private translateService: TranslateService, private ref: ChangeDetectorRef) {
        }

        address = new Address();

        getAddress(address: any) {
            this.addressLabel = address.Label;

            this.address.city = address.City;
            this.address.streetNum = address.BuildingNumber;
            this.address.addressLine = address.Street;
            this.address.unitNum = address.SubBuilding;
            this.address.region = address.Province;
            this.address.postCode = address.PostalCode;

            // we need to do this here as it is out of angular zone for some reason
            // we need both of these to force detection check to run and mark all elements in this cmp
            this.ref.markForCheck();
            this.ref.detectChanges();

            this.addressFields.forEach(element => {
                this.renderer.setElementClass(element.nativeElement, 'ui-state-filled', true);
            });
        }
    }

这是地址完整输入的模板:

<input id={{addressCompleteId}} name="addressComplete" type="text" size="30" pInputText (setAddress)="getAddress($event)" acAddressComplete> 

将填充城市的字段:

<input #addressField name="city" type="text" size="30" [(ngModel)]="address.city" pInputText > 

我也在使用primeng InputText组件。

所以问题在于,除非我强制手动更改检测(参见上面的markForCheck / detectChanges),表格中的值(例如城市)不会立即更新,而是仅在焦点更改(鼠标点击)后更新。而且我还必须手动设置primeng类以使浮动标签更新。

我想知道是否有更好的方法。我说它的方式对我来说不合适:(

0 个答案:

没有答案