Greg
Greg

Reputation: 6613

Angular dynamic form group inputs

So I have a form that has some basic family information. Then I want to have part of the form to add in children of the family. I'm using reactive forms, that looks something like this:

    this.details = fb.group({
      firstName: ['', Validators.required],
      lastName: ['', Validators.required],
      email: ['', Validators.compose([Validators.required, Validators.email])],
      phone: ['', Validators.required]
    });

Now, at some point in the UI, there will be inputs for children names, with the option to add more. Can I programatically add more input fields to the this.details group?

Update

@incognito's answer is perfect for the original question I asked. It shall remain the selected answer. While doing some digging on his answer I also found FormArray, which is the direction I ended up going, so I wanted to add that here. It looks like:

this.form = this.fb.group({
  ...
  children: this.fb.array([
    this.fb.group({
      name: ['', Validators.required],
      age: ['', Validators.required],
      gender: ['', Validators.required]
    })
  ])
});

Then, the view looks like:

<form [formGroup]="form">
    <div *ngFor="let child of form.controls.children.controls; let i = index;"
         formArrayName="children"
         class="childForm">
        <div [formGroupName]="i"
             class="row">
            <div class="col-md-4">
                <input type="text"
                       class="form-control"
                       formControlName="name">
            </div>
            <div class="col-md-4">
                <input type="number"
                       class="form-control"
                       formControlName="age">
            </div>
            <div class="col-md-4">
                <select class="form-control"
                        formControlName="gender">
                    <option value="male">Male</option>
                    <option value="female">Female</option>
                </select>
            </div>
        </div>
    </div>
    <button (click)="addChild()"
            class="btn btn-primary">
        <i class="fa fa-plus"></i> Add Another Child
    </button>
</form>

And the addChild function referenced in the button at the bottom of the form looks like:

addChild() {
  const children = <FormArray>this.form.get('children');
  children.push(this.fb.group({
    name: [''],
    age: [''],
    gender: ['']
  }));
}

So, again, this is a different way of going about it, and I only discovered it after digging in on @incognito's answer. Thanks @incognito!

Upvotes: 1

Views: 785

Answers (1)

Julius Dzidzevičius
Julius Dzidzevičius

Reputation: 11000

Sure you can. Implementation might be better, but something like this:

<button (click)="addKid()"> Add kid </button

numberOfKids: number = 0;

addKid() {
 this.numberOfKids++;
 let input = this.renderer.createElement('input');
 this.renderer.appendChild(form, input);
 this.renderer.setProperty(input, 'formControlName', this.numberOfKids); 

 this.details.addControl(this.numberOfKids, new FormControl(''));
}

So every formControl for every kid will be named as a number.

This implementation is based on Renderer2 (recommended way to "directly" manipulate DOM elements)

Upvotes: 1

Related Questions