skip to Main Content

I have a component that displays dynamic, read-only data. For example:

<div>{{getText()}}</div>

I noticed that getText is being invoked over and over by Angular, even if there is seemingly no need to do so, i.e. no data has changed. How can I detect when Angular triggers view refresh?

2

Answers


  1. You can detect it using the ngDoCheck hook. Which fires during a change detection cycle.

    On each cycle the function gets called and the function is evaluated.

    If you want to improve performance, you can enable ChangeDetectionStrategy.OnPush, which will reduce the number of change detection cycles.

    Angular OnPush Change Detection and Component Design – Avoid Common Pitfalls


    The more easier solution is to evaluate the function and store it in a property which you show in HTML, then you can rerun the function to update the property whenever it will change.

    export class SomeComponent {
    @Input() conditionToUpdateText: string;
    displayProp = ”;

    ngOnInit() {
      this.getText();
    }
    
    getText() {
      this.displayProp = this.conditionToUpdateText === 'hello' ? 'world' : 'asdf';
    }
    
    ngOnChanges() {
        this.getText();
    }
    

    In the above example we set the initial value of displayProp on the ngOnInit hook (during initialization), then since the data is dependent on the inputs, we use the ngOnChanges hook ( when inputs change ) to reevaluate the property. The HTML usage will be:

    {{displayProp}}
    

    Although it is ok for simple functions to fire multiple times during change detection, as a rule of thumb avoid functions since if you accidentally use a costly array operation like find in the HTML binding, it gets called multiple times and causes a drop in performance.

    Login or Signup to reply.
  2. This is expected – on every change detection cycle all expressions in the template are re-evaluated. There is one other approach which is not mentioned in the other answer. You can use Signals instead, which allow fine-grained reactivity and avoids unnecessary computations.

    To give an example:

    export class MyComponent {
      name = input<string>();
      text = computed(() => `Hello ${this.name()}!`);
    }
    

    This example uses the new signal-based input() function and computes a text based on the input value, using a computed function. Here, the computation for the text is only performed if one of the signals inside the computed function changed their value, which avoids unnecessary computations.

    Finally, you can display the text in the template like the following:

    <div>{{ text() }}</div>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search