You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Material表格实现Excel式Shift连续选行功能求助

Angular Material表格Shift批量选中连续行问题修复

你的Shift点击逻辑无效核心原因有两点:HTML未绑定Shift处理函数、选中状态未同步更新row.complete与全选/半选标识。以下是完整修复方案:

一、修改HTML代码

将复选框的(click)事件替换为toggleSelection,确保Shift按键事件能被捕获:

<ng-container matColumnDef="select">
  <th mat-header-cell *matHeaderCellDef>
    <mat-checkbox 
      id="allCheck" 
      (change)="setAllChekedOrUnchecked($event)"
      [checked]="isAllElementSelected" 
      [indeterminate]="iSsomeElementsSelected">
    </mat-checkbox>
  </th>
  <td mat-cell *matCellDef="let row">
    <mat-checkbox 
      [checked]="row.complete" 
      (click)="toggleSelection($event, row)">
    </mat-checkbox>
  </td>
</ng-container>
<ng-container matColumnDef="entityCode">
  <th mat-header-cell *matHeaderCellDef>TOUTES</th>
  <td mat-cell *matCellDef="let element" style="cursor: pointer">
    <span (click)="openConfirmationDialog(element)">{{ element.entityCode }}</span>
  </td> 
</ng-container>

二、修正TS代码逻辑

1. 修复半选状态判断函数

原函数依赖row.complete的判断逻辑有误,改为基于selection实际选中状态:

someElementsSelected(): boolean {
  return this.selection.selected.length > 0 && !this.isAllElementSelected;
}

2. 完善Shift批量选与单选逻辑

整合两种选择逻辑,同步更新UI状态与selection对象:

lastSelectedId: number | null = null;

getRowRange(idA: number, idB: number): Interclassement[] {
  const rows = this.dataSource.data;
  const startIndex = rows.findIndex(row => row.id === idA);
  const endIndex = rows.findIndex(row => row.id === idB);

  if (startIndex === -1 || endIndex === -1) {
    return [];
  }

  const [from, to] = startIndex < endIndex ? [startIndex, endIndex] : [endIndex, startIndex];
  return rows.slice(from, to + 1);
}

toggleSelection(event: MouseEvent, row: Interclassement) {
  event.stopPropagation();
  
  if (event.shiftKey && this.lastSelectedId !== null) {
    const rowsToToggle = this.getRowRange(this.lastSelectedId, row.id);
    // 以目标行当前状态为基准,批量切换连续行(和Excel逻辑对齐)
    const shouldSelect = !row.complete;

    rowsToToggle.forEach(item => {
      item.complete = shouldSelect;
      shouldSelect ? this.selection.select(item) : this.selection.deselect(item);
    });
  } else {
    // 单选逻辑:切换当前行状态
    row.complete = !row.complete;
    row.complete ? this.selection.select(row) : this.selection.deselect(row);
    this.lastSelectedId = row.id;
  }

  // 更新全选、半选状态
  this.isAllElementSelected = this.selection.selected.length === this.dataSource.data.length;
  this.iSsomeElementsSelected = this.someElementsSelected();
}

3. 优化全选/取消全选逻辑

确保全选操作后lastSelectedId同步更新,避免后续Shift操作异常:

setAllChekedOrUnchecked($event: MatLegacyCheckboxChange) {
  this.dataSource.data.forEach(elt => {
    elt.complete = $event.checked;
  });
  
  if ($event.checked) {
    this.selection.select(...this.dataSource.data);
    if (this.dataSource.data.length > 0) {
      this.lastSelectedId = this.dataSource.data[this.dataSource.data.length - 1].id;
    }
  } else {
    this.selection.clear();
    this.lastSelectedId = null;
  }
  
  this.isAllElementSelected = $event.checked;
  this.iSsomeElementsSelected = this.someElementsSelected();
}

三、关键修复点说明

  1. 事件绑定修正:将复选框点击事件绑定到toggleSelection,确保Shift按键事件能被触发。
  2. 状态双向同步:Shift批量选时必须同时更新row.complete(保证复选框UI变化)与selection对象(维护选中数据)。
  3. Excel逻辑对齐:Shift选时以目标行当前状态为基准,批量切换连续行,和Excel操作行为一致。
  4. 全选状态联动:全选/取消全选时同步更新lastSelectedId,避免后续Shift操作出现异常。

内容的提问来源于stack exchange,提问作者Chady

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 13:57:35