Javascript 角度2指令事件输出中的更改检测不工作
我使用这个指令。但是,在setAddress事件输出上,在我的组件中未检测到任何更改。视图未更新。我不明白 对于测试,如果我删除google.maps.event.addListener以替换为调用invokeEvent的简单setTimeout。它起作用了Javascript 角度2指令事件输出中的更改检测不工作,javascript,angular,events,directive,Javascript,Angular,Events,Directive,我使用这个指令。但是,在setAddress事件输出上,在我的组件中未检测到任何更改。视图未更新。我不明白 对于测试,如果我删除google.maps.event.addListener以替换为调用invokeEvent的简单setTimeout。它起作用了 @Directive({ selector: '[googleplace]', providers: [NgModel], host: { '(input)' : 'onInputChange()' } }) exp
@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() {
}
}
place\u 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
});
另一种可能的解决方案是注入
ApplicationRef
并调用tick()
方法来运行更改检测周期:
export class GoogleplaceDirective {
constructor(private app: ApplicationRef, ...) {
...
}
invokeEvent(place:Object) {
this.setAddress.emit(place);
this.app.tick(); <-----------------------------------
}
杰出的Thankssince事件发射器更新父组件上的值,而不管它运行在哪个区域,另一种方法可以是只注入
app:ApplicationRef
,然后调用app.tick()
,如果在父组件上更新时会初始化某些内容,那么在下一个操作中可能会出错。您必须运行detectChanges或勾选again@yurzui,很有趣,你可以创建一个plunker来显示它吗?这就是为什么angular包含这个.zone。运行订阅Сhoose,然后单击将地址更改为dd
按钮。然后强制updateSee zone primer当安排异步工作时,回调函数将在调用异步API时存在的区域所在的同一区域中执行。这允许跨多个异步调用跟踪区域。
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
});
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();
});
}
});