-2

I read the manual of binding object properties in Angular, however I struggle to find the perfect most optimized solution.

Let's say i have a model User

export class User {
  public _id: number;
  public _firstName: string;
  public _lastName: string;
  public _active: boolean;
  public _type: string;

  constructor(id: number, firstName: string, lastName: string, type: string, active: boolean = true) {
    this._id = id;
    this._firstName = firstName;
    this._lastName = lastName;
    this._active = active;
    this._type = type;
  }
}

I want to display ID, firstName and LastName if the user is active and of certain type - let's say administrator. Pretty simple, right?

From what I've read the easiest solution is:

<span *ngIf="model._active && model._type === 'administrator'">{{model._id}} | {{model._firstName}} | {{model._lastName}} | {{model._type}}</span>

You can even pipe this:

<span *ngIf="model._active | isModelActive : model._type">{{model._id}} | {{model._firstName}} | {{model._lastName}} | {{model._type}}</span>

Pipe gets called only once on init, and each time if property "active" changes. Changing the property "id" doesn't call the pipe.

In reality however your models most likely have private fields with accessors, since you want to encapsulate your objects. Now this is when this goes badly really quick.

private _active: boolean;
get active(): boolean {
   console.log('get active');
   return this._active;
}

now binding the getter instead of field causes this function to be called multiple times, plus it also gets called when other properties are changed (like id for example). God forbid if you have (mouseover) somewhere else because it will constantly redraw the view.

You can also pipe this:

<span *ngIf="model.active | isModelActive : model.type">{{model._id}} | {{model._firstName}} | {{model._lastName}} | {{model.type}}</span>

But still changing the property "id" causes the redraw. And if you want to pass the object to the pipe, you have to declare it impure, which according to documentation can cause serious performance degradation.

So which solution is the best? Or maybe there is another one I don't know about. Lemme know.

3
  • angular version? Commented Jan 29 at 10:59
  • pass the whole object as input to pipe and do not make it impure, but you need not to mutate the object if you want to update the object then you will have to make something like this: this.model = { ...this.model, id: newId } as by default pure pipe make memoization if the inputs are the same not changed so by passing the object you need with every change to make new object as it will detect that the refrence of the object changed so will execute the pipe Commented Jan 29 at 12:03
  • Angular CLI: 13.3.10 Ok, so from what I understand you can pass object to pure pipe, but object has to be Immutable -> every edit has to create a new object. Only then new reference is created which can be picked up by a pipe. Commented Jan 29 at 14:17

1 Answer 1

0
  1. Using get method is not slower than field ref, so this should not bother u. If while mouseover this get method will return same result, view wont be redrawn.
  2. Pipe. Pure pipe wont run when you change id, but it will check that pipe inputs did not change each digest cycle. So it wont be faster than ngIf

You should not focus on things above in 99.9999% of cases -- you will never get any measurable performance improvement.

  1. ChangeDetectionStrategy. This is what you missed. If you care about performance you should use ChangeDetectionStrategy.OnPush. E.g. with onPush get-methods, pipes etc. will be called less frequently.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.