SetValue And PatchValue In FormArray Angular

SetValue And PatchValue In FormArray Angular

In this Angular article, we will learn how to use SetValue and PatchValue in FormArray. In Reactive Forms, we use these methods to set the form's values. The AngularFormsModule has these methods. Refer to the Angular Forms SetValue and PatchValue article for more information. When we have nested FormArray, however, setting the value of the form controls gets a little complicated.

Nested FormArray Example

In the previous article, we created a nested Form array. The code is as follows: For a further description of the code, see the instructional nested FormArray Example.

The structure of our form model is as follows. There can be multiple teachers, each of whom can oversee multiple batches. Each batch can have a number of students in it.

|Form
|-- Teacher
|-----Batch
|-------Students

Open the app.component.html file and add the following code:
<h1>{{title}}</h1>
 
<form [formGroup]="teachersForm" (ngSubmit)="onSubmit()">
 
  <div formArrayName="teachers">
 
    <div *ngFor="let teacher of teachers().controls; let ti=index">
 
      <div [formGroupName]="ti"
        style="border: 1px solid blue; padding: 10px; width: 100%; display: inline-block; margin: 5px;">
        Teachers Name :
        <input type="text" formControlName="name">
        <button (click)="removeTeacher(ti)">Remove</button>
        <button type="button" (click)="addBatch(ti)">Add Batch</button>
 
        <div formArrayName="batches">
 
          <div *ngFor="let batch of batches(ti).controls; let bi=index">
 
            <div [formGroupName]="bi" style="border: 1px solid red; padding: 10px; margin: 5px; float:left">
 
              Batch Name :
              <input type="text" formControlName="name">
              <button (click)="removeBatch(ti,bi)">Remove Batch</button>
              <button (click)="addStudent(ti,bi)">Add Student</button>
 
              <div formArrayName="students">
 
                <div *ngFor="let batch of students(ti,bi).controls; let si=index">
                  <div [formGroupName]="si" style="border: 1px solid blue; padding: 2px; ">
                    Student Name :
                    <input type="text" formControlName="name">
                    <button (click)="removeStudent(ti,bi,si)">Remove student</button>
                  </div>
                </div>
 
              </div>
 
            </div>
 
          </div>
 
        </div>
 
      </div>
 
    </div>
 
  </div>
 
  <p>
    <button type="button" (click)="addTeacher()">Add Teacher</button>
  </p>
  <p>
    <button type="submit">Submit</button>
  </p>
 
</form>
 
{{this.teachersForm.value | json}}

Now, add the following code under the app.component.ts file.
import { Component } from '@angular/core';
import { FormGroup, FormArray, FormBuilder } from '@angular/forms'
 
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
 
  title = 'FormArray SetValue & PatchValue Example';
 
  teachersForm: FormGroup;
 
  constructor(private fb: FormBuilder) {
    this.teachersForm = this.fb.group({
      teachers: this.fb.array([]),
    })
  }
 
 
  /** Teachers */
  teachers(): FormArray {
    return this.teachersForm.get("teachers") as FormArray
  }
 
  newTeacher(): FormGroup {
    return this.fb.group({
      name: '',
      batches: this.fb.array([])
    })
  }
 
 
  addTeacher() {
    this.teachers().push(this.newTeacher());
  }
 
 
  removeTeacher(ti) {
    this.teachers().removeAt(ti);
  }
 
 
  /** batches */
 
  batches(ti): FormArray {
    return this.teachers().at(ti).get("batches") as FormArray
  }
 
 
  newBatch(): FormGroup {
    return this.fb.group({
      name: '',
      students: this.fb.array([])
    })
  }
 
  addBatch(ti: number) {
    this.batches(ti).push(this.newBatch());
  }
 
  removeBatch(ti: number, bi: number) {
    this.batches(ti).removeAt(ti);
  }
 
  /** students */
 
  students(ti, bi): FormArray {
    return this.batches(ti).at(bi).get("students") as FormArray
  }
 
  newStudent(): FormGroup {
    return this.fb.group({
      name: '',
    })
  }
 
  addStudent(ti: number, bi: number) {
    this.students(ti, bi).push(this.newStudent());
  }
 
  removeStudent(ti: number, bi: number, si: number) {
    this.students(ti, bi).removeAt(si);
  }
 
  onSubmit() {
    console.log(this.teachersForm.value);
  }
 
}

