1

Is it good/bad practice to disable an Angular button with a component method? Specifically, Would this be a performance issue in Angular? It seems like Angular would have to continuously calculate.

Is it better to use a static variable (eg this.productDisable: boolean), and just let it calculate at certain times?

isProductSaveDisabled() {
  if (this.productsSelected == null || this.productsSelected ?.length === 0) {
    return true;
  } else {
    return false;
  }

}

HTML:

<button mat-raised-button [disabled]="isProductSaveDisabled()" (click)="saveAll()">
    Save Product
</button>

Curious reading loot of tutorials and articles using class methods, etc

  • 1
    Inline or component method, doesn't matter. The logic will execute. What **does** matter is readability. And using a component method like that is **much more** readable than trying to shoe horn that logic inline. – Taplar Aug 06 '20 at 21:51
  • The component method also add self documentation. – Taplar Aug 06 '20 at 21:52
  • There should not be any noticible difference between the pure logic executing vs a method being called that executes the logic. Both cases will be evaluated the same number of times by change detection. – Taplar Aug 06 '20 at 21:53
  • This is the top result from Googling "should i put function calls in angular templates" https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496#:~:text=In%20this%20article%2C%20we%20learned,calls%20in%20Angular%20template%20expressions. – Adrian Brand Aug 06 '20 at 23:08
  • @AdrianBrand also as a side note, wonder if getters or setters also would be a good option? anyways, putting in a pipe call then, –  Aug 06 '20 at 23:09
  • Getter and setter logic still gets triggered each time change detection runs. – Adrian Brand Aug 06 '20 at 23:17

2 Answers2

4

This is the sort of question you will get asked in job interviews and it can cost you the job so don't put a function call in the template.

The best answer would be to use a pipe

@Pipe({
  name: 'emptyArray'
})
export class EmptyArrayPipe implements PipeTransform {
  transform(array: any[]): boolean {
    return !!array || array.length === 0;
  }
}

and use it

[disabled]="productsSelected | emptyArray"

This will only trigger change detection to rerun the logic if productsSelected changes.

If you go for a lot of Angular tech interviews you are likely to encounter this kind of scenario.

Adrian Brand
  • 20,384
  • 4
  • 39
  • 60
  • This is a good answer. You may want to elaborate on the pure-by-default nature of pipes which makes this a performant option. – Aluan Haddad Aug 06 '20 at 23:11
-1

With the way you have written it, there is not going to be any noticible performance difference between the non-function version and the function version. Both pieces of code will be executed the same number of times, any time change detection needs to re-evaluate.

What is of concern though is that the component method approach not only gives you a little more separation of concerns with the view logic and the controller logic, but it also increases the readibility of the code and introduces a chance for self documentation with the function name.

Taplar
  • 24,788
  • 4
  • 22
  • 35
  • No, you don't put function calls in the template, you use pipes. – Adrian Brand Aug 06 '20 at 22:59
  • @AdrianBrand Not sure what you mean. We use functions like this all the time. – Taplar Aug 06 '20 at 22:59
  • wonder if Angular has documentation discussing these kind of scenarios, whats optimal, etc? cc @Taplar –  Aug 06 '20 at 23:00
  • I personally, and this is obviously my opinion, feel that saying you have to use pipes is overkill. There should certainly be cases where pipes make sense. But I highly doubt that is an ultimatum. – Taplar Aug 06 '20 at 23:02
  • am reading this article, wonder how it pertains here? https://stackoverflow.com/a/54657951/13889515 cc @Taplar –  Aug 06 '20 at 23:03
  • hi @Taplar thanks for the help, I just gave thumbs up on your other questions, –  Aug 06 '20 at 23:12
  • It is definitely not an ultimatum. Another approach is to have a boolean flag called isProductSaveDisabled that you update when adding or removing products. But a function call in the template will definitely get your pull request rejected in our project. Pipes are incredibly convenient once you have a library of them built up in your app. – Adrian Brand Aug 06 '20 at 23:14
  • @AdrianBrand How do you avoid having pipes that are only really useful for one specific scenario? Or I guess that would be a use case for the boolean flag you just mentioned – Taplar Aug 06 '20 at 23:15
  • Once you get in the mindset of not calling functions in the template it become second nature to think about structuring your components with state that drives UI. State usually only changes with a user interaction or an observable emitting so you can construct the correct component state at the time of these events so we don't have to calculate UI state at change detection. – Adrian Brand Aug 06 '20 at 23:21