TL;DR: I already have working solutions, but I would like explanations why mat-select behaves like this.
While building an application with Angular Material I run into this error when using mat-select
combined with *ngFor
in the template: the get priorities
function is being called continuously like in an infinite loop and the browser freezes.
Component
get priorities() {
return [
{ name: 'NORMAL', value: 100 },
{ name: 'HIGH', value: 200 },
{ name: 'FORCE', value: 300 },
];
}
<mat-form-field appearance="outline">
<mat-label>Priority</mat-label>
<mat-select formControlName="priority">
<mat-option *ngFor="let element of priorities" [value]="element"
>{{ element.name }}</mat-option
>
</mat-select>
</mat-form-field>
Posible solutions
- Specifying each mat-option (without ngFor). Although this is not useful for many cases.
<mat-form-field appearance="outline">
<mat-label>Priority</mat-label>
<mat-select formControlName="priority">
<mat-option [value]="priorities[0]">{{ priorities[0].name }}</mat-option>
<mat-option [value]="priorities[1]">{{ priorities[1].name }}</mat-option>
<mat-option [value]="priorities[2]">{{ priorities[2].name }}</mat-option>
</mat-select>
</mat-form-field>
- Using native html select and option. This is a valid solution, but I wanted to make it work with Material.
<select matNativeControl>
<option *ngFor="let element of priorities" [value]="element">
{{ element.name }}
</option>
</select>
- It seems that in order to use
mat-option
withngFor
we need to add atrackBy
function. ¿Can someone explain why? I am aware that usingtrackby
improves efficiency, but I have not found any Material documentation about why it is necessary to use it withmat-select
.
<mat-form-field appearance="outline">
<mat-label>Priority</mat-label>
<mat-select formControlName="priority">
<mat-option
*ngFor="let element of priorities; trackBy: prioritiesTrackByFn"
[value]="element"
>{{ element.name }}</mat-option
>
</mat-select>
</mat-form-field>
prioritiesTrackByFn(index, item): number {
return item.value;
}