1

I am trying to create a dynamic form where you can add forms dynamically, and sub forms dynamically. For example:

+ user1  
--- + color1  
--- + color2  
--- + color3  
+ user2  
--- + color1  
--- + color2  
--- + color3  
+ user 3  
--- + color1

Where as you can add as many users as you want, and you can add as many colors as you want to each user. I can get the first array to work (users), but not sure about the nested array (colors). I have it set up so it loads a user and a color at the beginning. Here is my code I have so far:

export class FormsComponent implements OnInit {

  myForm: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.myForm = this.fb.group({
      email: '',
      users: this.fb.array([])
    })
  }

  get userForms() {
    return this.myForm.get('users') as FormArray
  }

  get colorForms() {
    return this.userForms.get('colors') as FormArray
  }

  addUser() {
    const userGroup = this.fb.group({
      user: [],
      colors: this.fb.array([])
    })
    this.userForms.push(userGroup);
  }

  deleteUser(i) {
    this.userForms.removeAt(i);
  }

  addColor() {
    const colorGroup = this.fb.group({
      color: []
    })
    this.colorForms.push(colorGroup);
  }

  deleteColor(i) {
    this.colorForms.removeAt(i)
  }

}

And this is my html code:

<form [formGroup]="myForm">

  <hr>

  <input formControlName="email">

  <div formArrayName="users">

    <div *ngFor="let user of userForms.controls; let i=index" [formGroupName]="i">

      <input formControlName="user">

      <button (click)="deleteUser(i)">Delete User</button>

      <div formArrayName="colors">

        <div *ngFor="let color of colorForms.controls; let t=index" [formGroupName]="t">

          <input formControlName="color">

          <button (click)="deleteColor(t)">Delete Color</button>

        </div>

      </div>

    </div>

  </div>

  <button (click)="addUser()">Add User</button>

</form>

Obviously this doesn't work, so I am trying to comprehend what I need to do.

1 Answer 1

1

It doesn't work because you do not take into account the index in which controls are stored.

For example

get colorForms() {
    return this.userForms.get('colors') as FormArray
}

won't work since userForms returns FormArray and you have to specify index to get colors control which belongs to specific user.

So it might look like:

getColors(index) {
  return this.userForms.get([index, 'colors']) as FormArray;
}

and in html:

<div *ngFor="let color of getColors(i).controls;...>

Also you need to keep it in mind when working with colors array:

addColor(index: number) {
  const colorGroup = this.fb.group({
    color: []
  })

  this.getColors(index).push(colorGroup);
        ^^^^^^^^^^^^
 use the them method to get correct FormArray
}

deleteColor(userIndex: number, colorIndex: number) {
  this.getColors(userIndex).removeAt(colorIndex);
}

See also Ng-run Example

Sign up to request clarification or add additional context in comments.

1 Comment

Works like a charm. I knew I needed to refer to the color index somehow, but I didn't know how to do it! Wonderful! Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.