Angular mat-selection-list,如何使单个复选框选择类似于单选按钮?

时间:2018-01-16 09:27:19

标签: angular angular-material

如何从mat-selection-list中选择make single复选框。类似于单选按钮,它接受一组值中的一个值。

15 个答案:

答案 0 :(得分:16)

这适用于材料5-7:

@ViewChild(MatSelectionList) selectionList: MatSelectionList;

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

答案 1 :(得分:12)

您需要做的是:

  • 倾听selectionChange
  • 使用deselectAll()方法
  • 清除所有内容
  • 再次将其设为

我在API页面中修改了原始示例,为选择列表添加了ViewChild并订阅了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
}

工作样本: https://stackblitz.com/edit/angular-i3pfu2-6n5cnt

另见: https://material.angular.io/components/list/api

答案 2 :(得分:3)

只需将MatSelectionList的多个选项设置为false:

ngOnInit() {
  this.links.selectedOptions._multiple = false;
}

你已经完成了。此外,您还可以取消选中所选复选框。

答案 3 :(得分:3)

首先,mat-selection-list不适合单值选择,因为它偏离了its intent

  

组中的复选框是非专有选项;可以在任何给定时间选中一个组中的多个复选框

您要查找的是单选按钮元素本身,因为在语义上it stands for

  

单选按钮是代表互斥选择的一组控件中的一个

很遗憾,Angular Material不包含mat-radio-list组件。但是您仍然可以通过在mat-radio-button中加入mat-list-item来实现。这将提供最佳实践,因为它向用户表明列表中的列表旨在用于相互排斥的选择(不同于表示多项选择的复选框)。并且由于单选按钮正在更新单个变量,因此您具有排他性:

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

Check a Stackblitz

答案 4 :(得分:2)

如果您没有使用Angular Material v6 +,为了从mat-selection-list中选择单个复选框,这里是我使用的解决方法: 假设我们有一个类别列表复选框。

在您的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>

在你的.TS:

  handleSelection(event, categorySelected) {
      if (event.selected) {
          event.source.selectionList.options.toArray().forEach(element => {
              if (element.value.name!= categorySelected.name) {
                 element.selected = false;
              }
         });
      }
  }

这里的关键是在MatListOption上使用属性selectionChange而不是MatSelectionList。

答案 5 :(得分:1)

参加聚会有点晚,但这是我想出的一种解决方案,它使用指令扩展了mat-selection-list的行为。

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);
        }
    }
}

您可以像这样使用...

<mat-selection-list [multiple]="false">
...
</mat-selection-list>

理想情况下,我们将使用无线电控件而不是复选框,但我认为在变角材料小组正式支持此解决方案之前,此解决方法是可以的。

答案 6 :(得分:0)

如果您为每个mat复选框使用ngFor,则可以在HTML模板中执行类似以下操作:

function identifyUser(){
   var input = Browser.inputBox('Enter User Id which will be used to save user to events (run once)');
  PropertiesService.getUserProperties().setProperty("ID", input);
}

并在TS中:

<ng-container *ngFor="let address of person.addresses; let i = index">
    <mat-checkbox [checked]="personCheckedIndex === i" (change)="customerCheckboxChange($event, i)"></mat-checkbox>
</ng-container>

答案 7 :(得分:0)

您需要的可能是<mat-radio-group>而不是<mat-selection-list>,它是选项列表,但只能选择一个选项。可以在Angular Material docs上找到示例。

但是请注意,您会得到一个单选按钮,而不是复选框。

答案 8 :(得分:0)

尝试一下:

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);
    }
}

模板:

<mat-selection-list #element_id>
    <mat-list-option *ngFor="let d of data">
        {{ d.name }}
    </mat-list-option>
</mat-selection-list>

答案 9 :(得分:0)

从哲学和用户体验的角度来看,您需要使用单选按钮。这是提供用户友好的“预期”行为的唯一方法。

答案 10 :(得分:0)

您可以使用“ mat-checkbox”而不是“ mat-selection-list”,并像这样玩click事件:

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;
  }

请记住,所有复选框的默认值均未选中。

答案 11 :(得分:0)

您可以声明[selected]的{​​{1}}属性

例如:

mat-list-option

通过这种方式,您只需更改一个选择,而无需更改任何MatSelectionList隐藏属性。

您也可以通过将<mat-selection-list #list> <mat-list-option *ngFor="let item of myList" [(mgModel)]="selectedOption" [selected]="item.id === selectedOption.id" [value]="item"> {{item.name}} </mat-list-option> </mat-selection-list> 替换为控制器逻辑来做到这一点, 通过这种方式,您可以将最后一个选择对象保存在类变量中。

ngModel

另请参阅Binding an Angular Material Selection List

答案 12 :(得分:0)

从Angular Material 9.1.0开始,选择列表支持单个选择模式。将multiple输入设置为falsehttps://material.angular.io/components/list/api#MatSelectionList

启用它

答案 13 :(得分:0)

试试这个: 我已经有了一个勾号,改变了 css

    :host ::ng-deep .mat-radio-outer-circle{
      border-radius:2px;
    }
    :host ::ng-deep .mat-radio-inner-circle{
        border-radius:2px;
        background-color: transparent!important;
        border-bottom: 4px solid white;
        border-right:4px solid white;
        height:30px;  
        width:15px;
        margin-top: -8px;
       margin-left: 3px;
    }
    :host ::ng-deep .mat-radio-checked .mat-radio-outer-circle{
       background:#ff4081!important;
    }
    :host ::ng-deep .mat-radio-checked .mat-radio-inner-circle{
       transform: rotate(45deg) scale(0.5);
    }
 
    :host ::ng-deep .mat-radio-button .mat-radio-ripple{
      height: 20px; /*double of your required circle radius*/
      width: 20px;  /*double of your required circle radius*/
      left: calc(50% - 10px); /*'10px'-same as your required circle radius*/
      top: calc(50% - 10px); /*'10px'-same as your required circle radius */
    }

答案 14 :(得分:0)

这是一个简单的解决方案,虽然不是完美的解决方案,但它可以完成您的工作!

 
change() {
    if (this.formGroup.get('control1').value === true) {
      this.formGroup.get('control2').setValue(false);
    } else if (this.formGroup.get('control2').value === true){
      this.formGroup.get('control1').setValue(false);
    }
 }
<mat-checkbox [formControlName]="'control1'" color="primary" (change)="change()">
   control1
</mat-checkbox>

<mat-checkbox color="primary" [formControlName]="'control2'" (change)="change()">
   control2
</mat-checkbox>