2

I have come across below example in Angular 2 documentation

@Component({
  selector: 'cmp',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `Number of ticks: {{numberOfTicks}}`
})
class Cmp {
  numberOfTicks = 0;
  constructor(ref: ChangeDetectorRef) {
    setInterval(() => {
      this.numberOfTicks ++
     // the following is required, otherwise the view will not be updated
     this.ref.markForCheck();
    }, 1000);
  }
}

As mentioned above , when changeDetection is to ChangeDetectionStrategy.OnPush , the view gets updated only when "this.ref.markForCheck();" is invoked.

Can any one please explain the importance of markForCheck() method here.

refactor
  • 13,954
  • 24
  • 68
  • 103
  • For the above component I also added a button with click event handler, My expection was, when user clicks the button , change detection will happen , and the view will be updated with latest numberOfTicks, but even now view is updated only when markForCheck is called in test() function . hope my question makes sense .. – refactor Mar 23 '17 at 18:07

2 Answers2

3

With ChangeDetectionStrategy.OnPush Angular runs change detection, when in @Input() was updated, a DOM event Angular listens to was received, or the async pipe (| async) received a new value.

If you for example subscribe to an observable from a service and update the status of the component, bindings to this status won't be updated, because this is not covered by above list. If you call this.ref.markForCheck() you tell Angular that it should run change detection because there actually are changes that need to be updated (that's also what the async pipe does).

Other cases are if you explicitly (this.zone.runOutsideAngular()) or for some other reasons code runs outside Angulars zone modifies the status of the component, this also won't be covered (even when the code is an event handler).

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • For the above component I also added a button with click event handler, My expection was, when user clicks the button , change detection will happen , and the view will be updated with latest numberOfTicks, but even now view is updated only when markForCheck is called in test() function . hope my question makes sense .. – refactor Mar 23 '17 at 18:09
  • I was sure an event binding causes change detection to run. Can you create a Plunker to reproduce and investigate? See also http://stackoverflow.com/questions/35386822/changedetectionstrategy-onpush-and-observable-subscribe-in-angular-2 – Günter Zöchbauer Mar 23 '17 at 18:17
  • Glad to hear, was starting to get worried ;-) – Günter Zöchbauer Mar 23 '17 at 18:33
1

Using ChangeDetectionStrategy.OnPush tells Angular not to perform change detection on your component (i.e. updating its view) unless one or more of the component's inputs has changed (these inputs should be immutable objects).

For any events that come from within the component itself and require the view to be updated, you have to explicitly tell the change detector to look for changes in that component on its next change detection run.

In this snippet, ref is a reference to the change detector. Calling ref.markForCheck() tells the change detector that something has happened that will change the view (i.e. numberOfTicks has been incremented) and it needs to recompute it.

Ben Elliott
  • 1,650
  • 14
  • 18