Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular : How to use app.tick() ? Can anyone give me an example of ApplicationRef.tick()?

Tags:

angular

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.

like image 695
Aditya Shukla Avatar asked Oct 17 '17 17:10

Aditya Shukla


2 Answers

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....
  }
}
like image 196
Günter Zöchbauer Avatar answered Nov 04 '22 23:11

Günter Zöchbauer


First of all what is ApplicationRef?

Application Ref contains reference to the root view and can be used to manually run change detection using tick function.

So how do we use the 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.

like image 44
Fmerco Avatar answered Nov 04 '22 22:11

Fmerco