When we talk about Change Detection mechanism in Angular 2, everyone suggests using NgZone
or ChangeDetectorRef
.
Is there any working example of application.tick()
/ApplicationRef.tick()
which also does the same thing as ChangeDetectorRef
/NgZone
.
Second question: API says, in DEV MODE, ApplicationRef.tick()
runs the change detection more than once.
Is there a way to run it only once. Because the moment I use this method, I get an error saying
ApplicationRef.tick() is called recursively
Similar example of the problem I face using tick() is here in this Github Link
I have gone through Triggering Change Detection Manually Question.
Any info in this appreciated. Thanks.
ApplicationRef.tick()
calls setTimeout((){})
You should only need this when code that runs outside Angulars zone updates Angulars model and Angular therefore can't get notified about the change by NgZone
.
It just invokes change detection for the whole application.
Usually it's better wrapping the code that updates the model from the outside with zone.run(() => {...})
than using ApplicationRef.tick()
ChangeDetectorRef.detectChanges()
or ChangeDetectorRef.markForCheck()
act only on a specific element (and its descendants).
To clarify for a comment below how to get zone
:
class MyComponent {
constructor(private zone:NgZone) {}
foo() {
...
this.zone....
}
}
Application Ref contains reference to the root view and can be used to manually run change detection using tick function.
tick()
function?Inject it into your component constructor and use it as you wish!
N.B. I purposely entered the ChangeDetectionStrategy.OnPush to remove the automatic update, so we should force the application to update manually.
In this regard we will use Tick()
function !
SIMPLE TEST CASE:
component.ts
@Component ({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
...
counter = 1;
constructor (private appRef: ApplicationRef) {
setInterval (() => this.counter ++, 1000);
}
updateApplication () {
this.appRef.tick ();
}
}
component.html
<h1>{{counter}}</h1>
<button (click)="updateApplication()"> UPDATE APP </button>
In my example every time we click on the UPDATE APP button we call the tick()
function which updates every single child component starting from the application root.
So in our case it will simply update the counter variable.
Stackblitz Test Case
As for your second question, if you can avoid having the tick()
called twice in devMode
the answer is You can't avoid it!
But I don't think this behavior leads to a recursive call, most likely you have used the function incorrectly, grafting components that call the tick()
or not disabling the changeDetection so as to start two or more changeDetects together.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With