4

In the following example, the

  • first expression {{ bar }} is never updated, but the
  • second expression {{ "" + bar }} is updated:

e.g.

two
1588950994873

Why is this the case?

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

@Component({
  selector: "my-app",
  template: `
    What is different and why?
    <br />
    {{ bar }} <br />
    {{ "" + bar }} <br />
  `
})
export class AppComponent {
  value: string = "default";

  bar: any = d => {
    this.value = d;
  };

  ngOnInit() {
    this.bar.valueOf = () => this.value;
    this.bar("one");
    setInterval(() => this.bar(Date.now() + ""), 1000);
    this.bar("two");
  }
}

Stackblitz example

TmTron
  • 17,012
  • 10
  • 94
  • 142
Log in
  • 65
  • 6
  • 1
    Just a theory (that brings no light to this behavior): angular handles different a simple expression when it just has to dereference a variable and when it has to calculate the value it's gonna show inside the curly braces. – julianobrasil May 08 '20 at 15:31

1 Answers1

3

The reason why is that angular change detection works by comparing the instance of an expression:

  • {{ bar }}: the instance bar never changes - you assign a function to this class member and you never reassign it - so every change detection cycle will see that bar is still the same instance and does not update it (i.e. since the instance is the same, we don't even ask for the value)
  • {{ "" + bar }}: in every change detection cycle the expression "" + bar will be evaluated. When this string concatenation is evaluated, we must get the value of bar which will be updated by your timer. So the result of the string concatenation will always be a new string-instance and thus the change detection will update the view.
TmTron
  • 17,012
  • 10
  • 94
  • 142
  • why {{bar}} is 'two' , not 'one' or 'default'? – Log in May 08 '20 at 15:50
  • 2
    the view is not updated before `ngOnInit` is done - so the last assignment "wins". Check the [life-cycle docs](https://angular.io/guide/lifecycle-hooks) – TmTron May 08 '20 at 15:51