【问题标题】:Binding an Angular Material Selection List绑定 Angular 材质选择列表
【发布时间】:2018-05-01 03:56:41
【问题描述】:

我正在使用 Angular Material 2 创建一个带有选择列表(每个列表项的复选框)的工具栏。我只是无法弄清楚如何在显示列表之前设置复选框,然后在用户交互后获取所选项目。

我正在尝试表单中的控件,认为我可能需要将其绑定到 ngModel,但这似乎没有帮助。到目前为止,我的 html 是:

<form
  novalidate
  #areaSelectForm="ngForm">

<div>
    <mat-selection-list 
                        #areasList="ngModel"
                        [(ngModel)]="model"
                        id="areaListControl"
                        name="areaListControl"
                        (ngModelChange)="onAreaListControlChanged($event)">
        <mat-list-option *ngFor="let tta of taskTypeAreas" (click)="onCheckboxClick($event)" [value]="tta">
            {{tta}}
        </mat-list-option>
    </mat-selection-list>
</div>

</form>

这一定是一个很好的路径,但文档很难解释,我似乎找不到任何合适的例子。

非常欢迎任何指导。

【问题讨论】:

    标签: angular angular-material


    【解决方案1】:

    您可以使用selectionChange 事件发射器来触发控制器功能。

    <mat-selection-list 
       id="areaListControl"
       name="areaListControl"
       (selectionChange)="onChange($event)"
    >
        <mat-list-option 
           *ngFor="let tta of taskTypeAreas" 
           [selected]="tta.selected"
           [value]="tta"
        >
            {{tta}}
        </mat-list-option>
    </mat-selection-list>
    

    在控制器中:

    onChange(change: MatSelectionListChange) {
       console.log(change.option.value, change.option.selected);
    }
    

    【讨论】:

    • 您应该能够使用 ViewChildren 访问 matListOption 实例,然后遍历它们以检查您需要什么。请注意,在加载视图之前,实例将不可用,您将无法在 onInit 中执行此操作。
    【解决方案2】:

    @LLai 的回答是正确的,但是你可能已经注意到,当我们使用对象作为mat-select-option[value] 时,Angular 材质选择不起作用

    为了解决这个问题,Angular 材质提供了[compareWith] 输入。

    @输入() compareWith: (o1: any, o2: any) => boolean

    用于将选项与所选值进行比较的函数 确定哪些选项应显示为已选择。首先 参数是选项的值。第二个是来自的值 选定的值。必须返回一个布尔值。

    例如,

    list-selection.component.ts

    export class ListSelectionExample {
    
      selectedOptions = [{name: 'Boots', id:1}];
      compareFunction = (o1: any, o2: any)=> o1.id===o2.id;
    
      typesOfShoes: {name: string, id: number }[] = [
        {name: 'Boots', id: 1}, 
        {name: 'Clogs', id: 2},
        {name: 'Loafers', id: 3 },
        {name: 'Moccasins', id: 4},
        {name: 'Sneakers', id:5}
      ];
    }
    

    list-selection.component.html

    <mat-selection-list [(ngModel)]="selectedOptions" [compareWith]="compareFunction">
      <mat-list-option *ngFor="let shoe of typesOfShoes" [value]="shoe">
        {{shoe.name}}
      </mat-list-option>
    </mat-selection-list>
    
    <p>
      Options selected: {{selectedOptions | json}}
    </p>
    

    在这里找到live Stackblitz example

    【讨论】:

    • 非常感谢您指出 compareWith 的事情。我一直在寻找解决方案,要么没有人想要默认选择,要么他们没有使用复杂的对象
    【解决方案3】:

    5.0.0 版本开始,角度材质现在支持ngModel 用于选择列表。

    所以代码可以简化为

    <mat-selection-list #list [(ngModel)]="selectedOptions" (ngModelChange)="onNgModelChange($event)">
        <mat-list-option *ngFor="let tta of taskTypeAreas" [value]="tta.name">
            {{tta.name}}
        </mat-list-option>
    </mat-selection-list>
    

    该版本还为选择列表公开了一个ngModelChange 事件。这是更新的stack blitz


    (Angular 5.0.0 之前的原始答案)

    mat-selection-list 目前似乎不支持 ngModel (https://github.com/angular/material2/pull/7456),但它看起来会在不久的将来得到支持。同时,您可以使用引用变量#list 来获取选定的选项。

    // component.html
    
    <mat-selection-list #list>
        <mat-list-option *ngFor="let tta of taskTypeAreas" [selected]="tta.selected" 
            (click)="onAreaListControlChanged(list)" [value]="tta.name">
            {{tta.name}}
        </mat-list-option>
    </mat-selection-list>
    

    然后将引用变量传递给您的 onAreaListControlChanged(list) 方法,以便您可以解析出选定的选项。

    // component.ts
    
    onAreaListControlChanged(list){
        this.selectedOptions = list.selectedOptions.selected.map(item => item.value);
    }
    

    要在加载时选中复选框,您可以使用每个&lt;mat-list-option&gt;[selected] 属性。

    <mat-list-option ... [selected]="tta.selected" ...>
    

    为此,您需要向数组中添加另一个属性。

    // component.ts
    
    taskTypeAreas: {
        name: string;
        selected: boolean;
    }[] = [
        {
            name: 'Area 1',
            selected: false
        },
        {
            name: 'Area 2',
            selected: false
        },
        {
            name: 'Area 3',
            selected: true
        },
    ];
    

    这将使Area 3 在加载时被选中。这是一个 stackblitz 演示这个。


    【讨论】:

    • 你是明星拉来。我将重构我的代码并试一试。谢谢。
    • 您建议的方法很有效。非常感谢。
    • @TDC 很高兴我能帮上忙!
    • 这确实应该是文档的一部分
    • 这是一个非常好的答案,我进行了编辑以将您的 Angular 5 答案移到顶部,因为它更相关。当我开始阅读它时,我的第一个想法是,“哦,不,它不支持”.. 等等.. 它是 :D 呵呵呵呵 +1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    • 1970-01-01
    • 1970-01-01
    • 2018-02-07
    • 2018-12-13
    • 2020-03-30
    • 2018-07-06
    相关资源
    最近更新 更多