PAYATHON 2026

Angular Signal Forms 提交后如何重置校验提示和 touched 状态?

数据小陈

提交成功后,在表单根节点调用 this.addForm().reset(),可以重置整个表单及其子字段的 touched 和 dirty 状态。再次打开弹窗时,原有的 invalid() && touched() 条件就不会因上一次操作而立即显示错误。

以下方案适用于使用 @angular/forms/signals 且项目版本提供 FieldState.reset() 的情况。原问题没有提供 Angular 版本。

为什么再次打开弹窗会显示错误?

模板中的两个条件同时成立时,才会显示错误:

addForm.name().invalid() && addForm.name().touched()

如果关闭弹窗后仍复用同一个 addForm 实例,字段的交互状态也会保留。只清空输入值不会重置这些状态:空值可能触发必填校验,而保留的 touched 状态会让错误提示立即出现。

原片段没有展示提交和关闭弹窗的逻辑,无法确定状态在哪一步被保留。可以先尝试通过表单的重置 API 清除交互状态。

提交成功后重置交互状态

在现有组件中加入以下方法,并在设备保存成功后调用:

resetAddFormState(): void {
  this.addForm().reset();
}

reset() 要在 addForm() 返回的字段状态对象上调用,因此写法是 this.addForm().reset()。

根据 Angular 的 FieldState API 文档,reset() 会重置当前字段及其所有后代字段的 touched 和 dirty。不传参数时,模型数据保持原值;传入值时,也会更新模型数据。

如果每次点击“添加设备”都代表开始一条新记录,也可以在打开弹窗前重置。具体选择哪个时机,取决于关闭后是否需要保留未提交的内容。保存失败时应保留输入和错误提示,不要无条件重置。

需要清空输入值时,传入完整的初始模型

单独调用 reset() 不会清空输入。如果还需要清空表单,可以传入初始值。例如,假设模型只有 name 字段:

this.addForm().reset({ name: '' });

如果实际设备模型还有其他字段,应提供符合模型类型的完整初始对象。

重置后,空的必填字段仍可能满足 invalid() === true。校验规则仍然有效,只是 touched() 已恢复为 false,所以错误暂时不会显示。

保留现有的错误显示条件

现有条件可以继续使用。原片段缺少外层 @if 的结束花括号,补齐后的模板如下:

@if (addForm.name().invalid() && addForm.name().touched()) {
  <div class="error">
    @for (error of addForm.name().errors(); track error.kind) {
      <span>{{ error.message }}</span>
    }
  </div>
}

如果重置后提示仍立即出现,检查打开弹窗的代码是否再次调用了 markAsTouched(),以及提交逻辑是否再次触发了该状态。还要确认模板绑定的表单实例与执行 reset() 的实例一致。

备注:内容仅供参考。