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
}
}
```
Angular uses directives to match these attributes with validator functions in the framework. Every time the value of a form control changes, Angular runs validation and generates either a list of validation errors that results in an INVALID status, or null, which results in a VALID status.
It provides some of the shared behavior that all controls and groups of controls have, like running validators, calculating status, and resetting state. It also defines the properties that are shared between all sub-classes, like value , valid , and dirty . It shouldn't be instantiated directly.
Matinput is an Angular directive that primarily allows input and text area elements to work with a form field. With this, you can display placeholders perfectly, add custom error messages, a clear button, specify the maximum length of the text or add prefixes and suffixes for a seamless user experience.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With