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

Angular多标签页下复选框选中项存入数组的实现问题

Angular多标签页复选框选中项持久化存储方案

需求:将多标签页中各标签页的复选框选中项存入数组,单标签页时功能正常,但多标签页场景下每次操作都会清空数组,无法保留所有标签页的选中项。最终需要按sampleNo分组统计criticalScore的总和。

当前尝试代码

component.ts

tabs = ['Sample #1', 'Sample #2', 'Sample #3'];
selected = new FormControl(0);
tabtitle: string = '';
criticalDefects: any[] = ['Helmet', 'Gloves', 'Boots', 'Jackets'];
sampleScore: any[] = [];

ngOnInit(): void {}

addTab() {
  let num = this.tabs.length + 1;
  this.tabs.push('Sample #' + num);
  this.selected.setValue(this.tabs.length - 1);

  this.tabtitle = '';
}
getSelectedCheckbox(tab: number, event: any) {
  this.sampleScore = [];
  var checkboxes = document.querySelectorAll('input[type=checkbox]:checked');
  const data = {
    sampleNo: tab,
    criticalScore: 3,
  };
  if (event.target.checked) {
    for (var i = 0; i < checkboxes.length; i++) {
      this.sampleScore.push(data);
    }
  }
  console.log(this.sampleScore);
}

component.html

<button type="button" (click)="addTab()">Add Sample</button>
<mat-tab-group [selectedIndex]="selected.value" (selectedIndexChange)="selected.setValue($event)">
  <mat-tab *ngFor="let tab of tabs; let index = index" [label]="tab">
    <table id="criticalTable">
      <thead>
        <tr>
          <th scope="col">Defect Classification</th>
          <th scope="col">Action</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let item of criticalDefects; let idx = index">
          <td>{{ item }}</td>
          <td style="width:30% ;">
            <div class="form-check">
              <input
                class="form-check-input"
                (change)="getSelectedCheckbox(index, $event)"
                type="checkbox"
                id="checkboxCritical_{{ idx }}"
              />
              <label class="form-check-label" for="checkboxCritical_{{ idx }}">
                Defect
              </label>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
  </mat-tab>
</mat-tab-group>

解决方案

核心思路是数据驱动跟踪每个标签的选中状态,避免直接操作DOM(mat-tab默认懒加载,未激活标签无DOM节点),同时取消每次操作清空数组的逻辑,改为维护每个标签的独立选中数据。

修改后的component.ts

tabs = ['Sample #1', 'Sample #2', 'Sample #3'];
selected = new FormControl(0);
tabtitle: string = '';
criticalDefects: any[] = ['Helmet', 'Gloves', 'Boots', 'Jackets'];
// 存储每个标签的选中缺陷,sampleNo对应标签索引
tabSelections: {sampleNo: number, selectedDefects: string[]}[] = this.tabs.map((_, idx) => ({
  sampleNo: idx,
  selectedDefects: []
}));

// 按需生成最终的score数组
get sampleScore(): any[] {
  return this.tabSelections.flatMap(selection => 
    selection.selectedDefects.map(() => ({
      sampleNo: selection.sampleNo,
      criticalScore: 3
    }))
  );
}

ngOnInit(): void {}

addTab() {
  let num = this.tabs.length + 1;
  this.tabs.push('Sample #' + num);
  // 新增标签时初始化选中状态
  this.tabSelections.push({
    sampleNo: this.tabs.length - 1,
    selectedDefects: []
  });
  this.selected.setValue(this.tabs.length - 1);
  this.tabtitle = '';
}

onDefectChange(tabIndex: number, defect: string, isChecked: boolean) {
  const tabSelection = this.tabSelections.find(t => t.sampleNo === tabIndex);
  if (!tabSelection) return;
  
  if (isChecked) {
    if (!tabSelection.selectedDefects.includes(defect)) {
      tabSelection.selectedDefects.push(defect);
    }
  } else {
    const defectIndex = tabSelection.selectedDefects.indexOf(defect);
    if (defectIndex > -1) {
      tabSelection.selectedDefects.splice(defectIndex, 1);
    }
  }
  console.log('所有选中项:', this.sampleScore);
}

// 按sampleNo统计总分
calculateTotalScore(): {sampleNo: number, totalScore: number}[] {
  return this.tabSelections.map(selection => ({
    sampleNo: selection.sampleNo,
    totalScore: selection.selectedDefects.length * 3
  }));
}

修改后的component.html

<button type="button" (click)="addTab()">Add Sample</button>
<mat-tab-group [selectedIndex]="selected.value" (selectedIndexChange)="selected.setValue($event)">
  <mat-tab *ngFor="let tab of tabs; let index = index" [label]="tab">
    <table id="criticalTable">
      <thead>
        <tr>
          <th scope="col">Defect Classification</th>
          <th scope="col">Action</th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let item of criticalDefects; let idx = index">
          <td>{{ item }}</td>
          <td style="width:30% ;">
            <div class="form-check">
              <input
                class="form-check-input"
                (change)="onDefectChange(index, item, $event.target.checked)"
                type="checkbox"
                id="checkboxCritical_{{ index }}_{{ idx }}"
                [checked]="tabSelections[index].selectedDefects.includes(item)"
              />
              <label class="form-check-label" for="checkboxCritical_{{ index }}_{{ idx }}">
                Defect
              </label>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
  </mat-tab>
</mat-tab-group>

<!-- 展示统计结果 -->
<div *ngIf="calculateTotalScore().length">
  <h3>Score Summary</h3>
  <ul>
    <li *ngFor="let summary of calculateTotalScore()">
      Sample #{{ summary.sampleNo + 1 }}: 总分 = {{ summary.totalScore }}
    </li>
  </ul>
</div>

关键修改点

  1. 取消DOM操作:改用tabSelections数组存储每个标签的选中缺陷,避免因mat-tab懒加载导致的DOM节点缺失问题。
  2. 持久化选中状态:新增标签时自动初始化对应选中状态对象,切换标签时通过[checked]指令保留之前的选择。
  3. 按需生成目标数组:通过getter属性sampleScore根据选中状态动态生成所需数组,无需手动维护重复数据。
  4. 直接统计总分:通过calculateTotalScore方法根据选中缺陷数量计算总分,无需依赖目标数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:15:36