-
Notifications
You must be signed in to change notification settings - Fork 6.8k
[input] Add example of using mat-error with parent formgroup validation #8513
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I've been meaning to add an example for this because it's a common need to validate matching passwords/emails/etc. Would you mind repurposing this issue for tracking such an example? |
Okay, I understand the problem. Thanks. Is it better like this ? |
How about See this answer for pretty much the same thing. I think it's a little more convoluted than necessary, but looks to get the job done. I'll try and add an official example soon. |
Thank you very much, I found the solution with this answer. |
@ewaschen I'm answering your question from #4027 (comment) over here to keep the discussion related to the issue topics If it works, the way you've outlined (by checking Another approach (forgive me for not testing this) would be to inject @Component({...})
export MyComponent {
constructor(private defaultMatcher: ErrorStateMatcher) { }
customErrorStateMatcher = {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const invalidParent = control && control.touched && control.parent.invalid;
return invalidParent || this.defaultMatcher.isErrorState(control, form);
}
}
}
|
I'm running into the same issue. Here's my Are Equals matcher. It does not use
You use it in your FormGroup, as such.
Is this why my Here's where I'm using it in my
The error only renders when it's outside of |
Ok, I've followed the stack post linked by @Jbz797, and here's the TLDR version of that poorly written post.
Thanks for this thread! |
I actually don't know what's the purpose of the submitted logic in that matcher class. it was causing some minor issues, where the formfield where you bind it to is showing up false positives (red when no error). I just removed it. |
ErrorStateMatcher approach is not so convenient. Imagine that validation function resides in the component class (because it depends on a @input() field. And that the component does not use form at all (because it's not part of the form). Creating a new class that extends ErrorStateMatcher does not allow me to invoke that validation function. It would be nice to be able to connect a simple, unconditional *ngIf on mat-error tag and it should popup without extending nothing |
@vcartera81 you don't necessarily need to extend and instantiate an ErrorStateMatcher class. You could very much do something like this: // this is untested
@Component({...})
export MyComponent {
@Input() showError: boolean;
myErrorStateMatcher = {
isErrorState = () => this.showError;
}
} I agree that it isn't the most convenient approach, but the ErrorStateMatcher is flexible enough to support a huge variety of use cases while maintaining the default error behavior defined in the spec. |
@willshowell you are right, I didn't thought of such approach :) thanks! |
ErrorStateMatcher doesn't work with custom MatFormFieldControl |
I have tried all the above suggestions but nothing worked for me!
And here is the method which will call recursively:
|
https://stackblitz.com/edit/angular-mlo6y6 Is this issue the same as my issue in this stackblitz? |
@kamok : It is solved my issues but now when I submit the form even it is a valid form and control it is showing as error for confirm password field.So I removed submitted from the return and everything is working fine.But I wanted to know the use of submitted value.So could u please explain what is the use of submitted in that code. |
Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends. Find more details about Angular's feature request process in our documentation. |
I was able to get this workin with nested forms. It's a simple solution with a custom error matcher. It only works a single level down unfortunately but that was enough for my use case. |
This may come late to the show, but here's a solution that solves the problem with submit state: import { FormControl, FormGroupDirective, NgForm } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
export class ParentErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = form?.submitted;
const controlDirtyOrTouched = control?.dirty || control?.touched;
const controlInvalid = control?.invalid;
const parentDirtyOrTouched = control?.parent?.dirty || control?.parent?.touched;
const parentInvalid = control?.parent?.invalid;
return ((controlDirtyOrTouched && parentDirtyOrTouched) || isSubmitted) && (controlInvalid || parentInvalid);
}
} import { ParentErrorStateMatcher } from '@shared/helpers/error-state.matcher';
@UntilDestroy()
@Component({
selector: 'cdb-user-add-update',
templateUrl: './user-add-update.component.html',
styleUrls: ['./user-add-update.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserAddUpdateComponent implements OnInit, OnDestroy {
matcher: ParentErrorStateMatcher;
ngOnInit() {
this.matcher = new ParentErrorStateMatcher();
}
} <div formGroupName="passwordGroup" fxLayout="row" fxLayoutGap="20px">
<!-- Password -->
<div fxFlex="50" fxLayout="column">
<mat-form-field>
<input
matInput
type="password"
formControlName="password"
name="password"
placeholder="{{ 'User.Password' | transloco }}"
[required]="(isEditing$ | async) === false"
[dimmed]="type.value === AccessType.Service"
autocomplete="off"
[errorStateMatcher]="matcher"
/>
</mat-form-field>
<small *ngIf="password.errors?.required && password.touched" class="mat-warn">
{{ 'User.PasswordRequired' | transloco }}
</small>
<small *ngIf="passwordGroup.errors?.invalidPassword && password.touched" class="mat-warn">
{{ 'User.PasswordInvalid' | transloco : { constraints: passwordConstraints } }}
</small>
</div>
<!-- Password confirmation -->
<div fxFlex="50" fxLayout="column">
<mat-form-field>
<input
matInput
type="password"
formControlName="passwordConfirmed"
name="passwordConfirmed"
placeholder="{{ 'User.PasswordConfirmed' | transloco }}"
[required]="(isEditing$ | async) === false"
[dimmed]="type.value === AccessType.Service"
autocomplete="off"
[errorStateMatcher]="matcher"
/>
</mat-form-field>
<small *ngIf="passwordConfirmed.errors?.required && passwordConfirmed.touched" class="mat-warn">
{{ 'User.PasswordRequired' | transloco }}
</small>
<small
*ngIf="passwordGroup.errors?.invalidPasswordConfirmed && passwordConfirmed.touched"
class="mat-warn"
>
{{ 'User.PasswordInvalid' | transloco : { constraints: passwordConstraints } }}
</small>
<small *ngIf="passwordGroup.errors?.mismatchedPasswords && passwordConfirmed.touched" class="mat-warn">
{{ 'User.PasswordMismatch' | transloco }}
</small>
</div>
</div> |
Uh oh!
There was an error while loading. Please reload this page.
Bug, feature request, or proposal:
<mat-error>
doesn't show when I use an email maching validator for emails inputs.What is the expected behavior?
To display the error.
What is the current behavior?
No error is displayed
What are the steps to reproduce?
Set a custom validator for check if two emails inputs are equals, like this :
The template :
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
Angular 5.0.2, Material 5.0.0-rc0, MacOS Sierra, Firefox
Additional Information
If i replace the
<mat-error>
tag by a<p>
tag (or anything else), it's work.The text was updated successfully, but these errors were encountered: