My form group structure looks like this (order.component.ts):
this.orderForm = this.formBuilder.group({
customer: this.formBuilder.group({
name: ['', Validators.required],
phone: ['', Validators.required],
email: ['', Validators.required]
}),
...
});
In the template (order.component.html) I have:
<form [formGroup]="orderForm" (ngSubmit)="onSubmit()">
<fieldset formGroupName="customer">
<legend>Customer Information</legend>
<label for="name">Full name:</label>
<input type="text" formControlName="name" class="form-control" name="name" id="name" required>
<small class="form-text text-danger" *ngIf="orderForm.controls['customer'].controls['name'].invalid && (orderForm.controls['customer'].controls['name'].dirty || orderForm.controls['customer'].controls['name'].touched)">Name invalid</small>
</fieldset>
...
</form>
This works, but is a shorter way of expressing orderForm.controls['customer'].controls['name']
? For example it would be more succinct for the *ngIf condition to be "name.invalid && (name.dirty || name.touched)"
This is a quick example of how to setup form validation in Angular 6 using Template-Driven Forms. The example is a simple registration form with pretty standard fields for first name, last name, email and password. All fields are required, plus the email field must be a valid email address and the password field must have a min length of 6.
The form input fields use the [ (ngModel)] directive to bind to properties of the model object in the app component. Validation is implemented using the attributes required, minlength and email, the Angular framework contains directives that match these attributes with built-in validator functions.
The Angular comes up with several built-in validators for this purpose. They are minlength, maxlength, email, pattern, required, etc.
One way i use alot is to cast the sub formGroup into a form group as the 'get ()' method returns an abstractControl and use the 'get ()' method to extract the control of the nested formGroup like so :
I ran into same issue. My main problem was that ng build --prod
fails when using orderForm.controls['customer'].controls['name']
with error:
Property 'controls' does not exist on type 'AbstractControl'.
Apparently this is just type issue when template gets compiled to TS.
My approach is to create getter for nested form group and cast the correct type which solves both my issue and yours:
get customer() {
return this.orderForm.controls.customer as FormGroup;
}
used in HTML:
<small class="form-text text-danger" *ngIf="customer.controls['name'].invalid && (customer.controls['name'].dirty || customer.controls['name'].touched)">Name invalid</small>
Yes, that is the correct way to fetch nested form Control and no shortcut.
or you could create some property in your component which points to orderForm.get('customer')
form object
private customerForm : FormGroup
And assign it after form initialization
this.customerForm = this.orderForm.get('customer')
and fetch it like {{customerForm.get('name').valid}}
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