1

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

@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...

H3AR7B3A7
  • 4,366
  • 2
  • 14
  • 37
  • There's no Angular specific mechanism to do this – Drenai Jun 20 '22 at 20:01
  • 1
    I don't know if this is what you're looking for, but you can make a variable equal b, but instead of just only doing newvariable = b (this will copy the value so when you click the increment this variable will update the same) but using JSON.stringify when doing this can solve that problem. You can see the full example here [link](https://stackblitz.com/edit/angular-ivy-raqpxb?file=src/app/app.component.ts) and here is an explanaition [link](https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0) – Florencia Cames Jun 20 '22 at 20:28
  • 1
    You can create a component that will show this number and by some trigger (through service or input) you can use `detach()` method from `ChangeDetectorRef`. Once you trigger `detach()` it will be cut off from the changeDetection cycle. – Dmitry S. Jun 20 '22 at 20:48

2 Answers2

3

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.

H3AR7B3A7
  • 4,366
  • 2
  • 14
  • 37
slim
  • 414
  • 1
  • 7
1

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.

H3AR7B3A7
  • 4,366
  • 2
  • 14
  • 37
  • But even if you use these versions, the value of `b` will be updated in the view in the following change detection (e.g. on a second click), so it is just delayed. – slim Jun 20 '22 at 21:03
  • @slim Yes, but why render it in the view if you don't want it to update? What is your use case? Can't you just update a value not bound to the template and then fetch it with a function whenever you DO want/need it? – H3AR7B3A7 Jun 20 '22 at 21:05