一个页面的“新增”和“修改”共用同一个弹窗,表单中有文件名和地址两个必填字段。先点修改、关闭,再点新增,空白表单刚打开就显示红色错误提示。
这里通常需要区分三件事:字段当前是否合法、用户是否已经交互、这一次是否提交过。清空字段值,不等于所有交互状态都回到了初始状态。
每次打开时重建表单
原来的处理思路是把创建表单的代码从只执行一次的初始化入口,移动到每次新增或编辑的入口。下面以响应式表单为例:
createForm(value = { name: '', url: '' }) {
this.myForm = this.fb.group({
name: [value.name, Validators.required],
url: [value.url, Validators.required]
});
this.submitted = false;
}
openCreate() {
this.createForm();
}
openEdit(record: { name: string; url: string }) {
this.createForm({ name: record.name, url: record.url });
}
示例中的 fb 为已注入的 FormBuilder,使用 @angular/forms 的 Validators,并按项目方式导入 ReactiveFormsModule。
不需要先去掉 required,再加回来。新增表单可以一开始就不满足必填校验,只是尚未到展示错误的时机。
也可以重置现有 FormGroup
如果希望保留同一表单对象,可以传入明确的默认值:
this.myForm.reset({ name: '', url: '' });
this.submitted = false;
FormGroup.reset 会重置值及相关交互状态,具体选项见 FormGroup 文档。若模板使用了 FormGroupDirective 自身的 submitted 状态,还要通过对应的 resetForm 处理,不能只重置组件中的一个同名布尔变量。FormGroupDirective
错误提示应有显示条件
例如,必填错误只在字段被触碰或当前表单已尝试提交后显示:
<p *ngIf="myForm.get('name')?.hasError('required')
&& (myForm.get('name')?.touched || submitted)">
请填写文件名
</p>
这是使用 *ngIf 的模板示例,项目需有相应指令支持。重点在判断条件,而不是必须选择某种模板写法。
复用弹窗还要清理什么
检查编辑对象是否被直接绑定并修改,异步加载是否在弹窗关闭后继续回填,以及表单订阅是否因每次重建而重复注册。重建对象时应释放旧订阅;复用对象时应重置本轮状态。
最后验证“新增—关闭—编辑—关闭—新增”等多种顺序。让提示不变红只是视觉结果,真正目标是每次打开都具有正确的初值、校验和提交语义。