angular 在触摸之前阻止表单验证
angular prevent form validation until touched
在 Angular 8 个项目中,
我有一个创建和编辑组件。
我只是 duplicated/refactored 创建以进行编辑。
到达编辑模式后,组件订阅了下一个要编辑的对象的行为主题(因为它是行为主题,无论时间范围如何,我的组件都正确地实例化了对象)
在编辑案例中,我没有使用空值来实例化表单,而是直接使用恢复后的值来实例化它。
很好。
现在对于用户来说,实际上他正在编辑那个对象。
问题是首先要创建的对象当然已经满足表单验证条件,因此“提交”按钮突出显示并准备就绪。
我希望触摸的 属性 已经是验证条件,并且在触摸值之前禁用提交按钮。
(不同的是理想的,但感动是一个很好的起点)
现在我的编辑表单一开始是有效的,但我不想这样。
我不想 "hack" 通过设置一个字段的无效标志来实现这一点,因为我不会先发制人地知道用户想要编辑什么,我希望它是任何字段,并且用户只需编辑 1-n 个字段即可使表单有效。
对于Angular^8:
在为控件设置值后将表单标记为原始:
this.form.markAsPristine();
并添加提交按钮的条件,使其在表单未被触及时禁用:
<button type="submit" [disabled]="form.pristine">Save</button>
当您创建控件时,即任何扩展 AbstractControl 的类型,例如 FormGroup、FormControl、ArrayControl…
默认情况下它们将被标记为脏(当然除非您自己实现)。
因此,当您创建这样一个控件并为其分配验证器时,这些验证器将立即被触发。
例如,假设 ErrorOnValidate
是一个总是 return 错误的验证器,下面的 formGroup
将立即保存由验证器 return 编辑的错误。
const formGroup: FormGroup = new FormGroup(
{
key: new FormControl('value'),
},
{
validators: [ErrorOnValidate],
}
);
console.log(formGroup.valid); /// false
如何防止这种行为?
您需要先创建表单,然后将其设置为原始表单,然后只将验证程序附加到该表单。
const formGroup: FormGroup = new FormGroup(
{
key: new FormControl('value'),
}
);
formGroup.markAsPristine();
formGroup.setValidators([ErrorOnValidate]);
console.log(formGroup.valid); /// true
这样,当控制器被触摸时,formGroup 将 运行 验证器(因此在此示例中保持验证器的错误)。
但是……
现在你有了一个带有值和验证器的 FormGroup,在它被触摸之前不会做任何事情。但是,只要您将此 FormGroup 与输入绑定,输入就会触及控件并因此触发验证,这意味着所有这些努力都将失败。
另一种方法是创建一个不带任何验证器的 FormControl,并且仅在视图初始化后才将它们添加到表单中。
ngAfterViewInit(): void {
this.formGroup.setValidators([ErrorOnValidate])
}
在 Angular 8 个项目中,
我有一个创建和编辑组件。
我只是 duplicated/refactored 创建以进行编辑。
到达编辑模式后,组件订阅了下一个要编辑的对象的行为主题(因为它是行为主题,无论时间范围如何,我的组件都正确地实例化了对象)
在编辑案例中,我没有使用空值来实例化表单,而是直接使用恢复后的值来实例化它。
很好。
现在对于用户来说,实际上他正在编辑那个对象。
问题是首先要创建的对象当然已经满足表单验证条件,因此“提交”按钮突出显示并准备就绪。
我希望触摸的 属性 已经是验证条件,并且在触摸值之前禁用提交按钮。
(不同的是理想的,但感动是一个很好的起点)
现在我的编辑表单一开始是有效的,但我不想这样。
我不想 "hack" 通过设置一个字段的无效标志来实现这一点,因为我不会先发制人地知道用户想要编辑什么,我希望它是任何字段,并且用户只需编辑 1-n 个字段即可使表单有效。
对于Angular^8:
在为控件设置值后将表单标记为原始:
this.form.markAsPristine();
并添加提交按钮的条件,使其在表单未被触及时禁用:
<button type="submit" [disabled]="form.pristine">Save</button>
当您创建控件时,即任何扩展 AbstractControl 的类型,例如 FormGroup、FormControl、ArrayControl…
默认情况下它们将被标记为脏(当然除非您自己实现)。
因此,当您创建这样一个控件并为其分配验证器时,这些验证器将立即被触发。
例如,假设 ErrorOnValidate
是一个总是 return 错误的验证器,下面的 formGroup
将立即保存由验证器 return 编辑的错误。
const formGroup: FormGroup = new FormGroup(
{
key: new FormControl('value'),
},
{
validators: [ErrorOnValidate],
}
);
console.log(formGroup.valid); /// false
如何防止这种行为?
您需要先创建表单,然后将其设置为原始表单,然后只将验证程序附加到该表单。
const formGroup: FormGroup = new FormGroup(
{
key: new FormControl('value'),
}
);
formGroup.markAsPristine();
formGroup.setValidators([ErrorOnValidate]);
console.log(formGroup.valid); /// true
这样,当控制器被触摸时,formGroup 将 运行 验证器(因此在此示例中保持验证器的错误)。
但是…… 现在你有了一个带有值和验证器的 FormGroup,在它被触摸之前不会做任何事情。但是,只要您将此 FormGroup 与输入绑定,输入就会触及控件并因此触发验证,这意味着所有这些努力都将失败。
另一种方法是创建一个不带任何验证器的 FormControl,并且仅在视图初始化后才将它们添加到表单中。
ngAfterViewInit(): void {
this.formGroup.setValidators([ErrorOnValidate])
}