'Angular 5 - how to limit change detection only to component scope?

How to configure Angular component not to trigger change detection for the whole application but only for the component itself and his children?

Working example: https://stackblitz.com/edit/angular-irc-starter-4txpbu?file=app%2Ftimer%2Ftimer.component.ts

There is a counter that increases value by one every second. It's TimerComponent and it's working as intended - value is increased and updated every second.

@Component({
  selector: 'app-timer',
  template: `{{value}}`
})
export class TimerComponent implements OnInit {
  value: number = 0;
  ngOnInit() {
    setInterval(() => this.value++, 1000);
  }
}

However, look at the parent component AppComponent.

<h3>Internal timer:</h3>
<p>Should not perform change detection for the whole app</p>
<app-timer></app-timer>

<h3>External binding</h3>
<p>Should not be updated after timer changes</p>
<p>{{someBindingProperty}}</p>

someBindingProperty is a getter:

get someBindingProperty() {
  this.bindingTimer++;
  return this.bindingTimer;
}

The problem: when TimerComponent increases value, change detection is triggered for the whole application. Is it possible to trigger change detection only within the component and children?

Note: if I add to TimerComponent:

changeDetection: ChangeDetectionStrategy.OnPush

Then changes are not detected within this component but change detection is still triggered for the whole application. So this is not a solution.



Solution 1:[1]

Another option to temporary disable change detection ChangeDetectorRef

enabled = true;  
constructor(private ref: ChangeDetectorRef)

toggleChangeDetection() {
  if (this.enabled) 
  {
    this.enabled = false;
    this.ref.detach();
  }
  else {
    this.enabled = true;
    this.ref.reattach();
}

Solution 2:[2]

You can run the interval for you timer outside of the angular zone and call ChangeDetectorRef.detectChanges everytime the timer value increases:

this.ngZone.runOutsideAngular(() => {
  setInterval(() => {
    this.timer++;
    this.cdr.detectChanges();
  }, 1000);
});

ChangeDetectorRef.detectChanges only detects changes for this view and its children.

I tried it out and using the Angular DevTools profiler you can see that neither the root component (AppComponent), nor the sibling component (SthWithDefaultCdComponent) got checked. Whether the timer component uses OnPush strategy or not does not make a difference.

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 parag badala
Solution 2 slim