I want users to be able to select a maximum of 3 options from a list.
If a form has four options, once the user selects three, the fourth should become disabled.
Here is the setup I have:
import {
Component,
Input,
ViewChild,
OnInit,
AfterViewInit
} from "@angular/core";
import { MatSelectionList } from "@angular/material/list";
type Option = {
key: string;
enabled: boolean;
};
@Component({
selector: "app-list-component",
template: `
<mat-selection-list>
<mat-list-option
*ngFor="let option of options"
checkboxPosition="before"
[selected]="option.enabled == true"
[disabled]="
selectedOptionsCount >= maxSelectedFilters && !option.enabled
"
>
{{ option.key }}
</mat-list-option>
</mat-selection-list>
`,
styleUrls: ["./list.component.css"]
})
export class ListComponent implements OnInit, AfterViewInit {
options: Option[];
selectedOptionsCount: number;
@Input() filters: string[];
@Input() selectedFilters: string[];
@Input() maxSelectedFilters: number;
@ViewChild(MatSelectionList) selectionList: MatSelectionList;
ngOnInit(): void {
this.options = this.filters.map((key) => ({
key,
enabled: this.selectedFilters.includes(key)
}));
// initially set the count
this.selectedOptionsCount = this.selectedFilters.length;
}
ngAfterViewInit(): void {
this.selectionList.selectionChange.subscribe(() => {
// update the count based on the selection change
this.selectedOptionsCount = this.selectionList.selectedOptions.selected.length;
});
}
}
In this configuration, only when you de-select an already selected option will the non-selected items become disabled.
How can you track these changes?
Edit:
The following solution seems to work. Add a template variable using '#' on the mat-list-option
, and use it to access the 'selected' property:
//
// ...
<mat-list-option
#foo
*ngFor="let option of options"
checkboxPosition="before"
[selected]="option.enabled == true"
[disabled]="selectedOptionsCount >= maxSelectedFilters && !foo.selected"
>
// ...
Source: https://codesandbox.io/s/lucid-kare-wc26k?file=/src/components/list.component.ts