How to make make single checkbox select from mat-selection-list. Similar to radio button which accepts one value from group of values.
What you'd need to do is:
selectionChange
deselectAll()
method I modified the original example from the API page, added a ViewChild for the selection list and subscribe to the selectionChange
event.
ngOnInit(){
this.shoes.selectionChange.subscribe((s: MatSelectionListChange) => {
this.shoes.deselectAll();
s.option.selected = true;
});
// WARNING: Don't attempt to do the following to select the value
// it won't trigger the value change event so it will remain unchecked
// this.shoes.selectedOptions.select(s.option);
// If interested source is here :
// https://github.com/angular/material2/blob/fa4ffffd0a13461b2f846e114fd09f8f4e21b814b1/src/lib/list/selection-list.ts
}
Working sample: https://stackblitz.com/edit/angular-i3pfu2-6n5cnt
See also: https://material.angular.io/components/list/api
If you're using ngFor for each mat-checkbox, you can do something similar to following in HTML template:
<ng-container *ngFor="let address of person.addresses; let i = index">
<mat-checkbox [checked]="personCheckedIndex === i" (change)="customerCheckboxChange($event, i)"></mat-checkbox>
</ng-container>
and in TS:
public personCheckedIndex = -1;
// Called from template when checkbox value changes
personCheckboxChange(event: MatCheckboxChange, index: number) {
// This allows only one checkbox to be checked among each checkbox
this.personCheckedIndex = event.checked ? index : -1;
}
Components >= 9.1.0
Selection list now supports a single selection mode directly. Enable it with the multiple input set to false.
<mat-selection-list [multiple]="false">...
Components < 9.1.0
You have to set SelectionModel for selectedOptions property of component reference on init.
@ViewChild(MatSelectionList, {static: true})
private selectionList: MatSelectionList;
ngOnInit() {
this.selectionList.selectedOptions = new SelectionModel<MatListOption>(false);
}
MatSelectionList api
This way you can define initially selected values too.
export declare class SelectionModel<T> {
constructor(_multiple?: boolean, initiallySelectedValues?: T[], _emitChanges?: boolean);
}
GitHub api
you can use 'mat-checkbox' instead of 'mat-selection-list' and play with click event like this:
HTML
<div *ngFor=" ... loop">
<mat-checkbox #checkBoxes (click)="changeCheckBox()">
</mat-checkbox>
</div>
TS
@ViewChildren('checkBoxes') checkBoxes: QueryList<MatCheckbox>;
changeCheckBox() {
this.checkBoxes.filter((checkbox: MatCheckbox) =>
checkbox.checked === true
)[0].checked = false;
}
remember that all check boxes default value is unchecked.
Bit late to the party, but here's a solution I came up with using a directive to extend the mat-selection-list
behaviour.
import { SelectionModel } from "@angular/cdk/collections";
import { Directive, Host, Input, OnChanges } from "@angular/core";
import { MatListOption, MatSelectionList } from "@angular/material/list";
@Directive({
selector: "mat-selection-list[multiple]"
})
export class MatSelectionListMultipleDirective implements OnChanges {
private matSelectionList: MatSelectionList;
@Input()
public multiple: boolean;
constructor(@Host() matSelectionList: MatSelectionList) {
this.matSelectionList = matSelectionList;
}
public ngOnChanges(): void {
if (this.multiple) {
this.matSelectionList.selectedOptions = new SelectionModel<MatListOption>(true, this.matSelectionList.selectedOptions.selected);
}
else {
let selected = this.matSelectionList.selectedOptions.selected.splice(0, 1);
this.matSelectionList.selectedOptions = new SelectionModel<MatListOption>(false, selected);
}
}
}
Which you can use like this...
<mat-selection-list [multiple]="false">
...
</mat-selection-list>
Ideally we would have a radio control instead of the checkbox, but I think this workaround is OK until the angular material team support this officially.
try this:
ts:
import { Component, OnInit, ViewChild} from '@angular/core';
import { MatSelectionList } from '@angular/material';
@Component({
selector : 'app-xxx',
templateUrl: './xxx.component.html'
})
export class xxxComponent implements OnInit {
public data: Object[] = [ {name : "name 1" }, {name : "name 2" }, {name : "name 3" }, {name : "name 4" } ];
@ViewChild('element_id') names_list: MatSelectionList;
ngOnInit() {
// only if the element is visible on the page, otherwise move this block and execute it until the list is displayed
setTimeout(()=>{
this.names_list.selectedOptions._multiple = false;
},0);
}
}
template:
<mat-selection-list #element_id>
<mat-list-option *ngFor="let d of data">
{{ d.name }}
</mat-list-option>
</mat-selection-list>