I have an angular material drop down selector where I have multiple options to choose from. There is also an option where I can select all the options at once.
I used the code from this link, ( found it in answer for a similar question ).
These are my problems
The solution that was given in stack blitz is not fully accessible. The events do not get triggered on click of space bar.
What I have tried : using (onSelectionChange) event. But this will throw " Maximum call stack size exceeded" error as soon as there is a change.
How do I check these ( select all ) options on load ?
What I have tried : adding [checked]=true. But this will throw "Can't
bind to 'checked' since it isn't a known property of 'mat-option'" error.
How do I achieve these behaviours ?
I have found a hack ( or an actual solution ) for this problem. Feel free to edit my code Turns out I wasn't the only one with the same problem. Even though there were lot of people with the same issue under this link. My problem was slightly different. I wanted even the 'All' option to be accessible via keyboard. And I had to load all the options on load.
Here's the code that I wrote for it :
app.component.html
<div class="ddHolder">
<div>
<form [formGroup]="selectYearsForm" autocomplete="off" >
<mat-form-field appearance="fill">
<mat-select formControlName="yearOption" multiple class="custom-select-csRp"
panelClass="custom-select-panelCsrp mat-select-custom scrollcsrp" disableOptionCentering #selectcsrp
contentTabIndex=null #matSelect (selectionChange)="matOPtionChanged($event)">
<mat-option #allSelected [value]="0">
All
</mat-option>
<mat-option *ngFor="let year of selectedYearDD" [value]="year">
{{year}}
</mat-option>
</mat-select>
</mat-form-field>
</form>
</div>
</div>
app.component.ts
import { Component, ViewChild } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { MatOption } from '@angular/material/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
toppings = new FormControl();
selectYearsForm!: FormGroup;
selectedYears: any = [];
selectedYearDD: any = [];
selectedYearDDCopy: any = [];
@ViewChild('allSelected')
private allSelected!: MatOption;
constructor(
private fb: FormBuilder
){
}
ngOnInit(): void {
this.selectYearsForm = this.fb.group({
yearOption: new FormControl('')
});
this.selectedYearDD = ['1999','2000','2001','2002','2003','2004','2005'];
this.selectedYearDDCopy.push([...this.selectedYearDD.map((item: any) => item), 0])
}
ngAfterViewInit() {
//if needed load all the values by default
setTimeout(() => {
this.selectYearsForm.controls.yearOption
.patchValue([...this.selectedYearDD.map((item: any)=> item), 0]);
this.selectedYears = [];
this.selectYearsForm.controls.yearOption.value.forEach((item: any) => item == 0 ? "" : this.selectedYears.push(item));
}, 1);
}
matOPtionChanged(event: { value: number[]; }) {
const filteredArray = event.value.filter(val => !this.selectedYearDDCopy.includes(val));
if (event.value.length == this.selectedYearDD.length && !event.value.includes(0)) {
if (this.allSelected.selected || event.value.length - 1 == this.selectedYearDDCopy.length) {
this.selectYearsForm.controls.yearOption
.patchValue([...this.selectedYearDD.map((item: any) => item), 0]);
}
else {
this.selectYearsForm.controls.yearOption
.patchValue([]);
}
}
else if (filteredArray.length == 1 && filteredArray[0] === 0) {
this.selectYearsForm.controls.yearOption
.patchValue([...this.selectedYearDD.map((item: any) => item), 0]);
}
else if (event.value.includes(0) && event.value.length - 1 < this.selectedYearDD.length) {
event.value.shift();
this.selectYearsForm.controls.yearOption
.patchValue(event.value);
}
this.selectedYearDDCopy = this.selectYearsForm.controls.yearOption.value;
this.selectedYears = [];
this.selectYearsForm.controls.yearOption.value.forEach((item: any) => item == 0 ? "" : this.selectedYears.push(item));
}
}