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>
关键修改点
- 取消DOM操作:改用
tabSelections数组存储每个标签的选中缺陷,避免因mat-tab懒加载导致的DOM节点缺失问题。 - 持久化选中状态:新增标签时自动初始化对应选中状态对象,切换标签时通过
[checked]指令保留之前的选择。 - 按需生成目标数组:通过getter属性
sampleScore根据选中状态动态生成所需数组,无需手动维护重复数据。 - 直接统计总分:通过
calculateTotalScore方法根据选中缺陷数量计算总分,无需依赖目标数组。
内容的提问来源于stack exchange,提问作者Rak
相关产品推荐
相关产品推荐

