Angular Material Form Validation
The form itself can be checked with valid and invalid. The below should work:
[disabled]="biodataForm.invalid"
Info on the Angular form group can be found at: https://angular.io/api/forms/FormGroup
In addition, the email and phone inputs...you are using [(value)]...change those to [(ngModel)] and it should work the way you expect.
vicatcu
Expertise in Embedded Systems / Microcontrollers Cornell University B.S. ECE '02, M.Eng ECE '04 Co-Founder of Wicked Device, LLC Air Quality Egg Zynect Sensors
Updated on November 23, 2020Comments
-
vicatcu over 3 years
If the fields of my FormGroup are model-bound, ala [(ngModel)], and become populated on page load, e.g. because of a service, my Submit Button, which is guarded as
[disabled]="biodataForm.status !== 'VALID'"
, does not become disabled. If the form comes up blank and I fill it in normally, the guard passes when the form is correctly filled out. If the same exact values are populated through the data-binding, the biodataForm.status value remains INVALID until I change the value of every field.My feeling is that the form should recognize it has valid content after the data-bindings are populated, and its status should change from INVALID to VALID as a result... what's going wrong here?
My form markup looks like this:
<form class="form" name="biodataForm" [formGroup]="biodataForm"> <mat-form-field class="full-width"> <input matInput placeholder="First Name" required [(ngModel)]="_memberdata.firstname" [formControl]="firstnameFormControl"> <mat-error *ngIf="firstnameFormControl.invalid">{{getRequiredErrorMessage('firstname')}}</mat-error> </mat-form-field> <mat-form-field class="full-width"> <input matInput placeholder="Last Name" required [(ngModel)]="_memberdata.lastname" [formControl]="lastnameFormControl"> <mat-error *ngIf="lastnameFormControl.invalid">{{getRequiredErrorMessage('lastname')}}</mat-error> </mat-form-field> <mat-form-field class="full-width" hintLabel="Note: We'll send you an email with a link to click to prove it's you"> <input matInput placeholder="Email" required [(value)]="_memberdata.email" [formControl]="emailFormControl"> <mat-error *ngIf="emailFormControl.invalid">{{getEmailErrorMessage()}}</mat-error> </mat-form-field> <mat-form-field class="full-width"> <input matInput placeholder="Phone" type="tel" [(value)]="_memberdata.phone" required [formControl]="phoneFormControl"> <mat-error *ngIf="phoneFormControl.invalid">{{getPhoneErrorMessage()}}</mat-error> </mat-form-field> <button mat-raised-button color="primary" class="submit-button" [disabled]="biodataForm.status !== 'VALID'" (click)="handleNext()">Next Step</button> </form>
```
My Angular component surrounding this form looks like this (details omitted for clarity, full source is here):
export class WelcomeComponent { emailFormControl = new FormControl('', [ Validators.required, Validators.email, ]); firstnameFormControl = new FormControl('', [Validators.required]); lastnameFormControl = new FormControl('', [Validators.required]); phoneFormControl = new FormControl('', [ Validators.required, Validators.pattern(/(\(?[0-9]{3}\)?-?\s?[0-9]{3}-?[0-9]{4})/) ]); // addressFormControl = new FormControl('', [Validators.required]); biodataForm: FormGroup = new FormGroup({ email: this.emailFormControl, firstname: this.firstnameFormControl, lastname: this.lastnameFormControl, phone: this.phoneFormControl // address: this.addressFormControl }); getEmailErrorMessage() { return this.emailFormControl.hasError('required') ? 'You must enter a value' : this.emailFormControl.hasError('email') ? 'Not a valid email' : ''; } getPhoneErrorMessage() { return this.phoneFormControl.hasError('required') ? 'You must enter a value' : this.phoneFormControl.hasError('pattern') ? 'Format must be (xxx) xxx-xxxx' : ''; } getRequiredErrorMessage(field) { return this.biodataForm.get(field).hasError('required') ? 'You must enter a value' : ''; } constructor( public _memberdata: MemberDataService, private _api: ApiService, private _router: Router, private _snackBar: MatSnackBar) { } handleNext() { // ... handle button click } }
```
-
vicatcu about 6 yearsUnfortunately, just tried this, behaves the same way as my posted code (re: not identifying 'valid' state with preloaded model-bound fields). Live development version is running at ithacagenerator.org/onboard if you want to have a look
-
jdgower about 6 yearsEdited my answer...that should do it.
-
vicatcu about 6 yearsYou rock, thanks so much. That was bone-headed, thanks for the fresh eyes.