Comment faire une seule case à cocher dans la liste de sélection de mat. Semblable au bouton radio qui accepte une valeur d'un groupe de valeurs.
Cela fonctionne avec le matériau 5-7:
@ViewChild(MatSelectionList) selectionList: MatSelectionList;
ngOnInit() {
this.selectionList.selectedOptions = new SelectionModel<MatListOption>(false);
}
Je ne comprends pas qui a inventé mat-selection-list
comme cela fonctionne maintenant. Je ne comprends pas pourquoi il n'y a pas de moyen évident d'en faire une sélection unique et je ne comprends pas non plus pourquoi je ne peux pas désactiver la case à cocher.
Ce que vous devez faire c'est:
selectionChange
deselectAll()
J'ai modifié l'exemple d'origine à partir de la page API, ajouté un ViewChild pour la liste de sélection et souscrit à l'événement selectionChange
.
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/fa4ddd0a13461b2f846e114fd09f8f4e21b814b1/src/lib/list/selection-list.ts
}
Échantillon de travail: https://stackblitz.com/edit/angular-i3pfu2-6n5cnt
Voir aussi: https://material.angular.io/components/list/api
Pour créer une seule case à cocher, sélectionnez Mat-Selection-List si vous n’utilisez pas Angular Material v6 +. Voici la solution de contournement que j’ai utilisée:.
Dans votre HTML:
<mat-selection-list>
<mat-list-option (selectionChange)="handleSelection($event, category)" *ngFor="let category of categories" [value]="category">
<span >{{category.name}}</span>
</mat-list-option>
</mat-selection-list>
Dans votre .TS:
handleSelection(event, categorySelected) {
if (event.selected) {
event.source.selectionList.options.toArray().forEach(element => {
if (element.value.name!= categorySelected.name) {
element.selected = false;
}
});
}
}
La clé ici consiste à utiliser la propriété selectionChange sur MatListOption et non MatSelectionList.
Pour commencer, mat-selection-list
ne convient pas à une sélection à valeur unique, car il s'éloigne de son intention :
Les cases à cocher d'un groupe sont des options non exclusives. plus d'une case à cocher dans un groupe peut être cochée à tout moment
Ce que vous recherchez, c’est l’élément bouton radio lui-même, car sémantiquement il représente :
Un bouton radio fait partie d'un groupe de commandes représentant des choix mutuellement exclusifs.
Malheureusement, Angular Material n’inclut pas de composant mat-radio-list
. Mais vous pouvez toujours y parvenir en incluant un mat-radio-button
dans votre mat-list-item
. Cela constituera la meilleure pratique, car il indique à l'utilisateur que la liste affichée est destinée à des choix mutuellement exclusifs (contrairement aux cases à cocher indiquant un choix multiple). Et comme les boutons radio mettent à jour une seule variable, vous obtenez l'exclusivité:
<mat-list role="list">
<mat-list-item role="listitem" *ngFor="let x of [0,1,2]; let i = index">
<mat-radio-button [value]="i" (change)="selection = $event.value">
Item {{x}}
</mat-radio-button>
</mat-list-item>
</mat-list>
Il suffit de définir l'option multiple de MatSelectionList sur false:
ngOnInit() {
this.links.selectedOptions._multiple = false;
}
et tu as fini. De cette manière, vous pourrez également désélectionner la case à cocher sélectionnée.
essaye ça:
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);
}
}
modèle:
<mat-selection-list #element_id>
<mat-list-option *ngFor="let d of data">
{{ d.name }}
</mat-list-option>
</mat-selection-list>
Ce dont vous avez besoin est probablement un <mat-radio-group>
au lieu d'un <mat-selection-list>
. C'est une liste d'options mais une seule option peut être sélectionnée. un exemple peut être trouvé à la Matériel angulaire docs .
Mais sachez qu’au lieu d’une case à cocher, vous aurez un bouton radio.
Si vous utilisez ngFor pour chaque case à cocher, vous pouvez faire quelque chose de similaire à ce qui suit dans le modèle HTML:
<ng-container *ngFor="let address of person.addresses; let i = index">
<mat-checkbox [checked]="personCheckedIndex === i" (change)="customerCheckboxChange($event, i)"></mat-checkbox>
</ng-container>
et dans 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;
}
Du point de vue philosophique et UX, vous devez utiliser des boutons radio. C’est le seul moyen de fournir un comportement convivial "comme prévu".
vous pouvez utiliser 'mat-checkbox' au lieu de 'mat-selection-list' et jouer avec un événement click comme ceci:
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;
}
rappelez-vous que la valeur par défaut de toutes les cases à cocher n'est pas cochée.