I’m currently trying to implement a search function for my mat-select function in Angular 18. For some reason, search is not natively supported, so I have to utilize ngx-mat-select-search. I’m able to successfully get the search function to ‘autocomplete’ the objects in the select menu. However, once I click the results in the menu, the results don’t persist afterwards. For example, if I search for ‘lorem’ and click it in the menu, and then click out of the box to do some other unrelated action, then the result goes away from the box. Any pointers for this problem? I had to utilize a StackOverflow answer for actually getting the search function to autocomplete. I am okay with moving forward with an alternative, non-ngx solution as well if needed.
Here is my HTML:
<mat-form-field appearance="fill" class="matformfield">
<mat-label class="matlabel" *ngIf="!selectedModules.length">Select Modules</mat-label>
<mat-select [formControl]="control" #drop multiple [(ngModel)]="selectedModules"> <!--[(ngModel)]="selectedModules"-->
<ngx-mat-select-search [formControl]="control" ></ngx-mat-select-search>
<!--<input (keyup)="onKey($event)">-->
<mat-select-trigger *ngIf="drop.value && drop.value.length">
{{ drop.value.length>modules.length?'ALL': drop.value[0] === null ? drop.value.slice(1):drop.value}}
</mat-select-trigger>
<mat-option class="matoption" (click)="onClick(drop.options, true)" [value]="'ALL'">ALL</mat-option>
<mat-option class="matoption" *ngFor="let module of filteredRecords | async" [value]="module" [disabled]="isAllSelected()" (click)="onClick(drop.options)">{{ module }}</mat-option>
<!--[value]="module.value", {{ module.viewValue }}-->
</mat-select>
</mat-form-field>
onClick is an unrelated function that selects all and deselects all if ‘ALL’ is clicked. Here is my typescript:
export class ModuleMenuComponent {
/*modules: [
{ value: 'Module 1', viewValue: 'Module 1'},
{ value: 'Module 2', viewValue: 'Module 2'},
{ value: 'Module 3', viewValue: 'Module 3'},
{ value: 'Module 4', viewValue: 'Module 4'},
{ value: 'Module 5', viewValue: 'Module 5'}
];*/
public control: FormControl = new FormControl();
private _onDestroy = new Subject<void>();
public filteredRecords: ReplaySubject<any[]> = new ReplaySubject<any[]>(1);
@ViewChild('Select') select: MatSelect;
modules: any[] = [
'lorem', 'ipsum', 'domor', 'sit', 'amet'
];
selectedModules: string[] = [];
constructor() {
this.setInitialValue();
this.control.setValue([]);
this.filteredRecords.next(this.modules.slice());
this.control.valueChanges
.pipe(takeUntil(this._onDestroy))
.subscribe(() => {
this.filterModulesMulti();
});
}
private setInitialValue() {
this.filteredRecords
.pipe(take(1), takeUntil(this._onDestroy))
.subscribe(() => {
this.select.compareWith = (a: any, b: any) => a === b;
});
}
private filterModulesMulti() {
if (!this.modules) {
return;
}
let search = this.control.value;
if (!search) {
this.filteredRecords.next(this.modules.slice());
return;
}
else {
search = search.toLowerCase();
}
if (search.length >= 2) {
this.filteredRecords.next(
this.modules.filter(module => module.toLowerCase().indexOf(search) > -1)
);
}
}...
}