我的验证甚至自定义验证在使用mat-error和反应式表单时都运行良好,但是我试图直观地实现服务器端错误,结果一团糟。
我的服务器端错误是通过自定义验证器实现的,该自定义验证器检查存储在this.serverErrors中的n个表达验证器映射的错误响应。
发生的问题是,我希望在更新值或整个表单时删除错误,以便我可以使用禁用的提交按钮(这是可选的,但需要的功能)
我还通过ngIfs在每个控件中使用了多个错误。
请有人指出正确的方向来处理服务器端错误,最好使用mat-errors显示吗?
谢谢。
export class ServerForm implements OnInit {
public serverErrors;
public form: FormGroup;
constructor(
private formBuilder: FormBuilder,
private routing: Router
) {}
ngOnInit() {
this.form.valueChanges.subscribe(changes => {
if (this.hasErrors()) {
// For each error, check if expiryField values are outdated mandating error reset.
Object.keys(this.serverErrors).forEach(error => {
let serverError = this.serverErrors[error];
// If error outdated, remove and reset validation.
if (this.checkServerErrorOutdated(serverError)) {
// Remove may only remove error text but control may still be invalid.
this.removeServerError(error);
this.triggerControlValidation(serverError.control);
}
});
}
});
}
checkServerErrorOutdated(serverError) {
let outdated = false;
// Default check to param, replace with expiry fields if exist.
let expiryChecks = [ serverError.param ];
if ('expiryFields' in serverError) {
expiryChecks = serverError.expiryFields;
}
// For each expiry field check if a value has updated, thus expiring the error.
expiryChecks.forEach(check => {
let invalidValue = serverError.invalidValues[check];
let currentValue = serverError.control.parent.value[check];
if (currentValue !== invalidValue) { outdated = true; }
});
return outdated;
}
triggerControlValidation(control) {
control.markAsTouched();
control.updateValueAndValidity();
}
triggerValidation() {
Object.keys(this.form.controls).forEach(field => {
let control = this.form.get(field);
this.triggerControlValidation(control);
});
}
serverErrorValidator(errorKeyCode, errorKey, expiryFields?): ValidatorFn {
// May need to add server error keys to class property...
return (control: AbstractControl): {[ key: string ]: any} | null => {
let value = control.value;
let error = {}; error[errorKeyCode] = value;
let serverError = this.getServerError(errorKey);
if (serverError) {
// Add form values and control to error.
serverError.invalidValues = control.parent.value;
serverError.control = control;
// Add fields which trigger error expiration to error.
if (expiryFields) {
serverError.expiryFields = expiryFields
}
}
return serverError ? error : null;
};
}
removeServerError(type) {
if (type in this.serverErrors)
delete this.serverErrors[type];
}
clearServerErrors() {
Object.keys(this.serverErrors).forEach(field => {
this.removeServerError(field);
});
}
getServerErrorMsg(type) {
let error = this.getServerError(type);
return error ? error.msg : null;
}
getServerError(type) {
let error = null;
if (this.hasErrors() && type in this.serverErrors) {
error = this.serverErrors[type];
}
return error ? error : null;
}
hasErrors() {
return Boolean(this.serverErrors);
}
handleErrors(response) {
if ('errors' in response) {
this.serverErrors = response.errors;
} else {
this.clearServerErrors();
}
}
}
答案 0 :(得分:2)
我添加到答案中的代码实现了我想要的。
我遇到的问题是由于找到了一个可以重新验证的地方,但并没有立即消除valueChange上的错误,因为valueChanges事件发射器触发得太频繁了(即使是提交/单击按钮)。