There is a component that encapsulates some library. In order to avoid all this library's event listeners' change detection nightmare, the library is scoped outside the angular zone:
@Component({ ... })
export class TestComponent {
@Output()
emitter = new EventEmitter<void>();
constructor(private ngZone: NgZone) {}
ngOnInit() {
this.ngZone.runOutsideAngular(() => {
// ...
});
}
}
That's all quite clear and common. Now let's add the event to emit the action:
@Component({ ... })
export class TestComponent {
@Output()
emitter = new EventEmitter<void>();
private lib: Lib;
constructor(private ngZone: NgZone) {}
ngOnInit() {
this.ngZone.runOutsideAngular(() => {
this.lib = new Lib();
});
this.lib.on('click', () => {
this.emitter.emit();
});
}
}
Problem is that this emitter does not trigger the change detection because it is triggered outside the zone. What is possible then is to reenter the zone:
@Component({ ... })
export class TestComponent {
@Output()
emitter = new EventEmitter<void>();
private lib: Lib;
constructor(private ngZone: NgZone) {}
ngOnInit() {
this.ngZone.runOutsideAngular(() => {
this.lib = new Lib();
});
this.lib.on('click', () => {
this.ngZone.run(() => this.emitter.emit());
});
}
}
Finally, I come to the question. This this.ngZone.run
is forcing the change detection even if I did not listen to this event in the parent component:
<test-component></test-component>
which is not wanted because, well, I did not subscribe to that event => there is nothing to detect.
What could be the solution to that problem?
For those who is interested in the real-life example, the origin of the question is here.
@Output() emitter = LazyEventEmitter(/* all required properties for creating observable */)
, then it becomes quite clear. – Kigali