Angular 7 Material Design Generic Validation Implementation
Please feel free to redirect me if something similar has been asked on SO before (I couldn't find anything similar to my problem)
I am very comfortable with AngularJS but pretty new on Angular/(Angular7). I normally use directives for generic validations which short cuts the development.
With angular material design, I tried to implement form validation but what I have noticed in the examples that we are creating a FormControl
for each and every field that we want to validate or a FormGroup
as a list of FormControl
in it but still I have to define a new validator for each and every field I want to validate. I am pretty sure there should be an easier way and thats what I am looking for.
For instance, I have created a shared validator as following:
import { FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
export class ZenValidator implements ErrorStateMatcher {
public ZenFormGroup: FormGroup;
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = form && form.submitted;
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
}
getEmailValidator() {
return new FormControl('', [
Validators.required,
Validators.email
]);
}
getNameValidator() {
return new FormControl('', [
Validators.required
]);
}
getFormValidators() {
return this.ZenFormGroup = new FormGroup({
name: new FormControl('', [
Validators.required,
Validators.maxLength(60)
]),
dateOfBirth: new FormControl(new Date()),
address: new FormControl('', [
Validators.required,
Validators.maxLength(100)
]),
email: new FormControl('', [
Validators.required,
Validators.email
])
});
}
}
And based on the example I found, I am using it as following in my html:
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>First Name</mat-label>
<input matInput placeholder="enter a first name"
[(ngModel)]="user.Firstname"
[formControl]="nameValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="nameValidator.hasError('required')">
This field is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>Last Name</mat-label>
<input matInput placeholder="enter a last name"
[(ngModel)]="user.Lastname"
[formControl]="nameValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="nameValidator.hasError('required')">
This field is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>Email Address</mat-label>
<input matInput placeholder="enter an email address" [(ngModel)]="user.EmailAddress"
[formControl]="emailValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="emailValidator.hasError('email') && !emailValidator.hasError('required')">
Please enter a valid email address
</mat-error>
<mat-error *ngIf="emailValidator.hasError('required')">
Email is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
And in my component, Im using it like below:
import { ZenValidator } from '@app/modules/shared/helpers/zen-validator';
// all other imports etc... here
// component decorator etc... here
export class UserEditComponent implements OnInit, AfterViewInit {
emailValidator;
nameValidator;
user = new User();
options: FormGroup;
constructor(fb: FormBuilder
, public zenValidator: ZenValidator
, private cdr: ChangeDetectorRef
) {
this.options = fb.group({
hideRequired: false,
floatLabel: 'auto',
});
this.emailValidator = zenValidator.getEmailValidator();
this.nameValidator = zenValidator.getNameValidator();
}
ngAfterViewInit() {
}
ngOnInit() {
}
}
I do not want to create a bunch of validators for each fields on the pages. What I want to do is, create a generic text box validator for instance which checks the maxlength and required. Thats it. Then date validator, etc.
But if I try to use the same validator that I created as "nameValidator" and try to use it on both FirstName and LastName fields, it just shows the error message for both input fields if one of them is not valid for instance (since they both use the same [formControl]='nameValidator'
). So that is why I was thinking, "So what? Now I have to create a separate validator for each field? No way!" and wanted to ask you guys. Thanks
PS: I have no issue to use if there is any other (better) 3rd party approach to use that you can suggest for validations.
angular validation material-design angular-material-7
add a comment |
Please feel free to redirect me if something similar has been asked on SO before (I couldn't find anything similar to my problem)
I am very comfortable with AngularJS but pretty new on Angular/(Angular7). I normally use directives for generic validations which short cuts the development.
With angular material design, I tried to implement form validation but what I have noticed in the examples that we are creating a FormControl
for each and every field that we want to validate or a FormGroup
as a list of FormControl
in it but still I have to define a new validator for each and every field I want to validate. I am pretty sure there should be an easier way and thats what I am looking for.
For instance, I have created a shared validator as following:
import { FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
export class ZenValidator implements ErrorStateMatcher {
public ZenFormGroup: FormGroup;
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = form && form.submitted;
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
}
getEmailValidator() {
return new FormControl('', [
Validators.required,
Validators.email
]);
}
getNameValidator() {
return new FormControl('', [
Validators.required
]);
}
getFormValidators() {
return this.ZenFormGroup = new FormGroup({
name: new FormControl('', [
Validators.required,
Validators.maxLength(60)
]),
dateOfBirth: new FormControl(new Date()),
address: new FormControl('', [
Validators.required,
Validators.maxLength(100)
]),
email: new FormControl('', [
Validators.required,
Validators.email
])
});
}
}
And based on the example I found, I am using it as following in my html:
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>First Name</mat-label>
<input matInput placeholder="enter a first name"
[(ngModel)]="user.Firstname"
[formControl]="nameValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="nameValidator.hasError('required')">
This field is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>Last Name</mat-label>
<input matInput placeholder="enter a last name"
[(ngModel)]="user.Lastname"
[formControl]="nameValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="nameValidator.hasError('required')">
This field is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>Email Address</mat-label>
<input matInput placeholder="enter an email address" [(ngModel)]="user.EmailAddress"
[formControl]="emailValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="emailValidator.hasError('email') && !emailValidator.hasError('required')">
Please enter a valid email address
</mat-error>
<mat-error *ngIf="emailValidator.hasError('required')">
Email is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
And in my component, Im using it like below:
import { ZenValidator } from '@app/modules/shared/helpers/zen-validator';
// all other imports etc... here
// component decorator etc... here
export class UserEditComponent implements OnInit, AfterViewInit {
emailValidator;
nameValidator;
user = new User();
options: FormGroup;
constructor(fb: FormBuilder
, public zenValidator: ZenValidator
, private cdr: ChangeDetectorRef
) {
this.options = fb.group({
hideRequired: false,
floatLabel: 'auto',
});
this.emailValidator = zenValidator.getEmailValidator();
this.nameValidator = zenValidator.getNameValidator();
}
ngAfterViewInit() {
}
ngOnInit() {
}
}
I do not want to create a bunch of validators for each fields on the pages. What I want to do is, create a generic text box validator for instance which checks the maxlength and required. Thats it. Then date validator, etc.
But if I try to use the same validator that I created as "nameValidator" and try to use it on both FirstName and LastName fields, it just shows the error message for both input fields if one of them is not valid for instance (since they both use the same [formControl]='nameValidator'
). So that is why I was thinking, "So what? Now I have to create a separate validator for each field? No way!" and wanted to ask you guys. Thanks
PS: I have no issue to use if there is any other (better) 3rd party approach to use that you can suggest for validations.
angular validation material-design angular-material-7
add a comment |
Please feel free to redirect me if something similar has been asked on SO before (I couldn't find anything similar to my problem)
I am very comfortable with AngularJS but pretty new on Angular/(Angular7). I normally use directives for generic validations which short cuts the development.
With angular material design, I tried to implement form validation but what I have noticed in the examples that we are creating a FormControl
for each and every field that we want to validate or a FormGroup
as a list of FormControl
in it but still I have to define a new validator for each and every field I want to validate. I am pretty sure there should be an easier way and thats what I am looking for.
For instance, I have created a shared validator as following:
import { FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
export class ZenValidator implements ErrorStateMatcher {
public ZenFormGroup: FormGroup;
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = form && form.submitted;
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
}
getEmailValidator() {
return new FormControl('', [
Validators.required,
Validators.email
]);
}
getNameValidator() {
return new FormControl('', [
Validators.required
]);
}
getFormValidators() {
return this.ZenFormGroup = new FormGroup({
name: new FormControl('', [
Validators.required,
Validators.maxLength(60)
]),
dateOfBirth: new FormControl(new Date()),
address: new FormControl('', [
Validators.required,
Validators.maxLength(100)
]),
email: new FormControl('', [
Validators.required,
Validators.email
])
});
}
}
And based on the example I found, I am using it as following in my html:
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>First Name</mat-label>
<input matInput placeholder="enter a first name"
[(ngModel)]="user.Firstname"
[formControl]="nameValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="nameValidator.hasError('required')">
This field is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>Last Name</mat-label>
<input matInput placeholder="enter a last name"
[(ngModel)]="user.Lastname"
[formControl]="nameValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="nameValidator.hasError('required')">
This field is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>Email Address</mat-label>
<input matInput placeholder="enter an email address" [(ngModel)]="user.EmailAddress"
[formControl]="emailValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="emailValidator.hasError('email') && !emailValidator.hasError('required')">
Please enter a valid email address
</mat-error>
<mat-error *ngIf="emailValidator.hasError('required')">
Email is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
And in my component, Im using it like below:
import { ZenValidator } from '@app/modules/shared/helpers/zen-validator';
// all other imports etc... here
// component decorator etc... here
export class UserEditComponent implements OnInit, AfterViewInit {
emailValidator;
nameValidator;
user = new User();
options: FormGroup;
constructor(fb: FormBuilder
, public zenValidator: ZenValidator
, private cdr: ChangeDetectorRef
) {
this.options = fb.group({
hideRequired: false,
floatLabel: 'auto',
});
this.emailValidator = zenValidator.getEmailValidator();
this.nameValidator = zenValidator.getNameValidator();
}
ngAfterViewInit() {
}
ngOnInit() {
}
}
I do not want to create a bunch of validators for each fields on the pages. What I want to do is, create a generic text box validator for instance which checks the maxlength and required. Thats it. Then date validator, etc.
But if I try to use the same validator that I created as "nameValidator" and try to use it on both FirstName and LastName fields, it just shows the error message for both input fields if one of them is not valid for instance (since they both use the same [formControl]='nameValidator'
). So that is why I was thinking, "So what? Now I have to create a separate validator for each field? No way!" and wanted to ask you guys. Thanks
PS: I have no issue to use if there is any other (better) 3rd party approach to use that you can suggest for validations.
angular validation material-design angular-material-7
Please feel free to redirect me if something similar has been asked on SO before (I couldn't find anything similar to my problem)
I am very comfortable with AngularJS but pretty new on Angular/(Angular7). I normally use directives for generic validations which short cuts the development.
With angular material design, I tried to implement form validation but what I have noticed in the examples that we are creating a FormControl
for each and every field that we want to validate or a FormGroup
as a list of FormControl
in it but still I have to define a new validator for each and every field I want to validate. I am pretty sure there should be an easier way and thats what I am looking for.
For instance, I have created a shared validator as following:
import { FormControl, FormGroup, FormGroupDirective, NgForm, Validators } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
export class ZenValidator implements ErrorStateMatcher {
public ZenFormGroup: FormGroup;
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = form && form.submitted;
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
}
getEmailValidator() {
return new FormControl('', [
Validators.required,
Validators.email
]);
}
getNameValidator() {
return new FormControl('', [
Validators.required
]);
}
getFormValidators() {
return this.ZenFormGroup = new FormGroup({
name: new FormControl('', [
Validators.required,
Validators.maxLength(60)
]),
dateOfBirth: new FormControl(new Date()),
address: new FormControl('', [
Validators.required,
Validators.maxLength(100)
]),
email: new FormControl('', [
Validators.required,
Validators.email
])
});
}
}
And based on the example I found, I am using it as following in my html:
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>First Name</mat-label>
<input matInput placeholder="enter a first name"
[(ngModel)]="user.Firstname"
[formControl]="nameValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="nameValidator.hasError('required')">
This field is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>Last Name</mat-label>
<input matInput placeholder="enter a last name"
[(ngModel)]="user.Lastname"
[formControl]="nameValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="nameValidator.hasError('required')">
This field is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
<div class="col-lg-3 col-md-4 no-left-padding">
<mat-form-field [floatLabel]="options.value.floatLabel">
<mat-label>Email Address</mat-label>
<input matInput placeholder="enter an email address" [(ngModel)]="user.EmailAddress"
[formControl]="emailValidator"
[errorStateMatcher]="zenValidator">
<mat-error *ngIf="emailValidator.hasError('email') && !emailValidator.hasError('required')">
Please enter a valid email address
</mat-error>
<mat-error *ngIf="emailValidator.hasError('required')">
Email is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
And in my component, Im using it like below:
import { ZenValidator } from '@app/modules/shared/helpers/zen-validator';
// all other imports etc... here
// component decorator etc... here
export class UserEditComponent implements OnInit, AfterViewInit {
emailValidator;
nameValidator;
user = new User();
options: FormGroup;
constructor(fb: FormBuilder
, public zenValidator: ZenValidator
, private cdr: ChangeDetectorRef
) {
this.options = fb.group({
hideRequired: false,
floatLabel: 'auto',
});
this.emailValidator = zenValidator.getEmailValidator();
this.nameValidator = zenValidator.getNameValidator();
}
ngAfterViewInit() {
}
ngOnInit() {
}
}
I do not want to create a bunch of validators for each fields on the pages. What I want to do is, create a generic text box validator for instance which checks the maxlength and required. Thats it. Then date validator, etc.
But if I try to use the same validator that I created as "nameValidator" and try to use it on both FirstName and LastName fields, it just shows the error message for both input fields if one of them is not valid for instance (since they both use the same [formControl]='nameValidator'
). So that is why I was thinking, "So what? Now I have to create a separate validator for each field? No way!" and wanted to ask you guys. Thanks
PS: I have no issue to use if there is any other (better) 3rd party approach to use that you can suggest for validations.
angular validation material-design angular-material-7
angular validation material-design angular-material-7
edited Jan 19 at 21:45
curiousBoy
asked Jan 19 at 20:53
curiousBoycuriousBoy
2,59322333
2,59322333
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54271305%2fangular-7-material-design-generic-validation-implementation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54271305%2fangular-7-material-design-generic-validation-implementation%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown