利用索引解决Angular多表单按钮禁用联动异常问题
解决方案
问题根源是所有循环生成的表单共用了同一个Form实例,任意一个表单的修改都会让这个全局表单变为dirty状态,导致所有按钮同步解锁。要解决这个问题,需要为每个任务创建独立的表单实例,具体步骤如下:
1. 组件中创建表单数组
在组件类里定义数组存储每个任务对应的FormGroup,并在初始化任务数据时,为每个任务生成独立表单:
import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; @Component({ // 组件元数据(保留你原有的配置) }) export class YourComponent implements OnInit { tasks: any[] = []; // 你的任务数据集 taskForms: FormGroup[] = []; isCollapsed: boolean[] = []; constructor(private fb: FormBuilder) {} ngOnInit(): void { // 加载任务数据(替换成你实际的数据获取逻辑) this.getTasks().then(() => { // 为每个任务生成独立表单 this.tasks.forEach(() => { const taskForm = this.fb.group({ tests: this.fb.group({ id1: [''], id2: [''], id3: [''], id4: [''], id5: [''] }) }); this.taskForms.push(taskForm); this.isCollapsed.push(false); // 初始化折叠状态 }); }); } getTasks(): Promise<any> { // 模拟数据加载,实际替换为接口请求 return Promise.resolve([ { id: 1, name: '任务1' }, { id: 2, name: '任务2' } ]); } onSave(index: number, taskId: number): void { const targetForm = this.taskForms[index]; if (targetForm.valid && targetForm.dirty) { // 执行保存逻辑,使用targetForm.value获取当前任务的表单数据 console.log(`保存任务${taskId}数据:`, targetForm.value); // 保存完成后重置表单dirty状态,让按钮重新禁用 targetForm.markAsPristine(); } } }
2. 修改模板绑定
将模板中原有的共用Form替换为对应索引的taskForms[i],并更新按钮的禁用判断条件:
<div class="div-table-row"> <div *ngFor="let item of items" class="div-table-col h6"> {{ item }} </div> </div> <div *ngFor="let task of tasks; let i = index" class="div-table-row"> <div class="div-table-col">{{ task.id }}</div> <div class="div-table-col">{{ task.name }}</div> <a class="btn-toogle" (click)="isCollapsed[i] = !isCollapsed[i]"> {{isCollapsed[i] ? "隐藏" : "显示"}} <mdb-icon fas icon="{{ isCollapsed[i] ? 'up' : 'down' }}"></mdb-icon> </a> <div *ngIf="isCollapsed[i]" class="div-container"> <h6 class="mb-3 mt-3 h6">{{ task.name }}</h6> <!-- 绑定当前索引对应的独立表单 --> <form [formGroup]="taskForms[i]"> <div formGroupName="tests"> <div class="row form-group"> <div class="col-sm-4"> <input formControlName="id1" type="number" class="form-control" /> </div> <div class="col-sm-4"> <input formControlName="id2" type="number" class="form-control" /> </div> <div class="col-sm-4"> <input formControlName="id3" type="number" class="form-control" /> </div> </div> <div class="row form-group"> <div class="col-sm-4"> <input formControlName="id4" type="number" class="form-control" /> </div> <div class="col-sm-4"> <input formControlName="id5" type="text" class="form-control" /> </div> <!-- 基于当前表单的dirty状态判断禁用 --> <button [disabled]="!taskForms[i].dirty" (click)="onSave(i, task.id)"> Zapisz </button> </div> </div> </form> </div> </div>
核心说明
- 每个任务对应独立的
FormGroup,修改某一个任务的表单只会改变该表单的dirty状态,不会影响其他任务的按钮状态。 - 保存完成后调用
markAsPristine()可以重置表单的dirty标记,让按钮重新回到禁用状态。
内容的提问来源于stack exchange,提问作者rdsm2
相关产品推荐
相关产品推荐

