1

In the latest versions of Angular, I was using the following HTML:

    <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
    <mat-option *ngFor="let entity of entityNames" [value]="entity.EntityId">
     {{ entity.EntityName }}
    </mat-option>

Inside my regular angular component the displayFn method appears like this:

displayFn(entityId: number): string {
  const name = (entityId && entityId > 0) ? this.entityNames?.find(entityName => entityName.EntityId === entityId).EntityName : '';
  return name;
}

The problem is, my component "this." is not available and any access to its members fails.

Kim Gentes
  • 1,496
  • 1
  • 18
  • 38

1 Answers1

4

The short answer is simple: change your displayFn method call in HTML to add .bind(this) as follows:

    <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn.bind(this)">
      <mat-option *ngFor="let entity of entityNames" [value]="entity.EntityId">
        {{ entity.EntityName }}
      </mat-option>
    </mat-autocomplete>

I just spent 2 days finding out that "this." isn't available in a component method when the method is also used as a displayWith callback in a material form in that component. I now know that you can displayFn.bind(this) in the HTML, but really why wouldn't that be the default behavior of the callback when it's pretty guaranteed that anyone that doesn't want to use will just, well, not use it? In the mean time, the 100% of time that people want to use it, they will have to add the silly .bind(this). Stupid. Really.

Kim Gentes
  • 1,496
  • 1
  • 18
  • 38
  • 1
    I think I remember someone stating that this is by design. Plus, you don't need to use .bind - you can use a wrapper with arrow function like this: `get displayFn() { return (val) => this.someProperty + val; }` – TotallyNewb Jul 01 '20 at 19:28
  • 1
    The long answer is Angular had their head buried somewhere when this got coded. Totally worthless. – grantwparks Sep 12 '22 at 22:12