I am using Angular’s reactive forms and would like to apply a css style to controls inside a FormArray depending on the value of the control’s invalid property. I have come up with the following approach but I think the expression inside the ngClass property is too long and complex. Is there a more succinct way to access the invalid property for a control within a FormArray?
Template:
<form [formGroup]="myForm" class="form-horizontal">
<div class="form-group" [ngClass]="{'has-error': myForm.controls.name.invalid }">
<label class="control-label">Name</label>
<input formControlName="name" type="text" class="form-control" />
</div>
<div formArrayName="array1">
<div *ngFor="let f of array1_FA.controls; let i = index" [formGroupName]="i">
<div>
<div class="form-group"
[ngClass]="{'has-error': myForm.controls.array1.at(i).controls.question.invalid}">
<label class="control-label">Question #{{i+1}}</label>
<input formControlName="question" class="form-control" type="text" />
</div>
<div class="form-group"
[ngClass]="{'has-error': myForm.controls.array1.at(i).controls.response.invalid}">
<label class="control-label">Answer #{{i+1}}</label>
<input formControlName="response" class="form-control" type="text" />
</div>
</div>
</div>
</div>
</form>
Component:
import { Component } from '@angular/core';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'form-array-validation',
templateUrl: './form-array-validation.component.html'
})
export class FormArrayValidationComponent {
myForm: FormGroup;
questions = ['Q1', 'Q2', 'Q3', 'Q4'];
constructor(private fb: FormBuilder) {
this.createForm();
}
createForm() {
this.myForm = this.fb.group({
name: ['Name1', Validators.required],
array1: this.fb.array(this.questions.map(val => this.fb.group({
question: [val, Validators.required],
response: [null, Validators.required]
})))
});
}
get array1_FA(): FormArray {
return this.myForm.get('array1') as FormArray;
};
}
Validating Angular FormArray First you need to add the required validators while creating a new product form group inside the addProduct method. Now let's add a span element adjacent to the input control. Add the following CSS to the app. component.
Adding input controls dynamically Let's add a mat-icon-button besides the input form field to add a new control. To do that we'll have to add some style and convert the div into a flex row. We'll add a class to the div and add the styles in our css file. Next, let's add the button itself.
First, we need to import the FormArray from the Angular Forms Module. Build a formGroup orderForm using the FormBuilder. We define items as FormArray. We need to capture two fields under each item, the name of the item & description and price.
push(new FormGroup({ 'inputValue': new FormControl({ value: '', disabled: true }, Validators. required), })); You have to remember that disabling the form input will not allow you to submit. Instead, you can use the readonly property as below.
In this case you can make use of your f
in the iteration in template:
*ngFor="let f of array1_FA.controls;
which makes your code a bit shorter/cleaner, so instead of:
[ngClass]="{'has-error': myForm.controls.array1.at(i).controls.question.invalid}">
do:
[ngClass]="{'has-error': f.get('question').invalid}
or
[ngClass]="{'has-error': f.controls.question.invalid}
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