web-dev-qa-db-fra.com

Angular mat-selection-list, Comment faire pour sélectionner une case à cocher semblable à un bouton radio?

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.

11
user9182427

Cela fonctionne avec le matériau 5-7:

@ViewChild(MatSelectionList) selectionList: MatSelectionList;

ngOnInit() {
    this.selectionList.selectedOptions = new SelectionModel<MatListOption>(false);
}
14
hovado

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:

  • Écoutez selectionChange 
  • Effacer tout avec la méthode deselectAll() 
  • Définir comme sélectionné à nouveau

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

11
Simon_Weaver

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.

2
Siscka

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>

Vérifiez un Stackblitz

2
Asaf Agranat

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.

2
Alain Iglesias

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>
0
Gilberto

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.

0
Mendy

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;
}
0
Kush Grover

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".

0
Florin Filip

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.

0
amir110