I'm trying to validate a form using custom validation. For some reason I have to build a form that can change either E-Mail or set a new Password. For that reason I cannot use Validators.required as password fields become only required when they are touched.
My problem is that when input validation is resolved the form is still invalid.
I've made a plnkr to demonstrate my problem:
http://plnkr.co/edit/obF4gC5RHkXOOlCEsIuH?p=preview
ngOnInit(): void {
this.emailField = new FormControl('mail@mail.com', Validators.email);
this.pw1 = new FormControl('', [this.passwordAreEqualValidator, Validators.minLength(2)]);
this.pw2 = new FormControl('', this.passwordAreEqualValidator);
this.pwOld = new FormControl('', this.notEmptyIfNewIsTouchedValidator);
this.form = this.formBuilder.group({
pw1: this.pw1,
pw2: this.pw2,
emailField: this.emailField,
pwOld: this.pwOld
});
}
notEmptyIfNewIsTouchedValidator(control: FormControl) : ValidationErrors | null {
if (control.dirty) {
if (control.value === '') {
return {
oldPasswordEmpty: true
}
}
const parent = control.parent,
pw1 = parent.get('pw1'),
pw2 = parent.get('pw2');
// this will trigger nothing in template, this part is only
// to mark form invalid if password was entered. passwordNew1
// cannot be false by default as this is okay when you only
// want to change your e-mail adress.
if (pw1.value.length === 0) {
pw1.setErrors({noPassword: true});
} else {
if (pw1.hasError('noPassword')) {
let pw1Errors = pw1.errors;
delete pw1Errors.noPassword;
pw1.setErrors(pw1Errors);
}
}
console.log('pw1 errors: ', pw1.errors);
console.log('pw2 errors: ', pw2.errors);
console.log('old errors: ', control.errors);
}
return null;
}
passwordAreEqualValidator(control: FormControl): ValidationErrors | null {
if (control.dirty) {
const
parent = control.parent,
pwOld = parent.get('pwOld'),
pw1 = parent.get('pw1'),
pw2 = parent.get('pw2');
if (pwOld.value === '') {
pwOld.setErrors({oldPasswordEmpty: true})
}
if (pw1.value !== pw2.value) {
return {
notEqual: true
};
} else {
let pw1Errors = pw1.errors;
if (pw1.hasError('notEqual')) {
delete pw1Errors.notEqual;
pw1.setErrors(pw1Errors);
}
if (pw1.hasError('noPassword')) {
delete pw1Errors.noPassword;
pw1.setErrors(pw1Errors);
}
pw2.setErrors(null);
console.log('pw1 errors: ', pw1.errors);
console.log('pw2 errors: ', pw2.errors);
console.log('old errors: ', pwOld.errors);
}
}
return null;
}
Steps to reproduce:
- Enter a password (error old password is empty shows up)
- Repeat Password (error password are not equal shows up until both password matches)
- once your repeating password is matching add a value for old password (error old password is removed)
- all validation errors are removed, but still form is not valid.
Why is my form invalid?
P.S: Once I edit my pw1 again, my form becomes valid, although the result of the errors did not change.