Search code examples
angulargetter-setter

Angular: Using setter vs Using ngModelChange to update another field (binding to getter, setter are bad in angular world?)


I have two fields - an html select control and a text input control. Upon selecting an option in select control, the text input should be cleared and updated with a default value (user can still edit it though).

There are two ways to do this -

a. Using setter & getter

<select [(ngModel)]="selectedItem ">
    <option value="one">One</option>
     ...
</select>
<input [(ngModel)]="textValue">   
textValue: string;
get selectedItem(): string {
   return _selectedItem;
}
set selectedItem(value: string) {
   this._selectedItem = value;
   this.textValue = some-default-value;
}

b. Using ngModelChange

<select [(ngModel)]="selectedItem " (ngModelChange)="onSelectionChange($event)">
    <option value="one">One</option>
     ...
</select>
<input [(ngModel)]="textValue">
textValue: string;
selectedItem: string;
public onSelectionChange() {
   this.textValue = some-default-value;
}

I personally like approach #a(looks more MVVM rather than Event Driven Winforms as in #2), but I heard that it is actually bad to use getters and setters in angular world. Few arguments were -

  1. using getters instead of directly binding to the instance member might impact performance(angular change detection could behave different?)

  2. if we keep encouraging using getters setters, you could easily end up with your application abusing it by placing some logic in the getter/setter which could end up with the data in the UI & the actual model data out of sync(which also results in ExpressionChangedAfterItHasBeenCheckedError errors), so it is probably better to stick with approach #b

What are you opinions?, should angular applications stick with approach #b?

Thanks in advance.


Solution

  • Use them as long as you don't bind to them (you can always bind to the backing field). The problem with angular's change detection regarding getters and setters is that they are actually functions so the change detection mechanism has to run them every cycle to check if something changed.

    You can actually benefit performance wise using setters in angular.

    It's done by setting the component with

    @Component({
      // ...
      changeDetection: ChangeDetectionStrategy.OnPush
    })
    

    and running change detection with ChangeDetectorRef in your setters.

    But that's a bit advance stuff and requires a bit of knowledge about the change detection system to use it properly and this approach influences all the component's children so can actually mess up with 3rd party components.

    I'm just mentioning it here in case you ever get to the point in your project where everything starts slowing down significantly