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() 的实例一致。
备注:内容仅供参考。
