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

Angular17响应式表单FormArray删除元素后DOM未正确更新

问题根源

你遇到的DOM未正确更新问题,核心原因是removeFilm方法中多余的reset调用:

this.addVehicleForm.reset(this.addVehicleForm.value);

当调用films.removeAt(index)后,FormArray已经正确移除了对应元素,表单值也同步更新。但随后的reset操作会强制将表单重置为当前值,这个过程会打乱Angular表单控件与DOM的绑定关系,导致DOM显示的内容跟不上表单状态变化。

另外,HTML模板中存在未在FormGroup中定义的控件绑定:

<input type="hidden" name="id" formControlName="id" />

createFilmFormGroup方法返回的FormGroup里并没有id这个FormControl,这会导致表单出现无效状态,也可能间接影响DOM更新。

解决方案
  1. 移除不必要的reset调用:删除removeFilm中的this.addVehicleForm.reset(this.addVehicleForm.value);语句,removeAt本身已经足够修改FormArray并触发变更检测。
  2. 修正未定义的控件绑定:要么在createFilmFormGroup中添加id控件,要么删除HTML中的hidden input。
  3. 无需额外调用updateValueAndValidity()、appRef.tick()或cdr.detectChanges(),Angular响应式表单的变更会自动触发DOM更新。
修正后的代码

TypeScript代码

import { CommonModule } from '@angular/common';
import { ChangeDetectorRef, Component } from '@angular/core';
import {
  FormArray,
  FormBuilder,
  FormGroup,
  ReactiveFormsModule,
} from '@angular/forms';

@Component({
  selector: 'app-add-vehicle',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
  templateUrl: './add-vehicle.component.html',
  styleUrl: './add-vehicle.component.scss',
})
export class AddVehicleComponent {
  constructor(
    private fb: FormBuilder,
    private cdr: ChangeDetectorRef
  ) {}

  addVehicleForm = this.fb.group({
    make: [''],
    model: [''],
    year: [''],
    films: this.fb.array([this.createFilmFormGroup()]),
  });

  createFilmFormGroup(): FormGroup {
    return this.fb.group({
      title: [''],
      releaseDate: [''],
      url: [''],
      // 如果需要id控件,添加这行
      // id: ['']
    });
  }

  get films(): FormArray {
    return this.addVehicleForm.get('films') as FormArray;
  }

  addFilm() {
    this.films.push(this.createFilmFormGroup());
  }

  removeFilm(index: number) {
    this.films.removeAt(index);
    // 极端情况下若仍有更新问题,可保留此行,但一般不需要
    // this.cdr.detectChanges();
  }
}

HTML模板

<div>
  <h1>Add Vehicle</h1>
  <form [formGroup]="addVehicleForm">
    <div class="form-group">
      <label for="make">Vehicle Make</label>
      <input
        type="text"
        class="form-control"
        id="make"
        formControlName="make"
      />
    </div>
    <div class="form-group">
      <label for="model">Vehicle Model</label>
      <input
        type="text"
        class="form-control"
        id="model"
        formControlName="model"
      />
    </div>
    <div class="form-group">
      <label for="ManufactureYear">Manufacture year</label>
      <input
        type="text"
        class="form-control"
        id="ManufactureYear"
        formControlName="year"
      />
    </div>

    <div style="border: 1px solid black; border-radius: 10px; padding: 10px">
      <div formArrayName="films">
        @for (film of films.controls; track $index) {
        <div
          [formGroupName]="$index"
          style="
          border-bottom: 1px solid #222;
          padding: 10px;
          margin-bottom: 10px;
        "
        >
          <!-- 移除未定义的id控件,或在FormGroup中添加id后保留 -->
          <!-- <input type="hidden" name="id" formControlName="id" /> -->
          <div class="form-group">
            <label [for]="'title' + $index">Title</label>
            <input
              type="text"
              class="form-control"
              [id]="'title' + $index"
              formControlName="title"
            />
          </div>
          <div class="form-group">
            <label [for]="'releaseDate' + $index">Release Date</label>
            <input
              type="text"
              class="form-control"
              [id]="'releaseDate' + $index"
              formControlName="releaseDate"
            />
          </div>
          <div class="form-group">
            <label [for]="'url' + $index">URL</label>
            <input
              type="text"
              class="form-control"
              [id]="'url' + $index"
              formControlName="url"
            />
          </div>
          <button type="button" (click)="removeFilm($index)">
            Remove Film
          </button>
        </div>
        }
      </div>
      <button type="button" (click)="addFilm()">Add Film</button>
    </div>
  </form>

  <pre>
  {{ addVehicleForm.value | json }}
</pre
  >
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:10:53