*Update
To create a customFormControl over a control, we use parent, see an example
checkPasswords(): ValidatorFn {
//see that the argument is a FormControl
return (control: FormControl): ValidationErrors => {
//the formGroup is control.parent
const group = control.parent as FormGroup;
//but we must sure that is defined
if (!group) return null;
console.log(group.get("password").value);
let pass = group.get("password").value;
let confirmPass = group.get("passwordConfirm").value;
return confirmPass ? pass === confirmPass ? null : { mismatch: true } : null;
};
}
As we want to make check when password change too
ngOnInit() {
this.form.get("password").valueChanges.subscribe(() => {
this.form.get("passwordConfirm").updateValueAndValidity();
});
}
See that the form is like
form = new FormGroup({
password: new FormControl("", Validators.required),
passwordConfirm: new FormControl("", [
Validators.required,
this.checkPasswords()
])
});
And the .html
<form [formGroup]="form" class="example-form">
<mat-form-field class="example-full-width">
<input matInput placeholder="password" formControlName="password">
<mat-error >
required
</mat-error>
</mat-form-field>
<mat-form-field class="example-full-width">
<input matInput placeholder="repeat password" formControlName="passwordConfirm"
>
<mat-error *ngIf="form.get('passwordConfirm').hasError('mismatch')">
must matcher
</mat-error>
<mat-error *ngIf="form.get('passwordConfirm').hasError('required')">
required
</mat-error>
</mat-form-field>
</form>
The stackblitz here
The other way is using a custom errorStateMatcher
Update 2 I said that other way is “use a errorStateMatcher.” A erroStateMatcher is a simple function that return true or false. If return true, our control will be marked as if he was invalid(*)
Imagine we has a form like
form = new FormGroup({
password: new FormControl("", Validators.required),
passwordConfirm: new FormControl("", [
Validators.required,
])
},this.checkPasswords());
See that error is belong to formGroup, we can create a customErrorMatcher that return true if control is invalid or if form.hasError(‘mismatch`)
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
return !!((control && form.hasError('mismatch') || control.invalid) && control.touched );
}
}
Well, the .html
<form [formGroup]="form" class="example-form">
<mat-form-field class="example-full-width">
<input matInput placeholder="password" formControlName="password">
<mat-error >
required
</mat-error>
</mat-form-field>
<!--see that the "errorStateMatcher" is applied to the input "passwordConfirm"-->
<mat-form-field class="example-full-width">
<input matInput placeholder="repeat password" formControlName="passwordConfirm"
[errorStateMatcher]="matcher"
>
<!--here show the error is form.hasError('mismatch')-->
<mat-error *ngIf="form.hasError('mismatch')">
must matcher
</mat-error>
<!--here show the error is form.get('passwordConfirm').hasError-->
<mat-error *ngIf="form.get('passwordConfirm').hasError('required')">
required
</mat-error>
</mat-form-field>
</form>
As always I can, the stackblitz
(*) check in the stackblitz form.get(‘passwordConfirm’).invalid
5
solved Angular 2+, why doesn’t material want to show error message?