【问题标题】:Checking max items in mat table using checkbox使用复选框检查垫表中的最大项目
【发布时间】:2021-06-21 17:23:00
【问题描述】:

我正在开发一个角度应用程序并使用带有 mat 复选框的 mat 表。代码如下:

    <table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
    
      <!-- Checkbox Column -->
      <ng-container matColumnDef="select">
        <th mat-header-cell *matHeaderCellDef>
        </th>
        <td mat-cell *matCellDef="let row">
          <mat-checkbox [(ngModel)]="row.checked" (change)="getCheckboxesData(row)">
          </mat-checkbox>
        </td>
      </ng-container>
    
      <!-- Position Column -->
      <ng-container matColumnDef="position">
        <th mat-header-cell *matHeaderCellDef> No. </th>
        <td mat-cell *matCellDef="let element"> {{element.position}} </td>
      </ng-container>
    
      <!-- Name Column -->
      <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef> Name </th>
        <td mat-cell *matCellDef="let element"> {{element.name}} </td>
      </ng-container>
    
      <!-- Weight Column -->
      <ng-container matColumnDef="weight">
        <th mat-header-cell *matHeaderCellDef> Weight </th>
        <td mat-cell *matCellDef="let element"> {{element.weight}} </td>
      </ng-container>
    
      <!-- Symbol Column -->
      <ng-container matColumnDef="symbol">
        <th mat-header-cell *matHeaderCellDef> Symbol </th>
        <td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
      </ng-container>
    
      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="selection.toggle(row)">
      </tr>
    </table>

import { SelectionModel } from '@angular/cdk/collections';
import { Component } from '@angular/core';
import { MatTableDataSource } from '@angular/material';

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
  { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
  { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
  { position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
  { position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
  { position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
  { position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
  { position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
  { position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
  { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' }
];

/**
 * @title Table with selection
 */
@Component({
  selector: 'table-selection-example',
  styleUrls: ['table-selection-example.css'],
  templateUrl: 'table-selection-example.html'
})
export class TableSelectionExample {
  public data: any;
  displayedColumns: string[] = [
    'select',
    'position',
    'name',
    'weight',
    'symbol'
  ];
  dataSource = new MatTableDataSource<PeriodicElement>(ELEMENT_DATA);
  selection = new SelectionModel<PeriodicElement>(true, []);

  /** Whether the number of selected elements matches the total number of rows. */
  isAllSelected() {
    const numSelected = this.selection.selected.length;
    const numRows = this.dataSource.data.length;
    return numSelected === numRows;
  }

  getCheckboxesData(row) {
    if (row.checked === true) {
      console.log(row);
      this.data.push(row);
    }
  }
}

堆栈闪电战:

https://stackblitz.com/edit/angular-l4x28h?embed=1&file=app/table-selection-example.html

我想在复选框中实现一个功能,这样如果用户单击超过 3 个复选框(最多 3 个用户可以检查),这意味着当用户尝试检查第 4 个复选框时,我需要显示一个对话框并确保特定行数据未添加到数组中。如果用户取消选中已选中的复选框,则应从数组中删除该特定项目。简而言之,我们应该允许随时检查最多 3 个项目。我该怎么做?

【问题讨论】:

    标签: angular angular-material angular8 angular9 angular10


    【解决方案1】:

    如果你改变你的getCheckboxData函数如下:

    getCheckboxesData(row) {
      if (row.checked === true) {
        if (!this.maxReached()) {
          // 3 selected items not reached, so add this one
          this.data.push(row);
        } else {
          // Needs to be done in a setTimeout - see https://github.com/angular/angular/issues/9275
          setTimeout(() => {
            // 3 selected items, so uncheck this one
            row.checked = false;
            // Display a dialog indicating there are too many items selected
            this.dialog.open(WarningDialog);
          });
        }
      } else if (row.checked === false) {
        // Remove the row
        this.data = this.data.filter(el => {
          return el.symbol !== row.symbol;
        });
      }
      console.log('selected', this.data);
    }
    

    这将执行检查 maxReached() 以查看 data 数组(包含所选项目)是否已包含 3 个项目。如果是这样,它将取消选中您刚刚检查的行(由于此问题,在 setTimeout 函数中执行此操作:https://github.com/angular/angular/issues/9275)并打开一个带有消息的对话框。

    maxReached() 函数仅在选择 3 个项目时返回 true,否则返回 false:

    maxReached(): boolean {
      return this.data.length === 3;
    }
    

    我在此处添加的另一段代码是如果您取消选中复选框,则会从data 数组中删除项目。这使用 Array 的 filter 函数来定位正确的元素,然后将其从数组中删除。您需要向TableSelectionExample 类添加一个构造函数,以注入打开模式所需的服务:

    constructor(public dialog: MatDialog) {}
    

    模型代码如下:

    打字稿

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'warning-dialog',
      templateUrl: 'warning-dialog.html'
    })
    export class WarningDialog {}
    

    HTML

    <h2 mat-dialog-title>Too Many Selected</h2>
    <mat-dialog-content class="mat-typography">
      <p>You can only select a maximum of 3 elements</p>
    </mat-dialog-content>
    

    不要忘记在 AppModule 类中将 WarningDialog 添加到 entryComponentsdeclarations

    有一个有效的 StackBlitz here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 2017-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多