Dexter
Dexter

Reputation: 528

unable to create the dynamic reactive forms using angular

i am trying to create the dynamic reactive form using angular i am able to loop it but it is displaying the exact way

<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
  <div *ngFor="let dat of formData;let index = index;">
     <label for="{{dat.name}}">{{dat.name }}</label>
     <input type="text" id="{{dat.id}}" [formControlName]="dat.name" />  
    </div>


</form>
<button type="button"><button>

.ts

 registerForm: FormGroup;
  submitted = false;

  formData = [{ id: 'firstName', name: 'firstName' },
  { id: 'lastName', name: 'lastName' },
  { id: 'address', name: 'address' },
  { id: 'emailid', name: 'emailid' }
  ]


  constructor(private formBuilder: FormBuilder) {
    this.registerForm = this.formBuilder.group({
      formData: []
    });
   }

   onSubmit(){
    console.log(this.registerForm.value); 
   }

including the validation

below is my stackblitz url

https://stackblitz.com/edit/angular-awguej

Upvotes: 0

Views: 693

Answers (4)

Eliseo
Eliseo

Reputation: 58039

To complement Krishna's answer, if you want to create a formArray with data, you can create two functions.

//create a formGroup with the data or empy if not data
createNewGroup(data):FormGroup {
    return this.formBuilder.group({
        id: [data?data.id:null], 
        name: [data?data.name:null] 
    })
}

//And a function to create the form

createForm(formData):formGroup
{
    //create an array of FormGroup,
    //if data, with each element of data a newGroup
    //else an array with one element
    let group=formData? formData.map(d=>this.createNewGroup(d))
                      :[this.createNewGroup(null)]

    return this.formBuilder.group({
         formData: this.formBuilder.array(group)
       });
}

So, you can

this.registerForm=createform(this.formData) //create a form with data
this.registerForm=createform(null) //create a empty form

Upvotes: 1

shajan
shajan

Reputation: 630

You can also add controls like this.

component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl, ValidatorFn } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  registerForm: FormGroup;
  submitted = false;

  formData = [{ id: 'firstName', name: 'firstName' },
  { id: 'lastName', name: 'lastName' },
  { id: 'address', name: 'address' },
  { id: 'emailid', name: 'emailid' }
  ]


  constructor(private formBuilder: FormBuilder) {
    this.registerForm = this.formBuilder.group({
      list: this.formBuilder.array([])
    });
  }

  ngOnInit() {
    this.registerForm = this.formBuilder.group({
      list: this.formBuilder.array(
        this.formData.map(x => this.formBuilder.group({
          name: [x['name']],
          id: [x['id']]
        }))
      )
    })
  }

  onSubmit() {
    console.log(this.registerForm.value);
  }
}

Component.html

<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
  <span formArrayName="list">
  <div *ngFor="let dat of registerForm.get('list').controls;let index = index;" formGroupName="{{index}}">
     <label for="{{dat.name}}">{{dat.name }}</label>
     <input type="text" id="{{dat.get('id').value}}" formControlName="name" />  
    </div>
  </span>
<button type="submit">button</button>
</form>

Upvotes: 1

Swoox
Swoox

Reputation: 3740

I added a value cause you need an id to control an input field a name to set the label and a value to set the value. If you end up with a more dynamic way this will come in handy.

In your component you do:

formData = [{ id: 'firstName', name: 'firstName', value: '' },
  { id: 'lastName', name: 'lastName', value: '' },
  { id: 'address', name: 'address', value: '' },
  { id: 'emailid', name: 'emailid', value: '' }
  ]

  constructor(private formBuilder: FormBuilder) {
    let formGroups: FormGroup[] = []; 
    for(let i = 0; i < this.formData.length; i++){
      formGroups.push(this.formBuilder.group({
          id: this.formData[i].id,
          name: this.formData[i].name,
          value: this.formData[i].value,
      }));
    }
    this.registerForm = this.formBuilder.group({
        array: this.formBuilder.array(formGroups)
    })
   }

   onSubmit(){
    console.log(this.registerForm.value); 
   }

And in the html:

<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
  <div formArrayName="array">
    <div *ngFor="let dat of registerForm.get('array').controls;let i = index;" [formGroupName]="i">
        <label>{{dat.get('name').value}} </label>
        <input type="string" id={{dat.value.id}} #input formControlName="value">
    </div>
  </div>
</form>

<button><button>

Upvotes: 1

Krishna Rathore
Krishna Rathore

Reputation: 9687

you can use this.formBuilder.array for this.

Stackblitz

component.html

<form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
    <div formArrayName="formData">
        <div *ngFor="let dat of registerForm.get('formData').controls;let index = index;" [formGroupName]="index">
            <label>{{dat.get('name').value }}</label>
     <input type="text" formControlName="name" />  
    </div>
<button type="submit">Submit</button>
  </div>
</form>
<button type="button" (click)="addNew()">Add</button>

component.ts

registerForm: FormGroup;
  submitted = false;

  constructor(private formBuilder: FormBuilder) {
    this.registerForm = this.formBuilder.group({
      formData: this.formBuilder.array([this.createNewGroup()])
    });
   }

   createNewGroup() {
    return this.formBuilder.group({
      id: ['id'], 
      name: ['name'] 
    })
  }

  addNew(){
    let formArr=this.registerForm.get('formData') as FormArray;
    formArr.push(this.createNewGroup());
  }

   onSubmit(){
    console.log(this.registerForm.value); 
   }

Upvotes: 1

Related Questions