I am using Angular 5 Reactive forms
, and have setup a form group
say confirmEmail
with two form controls
as email
and confirmEmail
. I have further added a validator
to my form group
and the form controls
have required
validations attached.
My use case is
: I want to trigger the custom validation
based on the value of the individual form controls and if the custom validator returns as invalid
, mark the form controls as having errors.
My issue is that
: Once the form controls
are marked with errors, custom validator (which is on form group) does not trigger until I touch both of the form controls again and change the values for both of them.
I would ideally want to just update one of the fields (to match the other one) and be able to trigger the custom validation again.
Sample code:
@Component({...})
export class FormComponent implements OnInit {
user: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.user = this.fb.group({
data: this.fb.group({
email: ['', Validators.required],
confirmEmail: ['', Validators.required]
}, , { validator: validateEmail })
});
}
const validateEmail = (control: AbstractControl): {[key: string]: boolean} => {
const email = control.get('email');
const confirmEmail = control.get('confirmEmail');
if (email.value === confirmEmail.value) {
return null;
} else {
this.setFieldAsInvalid(email);
this.setFieldAsInvalid(confirmEmail);
return { nomatch: true };
}
};
private setFieldAsInvalid(field: AbstractControl) {
field.setErrors({
'invalid': true
});
}
}
Any suggestions to fix this or any other approach I should take.
You are changing controls(email and confirmEmail) into invalid when they keep different values, but return null
in ValidatorFun will only change current formcontrol's valid to true, not all email and confirmEmail.
Solution1:
You can change email and confirmEmail back to valid via field.setErrors(null)
when they keep same value.
if (email.value === confirmEmail.value) {
// clear custom error for all related controls
this.setFieldAsValid(email);
this.setFieldAsValid(confirmEmail);
return null;
} else {
this.setFieldAsInvalid(email);
this.setFieldAsInvalid(confirmEmail);
return { nomatch: true };
}
private setFieldAsValid(field: AbstractControl) {
field.setErrors(null);
}
see fixed demo.
Solution2:
If you only care about error nomatch
, you can track on formgroup data
to see whether it has error of nomatch
like below(also included in above demo's template part):
this.user.get('data').hasError('nomatch')
Mention that This way will leave the other formcontrol to be invalid.