Search code examples
angularformsangular-reactive-forms

How to use array of objects for controls in Form Group


I need to dynamically create forms in Angular. I have the following model:

values = [
    {
      id: 14,
      group: 'basics',
      field: 'food',
      comment: 'Fine',
    },
    {
      id: 15,
      group: 'basics',
      field: 'water',
      comment: 'Good',
    },
    {
      id: 19,
      group: 'others',
      field: 'recreation',
      comment: '',
    },
    {
      id: 16,
      group: 'basics',
      field: 'shelter',
      comment: '',
    },
    {
      id: 17,
      group: 'others',
      field: 'job',
      comment: 'Not Good',
    },
    {
      id: 18,
      group: 'others',
      field: 'education',
      comment: 'Fine',
    },
  ];

This is how i expect the form to be displayed:

enter image description here

Here is the HTML model for the Form where each field has its own corresponding comment.

<form [formGroup]= "form" (submit)="onSubmit()">
    Basic Neccessary
      <div >
        <div class="col-md-2">        
          <label class="custom-control-label">
           Food Quality&nbsp;
          </label>
          <input type="text" formControlName="comment" /> 
        </div>
        <div class="col-md-2" >        
          <label class="custom-control-label">
            Water Availability&nbsp;
          </label>
          <input type="text" formControlName="comment" /> 
        </div>
        <div class="col-md-2" >        
          <label class="custom-control-label">
            Shelter &nbsp;
          </label>
          <input type="text" formControlName="comment" /> 
        </div>
      </div>
    Other Neccessary

      <div class="row" >
        <div class="col-md-2" >        
          <label class="custom-control-label">
           Jobs Value &nbsp;
          </label>
          <input type="text" formControlName="comment" /> 
        </div>
        <div class="col-md-2" >        
          <label class="custom-control-label">
            Educations Provided &nbsp;
          </label>
          <input type="text" formControlName="comment" /> 
        </div>
        <div class="col-md-2" >        
          <label class="custom-control-label">
            Recreational value &nbsp;
          </label>
          <input type="text" formControlName="comment" /> 
        </div>
      </div>
  <br/>   
   <button class="btn btn-primary btn-lg min-w100 float-right mt-3">
     Save
  </button>
</form>

For example, I have a 'food' field and its comment. I want the comment to be in the input box next to the 'Food Quality' field. How do I "bind" my field value to the form ?


Solution

  • --- Component ---

      protected readonly form = this.fb.group({
        values: this.fb.array<any[]>([]),
      });
    
      fillform(): void {
        values.forEach((value) => {
          const group = this.fb.group({
            id: this.fb.control(value.id),
            group: this.fb.control(value.group),
            field: this.fb.control(value.field),
            value: this.fb.control(value.comment),
          });
          (this.form2.controls.values as FormArray).push(group);
        });
      }
    

    --- HTML -----

    <form [formGroup]="form">
      @if (form) { @for (item of form.get('values')?.value; track $index) {
      <div>
        <div>
          <label [for]="item.id">id</label>
          <input [id]="item.id" type="text" formControlName="id" />
        </div>
        <div>
          <label [for]="item.group">group</label>
          <input [id]="item.group" type="text" formControlName="group" />
        </div>
        <div>
          <label [for]="item.field">field</label>
          <input [id]="item.field" type="text" formControlName="field" />
        </div>
        <div>
          <label [for]="item.comment">comment</label>
          <input [id]="item.comment" type="text" formControlName="comment" />
        </div>
      </div>
      } }
    </form>
    

    Any type must be your value type