Munna Babu
Munna Babu

Reputation: 5756

How to create form Builder for Dynamic fields Angular 4?

I was creating fields dynamically based on Json. For example if my json array has 3 value then i will create 3 input checkbox dynamically like below

<ng-template ngFor let-numberOfRow [ngForOf]="numberOfRows">
   <mat-checkbox [formControlName]="numberOfRow.row" [value]="numberOfRow.row" [name]="numberOfRow.row">All</mat-checkbox>
</ng-template>

now i m trying to create formBuilder for this fields like below but its not working. Could someone please tell me how to declare formbuilder for dynamic fields ?

public ngOnInit() {
   this.myForm= this.fb.group(this.formFields);
}
public formFields() {
    let empArr = [];
    for (let val of this.myArrayList) {
        empArr.push(val + ": ''");
    }
    let allFields = '{' + empArr.join(',') + '}';
    return allFields;
}

basically the above formFields function will return string like this { allRow: '', firstRow: '', secondRow: '', thirdRow: '' }

so instead if declaring statically this.myForm= this.fb.group({ allRow: '', firstRow: '', secondRow: '', thirdRow: '' }); i want to declare the fields dynamically.

Upvotes: 1

Views: 5316

Answers (4)

Shaybc
Shaybc

Reputation: 3147

I maintain an array with the json object fields names, and an array with the form controls, then i itterate over the field names in order to create the form checkboxes

TypeScript file:

import { FormBuilder, FormGroup } from '@angular/forms';

export class SomeComponent
{
  form!: FormGroup;
  fieldNames: string[];
  formControls: any;

  constructor(
    private formBuilder: FormBuilder,
  )
  {
      const someJsonOnject = {env: "Dev", name: "SRV", ver: "21.1" };
      this.fieldNames= [];
      this.formControls= {};

      Object.keys(someJsonOnject).forEach(currentFieldName => {
        // add the current field name to the fieldNames array
        this.fieldNames.push(currentFieldName);

        // create a boolean formControl from each field
        this.formControls[currentFieldName] = [true];
      });
            
      // add formControls to the form
      this.form = this.formBuilder.group(this.formControls);
  }
}

HTML Template file:

<form [formGroup]="form">
    <ng-container *ngFor="let currentFormControl of fieldNames">
        <div><mat-checkbox formControlName="{{ currentFormControl }}">{{ currentFormControl }}</mat-checkbox></div>
    </ng-container>
</form>

Upvotes: 0

Lucas Breitembach
Lucas Breitembach

Reputation: 1683

building with formBuilder example:

component.ts

  form: FormGroup;

  constructor(
    private fb: FormBuilder
  ) { }

  ngOnInit() {
    this.form = this.fb.group({
      dropOffAddress : ['', Validators.required]
    })

  }

  addInput() {
    this.form.addControl(`input-${Object.keys(this.form.value).length}`, new FormControl('', [Validators.required]))
  }

  removeInput(key: string) {
    this.form.removeControl(key)

  }

component.html

<form [formGroup]="form" *ngIf="show">
  <ng-container *ngFor="let f of form.controls | keyvalue">
    <mat-form-field appearance="outline" class="w-100" color="primary">
      <mat-label>Label of Input</mat-label>
      <mat-icon (click)="addInput()" color="accent" matPrefix>add</mat-icon>
      <input type="text" [formControlName]="f.key" [name]="f.key" autofocus matInput placeholder="Digite um endereço">
      <mat-icon (click)="removeInput(f.key)" matSuffix>remove</mat-icon>
      <mat-error *ngIf="form.invalid">Please fill the field</mat-error>
    </mat-form-field>
  </ng-container>
</form>

Upvotes: 0

Munna Babu
Munna Babu

Reputation: 5756

As per @charlietfl issue is i am sending the string data instead of object, so i send as object like below now its working fine.

public ngOnInit() {
    this.myForm= this.fb.group(this.formFields());
 }
 public formFields() {
     let empArr = {};
     for (let val of this.myArrayList) {
         empArr[val] = '';
     }
     return empArr;
 }

so the above method formField created object like { allRow: '', firstRow: '', secondRow: '', thirdRow: '' } so now its working fine. Thanks everyone :)

Upvotes: 1

Aleš Doganoc
Aleš Doganoc

Reputation: 12052

You can do this by first building the FormControl in code using the control method of the FormBuilder and then using the addControl method of the FormGroup. For example like this:

this.myForm.addControl('controlName', 
   this.fb.control({ disabled: false, value: controlValue }, validators, asyncValidators));

Then you need to bind it using the FormControlDirective instead of the FormControlName directive because the control is already created. The binding will then look like this:

<mat-checkbox [formControl]="myForm.controls['controlName']" [value]="numberOfRow.row" [name]="numberOfRow.row">All</mat-checkbox>

Upvotes: 1

Related Questions