Now, run the application and show the output screen look's like below


Example of SetValue And PatchValue In Angular FormArray


How to load initial data in FormArray

There will be no controls in the FormArray when the form loads for the first time. There will be no effect if you call PatchValue or SetValue.

In the following example, the patchValue1 method tries to load the data. One teacher is in charge of two batches, each of which has three students.
patchValue1() {
    console.log('patchValue1')
    var data = {
      teachers: [
        {
          name: 'Teacher 1', batches: [
            { name: 'Batch No 1', students: [{ name: 'Ramesh' }, { name: 'Suresh' }, { name: 'Naresh' }] },
            { name: 'Batch No 2', students: [{ name: 'Vikas' }, { name: 'Harish' }, { name: 'Lokesh' }] },
          ]
        }
      ]
    }
 
    this.teachersForm.patchValue(data);
}

Invoke the method that was included in the template.
<p>
  <button (click)="patchValue1()">PatchValue1</button>
</p>

PatchValue will not operate unless all of the controls are loaded, as shown below. As a result, we must manually construct the form before running patchValue.


Example of SetValue And PatchValue In FormArray

PatchValue Example

To load the data, we must programmatically change our form to match the data. In the following example, the patchValue2 function accomplishes this.
patchValue2() {
 
  var data = {
    teachers: [
      {
        name: 'Teacher 1', batches: [
          { name: 'Batch No 1', students: [{ name: 'Ramesh' }, { name: 'Suresh' }, { name: 'Naresh' }] },
          { name: 'Batch No 2', students: [{ name: 'Vikas' }, { name: 'Harish' }, { name: 'Lokesh' }] },
        ]
      }
    ]
  }
  this.clearFormArray();
 
 
  data.teachers.forEach(t => {
 
    var teacher: FormGroup = this.newTeacher();
    this.teachers().push(teacher);
 
    t.batches.forEach(b => {
      var batch = this.newBatch();
 
      (teacher.get("batches") as FormArray).push(batch)
 
      b.students.forEach(s => {
        (batch.get("students") as FormArray).push(this.newStudent())
      })
 
    });
  });
 
  this.teachersForm.patchValue(data);
}
 
 
clearFormArray() {
 
  //Angular 8 +
  this.teachers().clear();
 
  //older Versions of angualar
  //while (this.teachers().length) {
  //  this.teachers().removeAt(0);
  //}
}

To begin, we'll clear the FormArray. If the user wants to discard and reload the original data, clearing is useful.

All you have to do to clear the form is grab the top-level FormArray and call the clear function. It's worth noting that clear is accessible starting with Angular 8+. Use the removeAt(index) method if you're using an older version.
clearFormArray() {
 
  //Angular 8 +
  this.teachers().clear();
 
  //older Versions of angualar
  //while (this.teachers().length) {
  //  this.teachers().removeAt(0);
  //}
}

Now it's time to loop through the data. 
data.teachers.forEach(t => {

Create a nested form array for each teacher and add it to the top-level FormArray.
var teacher: FormGroup = this.newTeacher();
this.teachers().push(teacher);

Now it's time to loop over all of the batches and add them to the batches form array.
t.batches.forEach(b => {

  var batch = this.newBatch();
  (teacher.get("batches") as FormArray).push(batch)

After that, repeat the process with pupils.
b.students.forEach(s => {
  (batch.get("students") as FormArray).push(this.newStudent())
})

Our form model now corresponds to the data structure. To update the Form, use the patchValue or setValue methods. Keep in mind the distinction between PatchValue and SetValue.

Even if the data does not fit the Form's structure, the patchValue sets it.

SetValue specifies that the data must exactly match the FormArray's structure.

Now, run the application and show the output screen below.


Example of SetValue And PatchValue In FormArray Angular


Conclusion

Using the initial data, in this article we learned how to update the values of FormArray. To do so, you must first edit your form to reflect the data structure. Then either PatchValue or SetValue can be used.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in comment section.

Post a Comment

Previous Post Next Post