I have a confirm password formcontrol that I want to validate.
I want to display my mat-error element when the password is not the same as the value in the confirm password input. For this I have a function called equalPasswords()
. If the functions are the same then we receive true, if not, we receive false.
<mat-form-field>
<input matInput placeholder="Repeat password" [formControl]="password2" type="password">
<mat-error *ngIf="password2.invalid && password2.hasError('required')">Password is required</mat-error>
<mat-error *ngIf="!equalPasswords() && !password2.hasError('required')">Passwords need to match</mat-error>
</mat-form-field>
I checked the console and when I enter two different inputs in the password boxes it equalPasswords() returns false. It however still doesn't show the error in the DOM.
Does someone know how to fix this?
Signup.component.ts
@Component({
selector: 'app-sign-up',
templateUrl: 'sign-up.component.html',
styleUrls: ['sign-up.component.css']
})
export class SignUpComponent implements OnInit {
mySignupForm: FormGroup;
countries = countries;
uniqueUsernameMessage;
uniqueEmailMessage;
formSubmitted = false;
@Output() closeSubmenu = new EventEmitter();
@ViewChild('select') select;
constructor(
private authService: AuthenticationService,
private route: Router,
private navigationService: NavigationService){}
get firstName() { return this.mySignupForm.get('firstName'); }
get lastName() { return this.mySignupForm.get('lastName'); }
get username() { return this.mySignupForm.get('username'); }
get email() { return this.mySignupForm.get('email'); }
get password1() { return this.mySignupForm.get('password1'); }
get password2() { return this.mySignupForm.get('password2'); }
get birthDate() { return this.mySignupForm.get('birthDate'); }
get country() { return this.mySignupForm.get('country'); }
get house() { return this.mySignupForm.get('house'); }
ngOnInit() {
this.mySignupForm = new FormGroup({
firstName: new FormControl(null, Validators.required),
lastName: new FormControl(null, Validators.required),
username: new FormControl(null, [Validators.required, Validators.minLength(5), Validators.maxLength(15)]),
birthDate: new FormControl(null, Validators.required),
password1: new FormControl(null, [Validators.required, Validators.minLength(6), Validators.maxLength(15), Validators.pattern('^.*(?=.{4,10})(?=.*\\d)(?=.*[a-zA-Z]).*$')]),
password2: new FormControl(null, Validators.required),
email: new FormControl(null, [Validators.required, Validators.email]),
country: new FormControl(null, Validators.required),
house: new FormControl(null, Validators.required)
})
}
equalPasswords() {
console.log('equaltest', this.password1.value === this.password2.value);
return this.password1.value === this.password2.value;
}
}
MatFormField
only displays mat-error
elements when the FormControl
has an error. It does not display just because you tell it to via ngIfElse
- that would only work subject to the form control state. One way to solve this problem is to create a custom validator and use it to check that the passwords match. You could also set an error on the field from your equalPasswords()
function. That should be something like:
equalPasswords(): boolean {
const matched: boolean = this.password1.value === this.password2.value;
console.log('equaltest', matched);
if (matched) {
this.signupForm.controls.password2.setErrors(null);
} else {
this.signupForm.controls.password2.setErrors({
notMatched: true
});
}
return matched;
}
I discovered asubtle situation where this can occur.
If you add a [formGroup]
directive on something like a <div>
then it will not get submitted == true
when the form is submitted (it must be on a <form>
for that to occur).
The form being submitted is one of two triggers for displaying the error - the other is for the field to have been touched. And touched means onBlur
which means the focus must have been lost.
So you can get this situation:
You have [formGroup]
on a div
You have something like a username / password form.
You also have a submit button.
You enter both fields and hit enter.
Your validation triggers an error but it doesn't show! WHY!
Because you never blur
-ed the password field (take a look at your cursor - it's still in the password field isn't it!)
The easiest solution is to only ever add [formGroup]
to a <form>
tag
The other is to create a custom ErrorStateMatcher
If you are passing a formGroup
to a 'dumb' child component via an @Input (that is to a dumb component that doesn't manage its own form) you can use dependency injection and pass in the FormGroupDirective
instead in the constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With