Home > Back-end >  How can i cut away change detecion and prevent rerender by a simple class variable in Angular?
How can i cut away change detecion and prevent rerender by a simple class variable in Angular?

Time:06-21

I made a very simple demo app to explain what i want exatly to do.

    import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
a=1
b=2

increase(){
  this.a  
  this.b  
}
}

template:

<p>{{ a }}</p>
<p>{{ b }}</p>
<button type="button" (click)="increase()">Increase</button>

How can i achive it to when i click on increase button on display "variable a" change but "variable b" not.I mean just on the display...

CodePudding user response:

Make b private and use a different variable bDisplay for the template binding. Then you can keep track of the value of b and update the view by updating bDisplay whenever you need it.

Apart from that, I do not see any solution. Angulars goal is to keep model and view in sync, so you cannot get around having the view updated at some point if the bound value changes.

In your example there actually is a way to not update b in the view on the first button click (but it will make up for it on the second click): Use ChangeDetectionStrategy.OnPush in the component and increase the value of b inside a setTimeout:

increase(): void {
  this.a  ;
  setTimeout(() => {
    this.b  ;
  });
}

a will be updated in the view, because the click triggers a change detection cycle and marks the component to be checked for changes. Afterwards, setTimeout will elapse, which triggers a new CD cycle, but does not mark the component to be checked, so b will not be updated in the view. But with the next click, a will again be updated and b will be updated in the view to the value from the first click.

CodePudding user response:

What slim says is right. You basically have 2 options. One is changing Change Detection Strategy as he mentioned. The other is running it outside angular.

Change Detection Strategy OnPush

Use OnPush instead off default Change Detecton Strategy, like this:

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent {
  /* ... */
  increase() {
    this.a  
    this._ngZone.runOutsideAngular(() => {
      setTimeout(() => {
        this.b  ;
      });
    })
  }
}

NgZone

Or (if you don't want to switch to OnPush), you can run it outside of angular:

constructor(private _ngZone: NgZone) {}

increase() {
  this.a  
  this._ngZone.runOutsideAngular(() => {
    setTimeout(() => {
      this.b  ;
    });
  })
}

Here's an example on Stackblitz.

  • Related