Reactive Form in Angular With FormArray

Mustafa Kunwa
3 min readAug 27, 2019

--

Why use Reactive Forms?

Reactive forms provide a model-driven approach to handling form inputs whose values change over time. Reactive forms use an explicit and immutable approach to managing the state of a form at a given point in time. Each change to the form state returns a new state, which maintains the integrity of the model between changes. Reactive forms are built around observable streams, where form inputs and values are provided as streams of input values, which can be accessed synchronously.

Advantages and Disadvantages of Reactive Forms

It’s easier to write unit tests in reactive forms since all the form code and functionality is contained in the component. However, reactive forms require more coding implementation in the component.

To use reactive forms, import ReactiveFormModule from the @angular/forms package and add it to your NgModule's imports array.

import { ReactiveFormsModule } from ‘@angular/forms’;
@NgModule({
imports: [
// other imports …
ReactiveFormsModule
],
})
export class AppModule { }

For more validators, you can use ng2-validation which provide you with wide range custom validators you may require in forms

BUILD REACTIVE FORM

we’ll first need to add imports for FormBuilder ,Validators , FormArray and FormGroup to our component. Since FormBuilder is a service we inject that into our component’s constructor as well. we’ll add some validation to our form to prevent the user from submitting until all fields are valid.

ngOnInit() {
this.CreateForm();
}
CreateForm(){
this.StudentForm = this.fb.group({
FullName: [‘’, Validators.required],
Email: [‘’, [Validators.required, CustomValidators.email]],
Qualifications: this.fb.array([
this.QualificationForm()
])
})
}

Our Qualifications instance is a form array instead of a form control, and we’re calling a QualificationForm method to create a form group as the first Qualification in our array. Here’s what our Qualifications method looks like:

QualificationForm() {
return this.fb.group({
DegreeName: [‘’, Validators.required],
Percentage: [‘’,[Validators.required,
CustomValidators.digits,CustomValidators.max(100)]]
})
}

Adding to the FormArray Dynamically

Now the best part is that we can to treat our FormArray just like a regular array and push new items into it but before adding it just checking all earlier fields are valid:

AddQualification() {
if (this.StudentForm.controls.Qualifications.valid) {
var _semesters =FormArray>this.StudentForm.controls.Qualifications;
_semesters.push(
this.QualificationForm()
)
}
}

Remove From FormArray Dynamically

We can remove the item from array just like Regular array, instead of the splice, we’ll use removeAt.

RemoveQualification(index){
var _semesters = <FormArray>this.StudentForm.controls.Qualifications;
if(_semesters.controls.length>1){
_semesters.removeAt(index)
}
}

FormArray in the Template

we’ll use the formArrayName directive in the template to bind to our form array Here I have not included any error messages in form:

<form [formGroup]="StudentForm">
<div class="form-group row">
<label class="col-sm-2 col-form-label">Full name :</label>
<div class="col-sm-10">
<input class="form-control" formControlName="FullName">
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Email :</label>
<div class="col-sm-10">
<input class="form-control" formControlName="Email">
</div>
</div>
<div class="row" formArrayName="Qualifications">
<div class="row" *ngFor="let qualification of StudentForm.controls.Qualifications.controls; let i=index;last as last" formGroupName="{{i}}">
<div class="col-sm-5">
<label class="col-sm-4">Degree</label>
<div class="col-sm-8">
<input class="form-control" formControlName="DegreeName">
</div>
</div>
<div class="col-sm-5">
<label class="col-sm-4">Percentage</label>
<div class="col-sm-8">
<input class="form-control" formControlName="Percentage">
</div>
</div>
<div class="col">
<i class="icofont icofont-ui-remove m-r-5" (click)="RemoveQualification(i)">Remove</i>
<i class="icofont icofont-ui-add" (click)="AddQualification()" *ngIf="last">Add</i>
</div>
</div>
</div>
<button class="btn btn-primary" (click)="submit()">Submit</button></form>

Error message to any Input as:

<div class="col-sm-10">
<input class=”form-control” formControlName=”FullName”>
<div class=”messages text-danger text-left” *ngIf=”(submitted ||StudentForm.controls.FullName.touched) && StudentForm.controls.FullName.errors?.required”> FullName is required</div>
</div>

We can add an error message for each and every field as shown above.

Thanks for reading my article

--

--