Angular 2 中的指令事件输出中的更改检测不起作用
Change Detect not working in directive event ouput in Angular 2
我使用这个指令。但是,在 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;
}
place_changed
的处理程序 运行 在 angular 区域之外。您需要 运行 像这样:
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(); <-----------------------------------
}
这基本上就是区域正在做的事情:
_this._zone.onMicrotaskEmpty.subscribe({
next: function () {
_this._zone.run(function () {
_this.tick();
});
}
});
我使用这个指令。但是,在 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;
}
place_changed
的处理程序 运行 在 angular 区域之外。您需要 运行 像这样:
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(); <-----------------------------------
}
这基本上就是区域正在做的事情:
_this._zone.onMicrotaskEmpty.subscribe({
next: function () {
_this._zone.run(function () {
_this.tick();
});
}
});