0

I have the below partial HTML in my Material Table Angular application.

//HTML

 <button mat-icon-button class="mat-18" (click)="updateStatus(element.id)" 
            [disabled]="validateToWork(element.reachedTime)">
            <mat-icon>edit</mat-icon>
         </button>

//Typescript

  validateToWork(reachedTime:any):boolean{

    if(reachedTime&& new Date(this.datePipe.transform(reachedTime, DATE_WITH_TIME)) < new Date())
      return true;
    else
      return false;
  }

The above code works fine and the edit button is disabled. But what i observed is when i have a console.log(reachedTime) in the typescript like,

console.log(reachedTime)
if(reachedTime&& new Date(this.datePipe.transform(reachedTime, DATE_WITH_TIME)) < new Date())

I could see the event is triggered on every mouseover i do on the table. Its weird for me and not sure. How can i stop that?

Below is the console log i have

Log found in the browser

Any help ?

A Coder
  • 3,039
  • 7
  • 58
  • 129
  • 3
    https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496 – Chellappan வ Apr 09 '22 at 13:06

1 Answers1

2

Why

One of the rule with angular, is that you should try to avoid using method inside the html.

doing so

<button mat-icon-button class="mat-18" (click)="updateStatus(element.id)" 
  [disabled]="validateToWork(element.reachedTime)">
  <mat-icon>edit</mat-icon>
</button>

Will force [disabled] to be recalculated each time you make any interaction with the page, mouseover being one.

To test this out, just scroll or click somewhere, you should have the same result.


How to fix it

Add the logic inside a pipe

import { DatePipe } from '@angular/common'
import { Pipe, PipeTransform } from '@angular/core'
import { DATE_WITH_TIME } from 'from/some/where'

@Pipe({
  name: 'validateToWork',
})
export class ValidateToWorkPipe implements PipeTransform {
  constructor(private datePipe: DatePipe) {}

  transform(reachedTime: any): boolean {
    // <- do add a definition, try to never use any
    if (reachedTime && new Date(this.datePipe.transform(reachedTime, DATE_WITH_TIME)) < new Date())
      return true
    else return false
  }
}

And use it in your code like follow

<button mat-icon-button class="mat-18" (click)="updateStatus(element.id)" 
  [disabled]="element.reachedTime | validateToWork">
  <mat-icon>edit</mat-icon>
</button>

Further more

  • Do not forget to declare it in your module under the declarations: [] or in the imports: [] if you did create a module for that specific pipe
  • If you declares it directly, you won't be able to use it somewhere else.
  • If this is an object, you will have to manually trigger the update
Raphaël Balet
  • 6,334
  • 6
  • 41
  • 78