Reputation: 2610
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;
}
}
Upvotes: 14
Views: 23206
Reputation: 81
In addition to the G. Tranter comment, to see the mat-error element, the form field have to be touched. You can force it with the line
this.myForm.get('password2').markAsTouched();
Upvotes: 0
Reputation: 145910
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.
Upvotes: 4
Reputation: 17918
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;
}
Upvotes: 45