Angular mat-selection-list, How to make single checkbox select similar to radio button?

后端 未结 14 1704
北恋
北恋 2021-02-18 21:22

How to make make single checkbox select from mat-selection-list. Similar to radio button which accepts one value from group of values.

相关标签:
14条回答
  • 2021-02-18 21:30

    What you'd need to do is:

    • Listen for selectionChange
    • Clear all with deselectAll() method
    • Set it as selected again

    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

    0 讨论(0)
  • 2021-02-18 21:31

    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;
    }
    
    0 讨论(0)
  • 2021-02-18 21:34

    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

    0 讨论(0)
  • 2021-02-18 21:36

    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.

    0 讨论(0)
  • 2021-02-18 21:39

    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.

    0 讨论(0)
  • 2021-02-18 21:41

    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>
    
    0 讨论(0)
提交回复
热议问题