1

I'm trying to create a registration page with a password-confirm and email-confirm field where the user has to repeat their password and email. This is the setup of the FormGroup:

ngOnInit() {
this.basicInfo = this.formBuilder.group({
  userName: ['', [Validators.required, Validators.minLength(5)]],
  firstName: ['', Validators.required],
  lastName: ['',Validators.required],

  emails: this.formBuilder.group({
    email: ['', [Validators.required, Validators.email]],
    emailConfirm: ['', [Validators.required, Validators.email]],
  }, {validators: SignUpComponent.checkEmailMatch}),

  passwords: this.formBuilder.group({
    password: ['', [Validators.required]],
    passwordConfirm: ['', Validators.required]
  }, {validators: SignUpComponent.checkPasswordMatch})
});

The validator for the password fields is the following (the same for email):

static checkPasswordMatch(group: FormGroup) {
  let password = group.get('password');
  let passwordConfirm = group.get('passwordConfirm');
  if (password == null || passwordConfirm == null) return null; // prevent errors
  let match = password.value === passwordConfirm.value;
  if (!match) {
    passwordConfirm.setErrors({passwordMatchError: true});
    return {passwordMatchError: true};
  } else {
    return {passwordMatchError: null};
  }
}

Expected results

The validator should update whenever password or passwordConfirmed are edited, and add the appropriate error to the passwordConfirmed control if their values are not identical.

What actually happens

The error is only removed when passwordConfirmed is edited (adding the error works when either is edited)

Attempted solution

I tried modifying the if statement in the validator to remove the error from passwordConfirm:

if (!match) {
  passwordConfirm.setErrors({passwordMatchError: true});
  return {passwordMatchError: true};
} else {
  passwordConfirm.setErrors({passwordMatchError: null}); <-- this line
  return {passwordMatchError: null};
}

This does not remove the error, but instead just sets it to null. The control is still marked as invalid and the error is still there as indicated by this log to the console:

console log showing error

Are there any other ways of manually removing an error from a form control or is there another way to solve this?

(Angular & Angular forms version 7.2.0)

Alex
  • 634
  • 10
  • 29
  • You need to return `null` (considered valid) and not `{passwordMatchError: null};` – AT82 Jan 20 '19 at 19:59
  • Good point, but that only removes the error on the parent group and not the child control as the validator is on the group level and not on the individual control. – Alex Jan 20 '19 at 20:15

1 Answers1

1

You need to not manually set an error with setErrors. With custom validators you need to just return

return { myErrorName: true };

when it's not valid, and simply

return null;

when it's valid.

So modify your validator to this:

checkPasswordMatch(group: FormGroup) {
  let password = group.get('password');
  let passwordConfirm = group.get('passwordConfirm');
  if (!password && !passwordConfirm) return null;
  let match = password.value === passwordConfirm.value;
  return match ? null : { passwordMatchError: true};
}

DEMO

AT82
  • 71,416
  • 24
  • 140
  • 167
  • I'm using angular material ui and want the error to show up on the actual form field and not the parent group. – Alex Jan 20 '19 at 20:20
  • Is there a reason for that, now you are setting the custom validator on the form group and not the field, so why are you then doing that on the group? :P – AT82 Jan 20 '19 at 20:24
  • ... but of course, the issue is that if you were to set the custom validator on the formcontrol, it wouldn't fire when `password` field is edited. But my question is rather why it cannot be on the formgroup. Of course you can do some workaround for that if you really need it for some reason :) – AT82 Jan 20 '19 at 20:34
  • The problem is that, from a ui perspective, it does not show the error under the form field the way it is supposed to if the form group has the error. If the control itself has the error then it looks fine. – Alex Jan 20 '19 at 20:38
  • Here is the difference https://imgur.com/a/JxJY8HJ (i want the top one) – Alex Jan 20 '19 at 20:39
  • This is then basically a duplicate of a previous question. You need a custom error state matcher with angular material. I'll mark this as a duplicate... – AT82 Jan 20 '19 at 20:43