I have developed a custom component in Angular to manage my material autocomplete functionality for selecting an Action. I am passing the Action[] from the parent component to this component. The autocomplete feature is working correctly, but I am encountering an issue with my display name function. When trying to access this.actions inside the displayName function, I am receiving an error message "TypeError: Cannot read property 'filter' of undefined". After investigating further, I realized that this is because the this.actions array is empty within the displayName function. It seems like the actions property is not updating when the component loads the inputted value, causing it to remain stuck with the initial value. Despite this, the autocomplete component is functioning properly with the actions property. Is there a proper way to initialize the actions property so that it works effectively with my displayName() method?
import {Component, Input} from '@angular/core';
import {ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR} from '@angular/forms';
import {Action} from '../../../../Interfaces/action';
import {Observable} from 'rxjs';
import {map, startWith} from 'rxjs/operators';
@Component({
selector: 'app-input-action-typeahead',
templateUrl: './input-action-typeahead.component.html',
styleUrls: ['./input-action-typeahead.component.scss'],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: InputActionTypeaheadComponent,
multi: true
}]
})
export class InputActionTypeaheadComponent implements ControlValueAccessor {
@Input() actions: Action[] = [];
filteredActions: Observable<Action[]>;
actionCtrl = new FormControl();
constructor() {
this.filteredActions = this.actionCtrl.valueChanges.pipe(
startWith(''),
map(value => typeof value === 'string' ? value : value.name),
map(action => action ? this._filter(action) : this.actions.slice())
);
}
private _filter(value: string): Action[] {
const filterValue = value.toLowerCase();
return this.actions.filter(action => action.name.toLowerCase().indexOf(filterValue) !== -1);
}
registerOnChange(fn: any): void {
this.actionCtrl.valueChanges.subscribe(fn);
}
registerOnTouched(fn: any): void {
}
writeValue(obj: Action): void {
}
displayName(id: number): string {
if (!id) {
return '';
}
return this.actions.filter(action => action.id === id)[0].name;
}
clear(): void {
this.actionCtrl.setValue('');
}
}