I’m currently trying to implement a search function in my mat-select menu in Angular 18, through ngx-mat-select-search. I’m able to successfully click when I click ‘ALL’ after I search ‘ALL’. However, I’ve hit a roadblock when trying to essentially click any of the other modules in the menu. Specifically, it doesn’t let me click them at all. Any pointers? Here is my HTML:
<mat-form-field appearance="fill" class="matformfield">
<mat-label class="matlabel" *ngIf="!selectedModules.length">Select Modules</mat-label>
<mat-select #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}}
</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() && module !== 'ALL'" (click)="onClick(drop.options, module === 'ALL')">{{ module }}</mat-option>
<!--[value]="module.value", {{ module.viewValue }}-->
</mat-select>
</mat-form-field>
And 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[] = [
'ALL', '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)
);
}
}
/*onKey(value) {
const input = event.target as HTMLInputElement;
this.selectedModules = this.search(value);
}
search(value: string) {
let filter = value.toLowerCase();
return this.modules.filter(option => option.toLowerCase().startsWith(filter));
}*/
clearFields() {
this.selectedModules = [];
}
isAllSelected(): boolean {
return this.selectedModules.includes('ALL');
}
onClick(options:QueryList<MatOption>, isFirst:boolean=false) {
if (isFirst) {
const el = options.first;
options.forEach((x) => {
x[el.selected ? 'select' : 'deselect']();
});
if (el.selected) { //new
this.selectedModules = this.modules.slice();
}
else {
this.selectedModules = [];
} // end new
}
else {
const selected = options.filter((x, index) => index && x.selected);
if (selected.length == this.modules.length - 1) {
options.first.select();
this.selectedModules = this.modules.slice();
}
else {
options.first.deselect();
this.selectedModules = selected.map(x => x.value);
}
}
}
}
Any pointers would be appreciated for this problem. I’ve also attached a gif to demonstrate the issue.