我正在尝试创建一个自定义的MatFormFieldControl,它也实现了ControlValueAccessor。
我想从一个已知的用例开始:密码表单。
计划:创建一个表单字段,该字段获取单个字符串,但在其中包含自己的表单,以对confirmPassword字段添加验证。
我创造了一个StackBlitz with a working implementation。
每次调用错误状态变量时,我都会检查两个字段之间是否存在不匹配,并更新ngControl上的错误,以便它可以反映到外部。
首先正确显示错误状态,但如果您匹配密码而不是再次错配它们,则会抛出此错误:
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: null'. Current value: 'ngIf: [object Object]'.
我在网上找不到很多关于这个的文档,我不确定什么时候将错误添加到错误对象的正确位置
谁知道我怎么能避免这个错误?
提前致谢
get errorState() {
const missmatch = this.weightForm.value.password !== this.weightForm.value.confirmPassword;
if (missmatch) {
this.ngControl.control.setErrors({ missmatch }, { emitEvent: false });
}
return (this.ngControl.errors !== null || missmatch) && !!this.ngControl.touched;
}
这里的想法是创建一个“关注点分离”,外部形式不知道confirmPassword,因为它更像是一个“验证”字段,而不是“数据”字段,如果这是有道理的。
这种关注点分离的另一个例子是将代码编辑器作为表单字段,并使代码编辑器验证反映到外部,而不将代码编辑器本身暴露给外部。
测试你的StackBlitz示例我已经看到删除app.component上的* ngIf mat-error解决问题保持不变的表单输入的“错误报告功能”,我不知道这是否可以解决你的问题真实的网站,但我认为值得一试。
但我真正建议你做这种工作(密码匹配验证)是依靠Angular表单验证器(这里形式文档:https://angular.io/guide/form-validation)这种方法更安全,因为你不需要通过变量强制进行错误检查,但是单独理解字段是否无效的形式。
没有标准的验证器可以检查2个字段是否包含相同的文本,但是您可以构建自己想要的自定义验证器。
如果这有用,我将分享我通常用于密码检查的自定义验证器的语法(仅作为跟踪,确保您必须修改某些内容才能使其正常工作):
export function mismatchValidator(): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
if (control.parent) {
if (control.parent.get('password').value !== control.parent.get('password_confirmation').value) {
return {mismatch: true};
} else {
return null;
}
} else {
return null;
}
};
}
有关如何实现表单控制器,验证器和自定义验证器的其他信息可以在Angular站点上找到。
这是关于你的问题的一个有趣的article,如果你选择不实现表单验证器,它可能有助于你理解你的问题所在。