Ricardo Rocha
Ricardo Rocha

Reputation: 16206

Using setters and getter variables on HTML (angular component)

I created a simple angular component to test the usage of a variable that uses a getter/setter style:

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  _name = 'Variable Example';
  get name(): string {
    console.log("GET!!!");
    return this._name;
  }

  set name(value:string): void {
    this._name = value;
  }
}

Then, I use this variable on the html:

<p>
  {{ name }}
</p>

What I noticed is that the get name() is called 4 times (check live in here)

There is any best practices rules which points out that getter and setters shouldn't be used on html components? Will I have performance issues using this approach?

Thank you!

PS: This is not the real scenario, it just a small example of what I'm doing.

Upvotes: 13

Views: 18652

Answers (2)

waterplea
waterplea

Reputation: 3631

UPDATE: Now with Signals this discussion is finally definitively over. Use computed in place of getters and signal inputs and you are guaranteed to have good performance and declarative code. My answer below is still relevant for when you cannot use signals for some reason like old Angular version, no time to refactor or function calls that take arguments from template.

Here are my rule of thumbs that served me very well:

  1. Always use OnPush change detection strategy to avoid unnecessary checks

  2. Always use immutable data, update entire array/object on any change. Google immutability if you are not familiar with it, it is very helpful and a must for OnPush.

  3. Never store states that can be calculated. If it can be computed using say component @Inputs - go for a getter. Computing a simple getter with math or going through a small array is very fast and it saves you the trouble of syncing states. I did benchmarking in Firefox, a simple getter going over a 100 elements array executes 7 million times per second. Generally, getters will not be bottle necks of your app and they are much easier to work with, instead of updating states in lifecycle hooks. But read further.

  4. If your computed state produces a new array or object - always use pure pipe to avoid unnecessary recalculation as it is a much heavier operation and is not suitable for getter.

  5. If your getter is not going to change - consider lazy initialization pattern: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get#Smart_self-overwriting_lazy_getters

  6. Avoid ngOnChange in favor of setters on @Inputs - this way your changes propagate more "directly". Something changed - related stuff is updated, instead of "side effecting" it to some hook to be called later. Unless you need to react to multiple inputs changed at the same time.

NOTICE: These are just my thought on the matter that I've developed over a couple of years of working with Angular on complex projects.

You can read more on declarative approach in writing Angular code in this article I wrote: https://indepth.dev/compliant-components-declarative-approach-in-angular/

Upvotes: 29

ukn
ukn

Reputation: 1793

You should avoid calling methods/getter from your template because the method will be called every time change detection runs.

Instead you should compute whatever you want inside something like ngOnInit and assign it to a variable or use a pipe.

If you want to compute every time your value changes, you should use a pipe since it would be called only when input values change and not every time the change detection runs.

Upvotes: 12

Related Questions