[In short] you need to change one line in your current code
onClick() {
this._ngZone.runOutsideAngular(() => {
setTimeout(()=>this.num = 2,0); // instead of this.num = 2;
}}));
}
now if you click the on the <button>
, this.num
will become 2
, but you won't see any change in the UI (a temporary inconsistency between view and model)
[Explanation] without runOutsideAngular()
, async functions like addEventListener()
or setTimeout()
behaves differently (monkey patched). their callbacks will try to update UI with Angular after running user's code.
For example, you can treat (click)="onClick()"
as:
addEventListener("click",function modifiedCallback(){
onClick();
updateUIifModelChanges(); //call to Angular
})
In order to not triggered UI update we need to satisfy the following two conditions:
- not modify model in function
onClick
(so, modify inside setTimeout()
)
- when the model is indeed modified, do not invoke
updateUIifModelChanges
(call setTimeout()
inside runOutsideAngular
)
[More] of cause, the explanation I gave is a very very...simplified version of what happens. setTimeout()
has the same function signature whether it's running inside runOutsideAngular()
or not. The reason that it behaves differently is because it's running in a different Zone