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

利用索引解决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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:37:45