首页 > 解决方案 > 使用复选框检查垫表中的最大项目

问题描述

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

    <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 个项目。我怎样才能做到这一点?

标签: angularangular-materialangular8angular9angular10

解决方案


如果你改变你的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 )并打开一个带有消息的对话框。

如果选择了 3 个项目,该maxReached()函数仅返回 true,否则返回 false:

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

data我在此处添加的另一段代码是如果您取消选中复选框,则会从数组中删除该项目。这使用filterArray 的功能来定位正确的元素,然后将其从数组中删除。您需要向该类添加一个构造函数以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>

不要忘记在您的班级WarningDialog中添加entryComponents和。declarationsAppModule

这里有一个有效的 StackBlitz 。


推荐阅读