Я пытаюсь создать собственный валидатор для mat-input
. Все работает правильно, ошибка отображается при возникновении ошибки, но после устранения ошибки mat-form-field
не удаляет класс mat-form-field-invalid
https://imgur.com/a/MSsaVop
class CrossFieldErrorMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective |
NgForm | null): boolean {
return control.dirty && form.invalid;
}
}
errorMatcher = new CrossFieldErrorMatcher();
register = this.fb.group({
userName: ['', [Validators.required]],
userEmail: ['', [Validators.required, Validators.email]],
phone: ['', [Validators.required, this.phoneNumberValidator]],
userPassword: ['', [Validators.required]],
passwordconfirm: ['', ],
adminName: ['', [Validators.required]],
adminPassword: ['', [Validators.required]],
}, {
validator: this.passwordValidator
})
passwordValidator(form: FormGroup) {
const condition = form.get('passwordconfirm').value !==
form.get('userPassword').value;
return condition ? { passwordsDoNotMatch: true } : null;
}
<mat-form-field class = " my-4 ">
<input matInput type = "password" required
formControlName = "userPassword" placeholder = "Password"
[type] = "hide ?'password' : 'text'" class = "col-4" name = "password">
</mat-form-field>
<mat-form-field class = " my-4 ">
<input matInput type = "password" required
formControlName = "passwordconfirm" placeholder = "Confirm
Password"
[type] = "hide2 ? 'password' : 'text'" class = "col-4"
[errorStateMatcher] = "errorMatcher" name = "conpassword">
<mat-error *ngIf = "register.hasError('passwordsDoNotMatch')">
Passwords do not match!
</mat-error>
</mat-form-field>
Проблема в том, что ваш CrossFieldErrorMatcher
использует всю форму для проверки паролей, когда все, что вам действительно нужно, — это просмотреть подмножество этой формы.
Чтобы исправить это, просто добавьте отдельный FormGroup
для элементов паролей, чтобы ваша форма выглядела так:
register = this.fb.group({
userName: ['', [Validators.required]],
userEmail: ['', [Validators.required, Validators.email]],
phone: ['', [Validators.required, this.phoneNumberValidator]],
// Create a separate FormGroup here to isolate the scope
passwords: this.fb.group({
userPassword: ['', [Validators.required]],
passwordconfirm: [''],
}, { validator: this.passwordValidator }),
adminName: ['', [Validators.required]],
adminPassword: ['', [Validators.required]]
})
А затем в своем шаблоне просто «оберните» элементы пароля в div
, указав этот новый FormGroup
как его FormGroup
вот так:
<div [formGroup] = "register.get('passwords')"> // Assign the new FormGroup
<mat-form-field class = " my-4 ">
<input matInput type = "password" required
formControlName = "userPassword" placeholder = "Password"
[type] = "hide ?'password' : 'text'" class = "col-4" name = "password">
</mat-form-field>
<mat-form-field class = " my-4 ">
<input matInput type = "password" required
formControlName = "passwordconfirm" placeholder = "Confirm Password"
[type] = "hide2 ? 'password' : 'text'" class = "col-4"
[errorStateMatcher] = "errorMatcher" name = "conpassword">
<mat-error *ngIf = "register.get('passwords').hasError('passwordsDoNotMatch')">
Passwords do not match!
</mat-error>
</mat-form-field>
</div>
Я отредактировал свой пост, это должно решить вашу проблему! Также ваш Stackblitz не работает. Похоже, вам не хватает нескольких запятых (,
).
Вам нужно вернуть CrossFieldErrorMatcher
обратно в return control.dirty && form.invalid;
, потому что теперь, когда у паролей есть собственная форма, errorStateMatcher
может использовать эту форму с ограниченной областью для изолированной проверки.
Приятно это слышать и рад, что помог!
извините, но это не сработало stackblitz.com/edit/mat-error-parent-validation-yyt6f5