I am building a generic selector component with Angular Material. When setting the value manually it works ok but, if I update form value from typescript, the view does not reflect that change.
selector.component.html
<mat-form-field appearance="standard">
<mat-label>{{ label }}</mat-label>
<mat-select
[formControl]="formControl"
(valueChange)="onChange($event)"
multiple
>
<mat-select-trigger>
{{ !!selectedData.length ? selectedData[0][elementLabel] : '' }}
<span *ngIf="selectedData.length > 1" class="additional-selection">
(+{{ selectedData.length - 1 }}
{{ selectedData?.length === 2 ? 'other' : 'others' }})
</span>
</mat-select-trigger>
<mat-option
*ngFor="let element of data; trackBy: trackByFunction"
[value]="element"
>{{ element[elementLabel] }}</mat-option
>
</mat-select>
</mat-form-field>
selector.component.ts
import {
ChangeDetectionStrategy,
Component,
EventEmitter,
Input,
Output,
} from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'selector',
templateUrl: './selector.component.html',
styleUrls: ['./selector.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SelectorComponent {
@Input() data: any[] = [];
@Input() set init(value: any[]) {
this.selectedData = value;
}
@Input() label: string = '';
@Input() elementLabel: string = '';
@Output() onChangeEvent: EventEmitter<any[]> = new EventEmitter();
selectionDisplayText = '';
formControl = new FormControl([]);
get selectedData(): any[] {
return this.formControl.value;
}
set selectedData(data: any[]) {
this.formControl.setValue(data);
}
trackByFunction(item: any): string {
return item[this.elementLabel];
}
onChange = (data: any[]) => {
this.selectedData = data;
this.onChangeEvent.emit(this.selectedData);
};
}
When I try to update select values from parent component (using init
input), the code reaches set selectedData
method and formControl value is set OK, but the view displays an empty select. What am I missing?
Thanks