我写了一个小指令来包装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类以使浮动标签更新。
我想知道是否有更好的方法。我说它的方式对我来说不合适:(