0

I want to create a table like below, which is a editable form table in angular 2+. From user I will get the adult count, child count and infant count.

 **#          First name    Last name   Age**
    Adult 1   fn1           Ln16        Dec 27
    Adult 2   fn2           Ln15        Dec 27
    Adult 3   fn3           Ln14        Dec 27
    Child 1   fn4           Ln13        Dec 27
    Child 2   fn5           Ln12        Dec 27
    Infant 1  fn6           Ln11        Dec 27

By the use input I will build the form like

   ngOnInit() {
        this.travellerForm=this.formBuilder.group({
          adults: this.formBuilder.array([]),
          children: this.formBuilder.array([]),
          infant: this.formBuilder.array([])
        })
        const control1 = this.travellerForm.controls['adults'] as FormArray;
        for (let i = 0; i < this.adultCount; i++) {
          control1.push(this.adultForm());
        }
        const control2 = this.travellerForm.controls['children'] as FormArray;
        for (let i = 0; i < this.childCount; i++) {
          control2.push(this.childForm());
        }
        const control3 = this.travellerForm.controls['infant'] as FormArray;
        for (let i = 0; i < this.infantCount; i++) {
          control3.push(this.infantForm());
        }
      }

      adultForm() {
        let d = new Date();
        d.setFullYear(d.getFullYear() - 12);
        return this.formBuilder.group({
          first_name  : [''],
          last_name : [''],
          dob: [new Date(d)],
        });
      }
      childForm() {
        let d = new Date();
        d.setFullYear(d.getFullYear() - 2);
        return this.formBuilder.group({
          first_name  : [''],
          last_name : [''],
          dob: [new Date(d)],
        });
      }
        infantForm() {
          let d = new Date();
          d.setFullYear(d.getFullYear() - 2);
          return this.formBuilder.group({
            first_name  : [''],
            last_name : [''],
            dob: [new Date(d)],
          });
      }

The html is like

<form [formGroup]="travellerForm" class="form-horizontal">
      <div class="table-responsive">
        <table class="table table-bordered table-striped table-highlight">
          <thead>
            <th>#</th>

            <th>First Name</th>
            <th>Last Name</th>
            <th>DOB</th>
                         </thead>
          <tbody>
            <tr *ngFor="
                        let Y of travellerForm['controls’].children[
                          'controls'
                        ];
                        let ix = index
                      " [formGroupName]="ix">
              <td>Adult 1</td>

              <td><input type="text" class="form-control" /></td>
              <td><input type="text" class="form-control" /></td>
              <td><input type="text" class="form-control" bsDatepicker #dp1="bsDatepicker" /></td>


            </tr>

            <tr *ngFor="
                        let Y of travellerForm['controls'].adults[
                          'controls'
                        ];
                        let ix = index
                      " [formGroupName]="ix">
              <td>Adult 1</td>

              <td><input type="text" class="form-control" /></td>
              <td><input type="text" class="form-control" /></td>
              <td><input type="text" class="form-control" bsDatepicker #dp1="bsDatepicker" /></td>


            </tr>

            <tr *ngFor="
                        let Y of travellerForm['controls’].infants[
                          'controls'
                        ];
                        let ix = index
                      " [formGroupName]="ix">
              <td>Adult 1</td>

              <td><input type="text" class="form-control" /></td>
              <td><input type="text" class="form-control" /></td>
              <td><input type="text" class="form-control" bsDatepicker #dp1="bsDatepicker" /></td>


            </tr>

          </tbody>
        </table>
      </div>
    </form>

It is giving “Cannot find control with unspecified name attribute” error. How can I solve it and have a table like above.

Asmitha j.s
  • 267
  • 4
  • 16
  • You can refer the stackblitz link (https://stackblitz.com/edit/angular-dynamic-nested-form) from this answer https://stackoverflow.com/a/55295275/6019563 – Sachin Gupta Apr 02 '19 at 06:39
  • Thank you, But I don't have problem with adding and deleting nested form arrays. But i have a problem with creating single table which consists multiple formArrays. – Asmitha j.s Apr 02 '19 at 06:43
  • The code there shows the usage of `formArray` within `formArray`, thought you could find some help. Can you create a minimum reproduction for your error on stackblitz ? It will be helpful in answering the question. – Sachin Gupta Apr 02 '19 at 08:29

1 Answers1

0

You are missing formArrayNames on your groups

 <ng-container formArrayName="children">
        <tr *ngFor="
                    let Y of travellerForm['controls’].children[
                      'controls'
                    ];
                    let ix = index
                  " [formGroupName]="ix">
          <td>Adult 1</td>

          <td><input type="text" class="form-control" /></td>
          <td><input type="text" class="form-control" /></td>
          <td><input type="text" class="form-control" bsDatepicker #dp1="bsDatepicker" /></td>
        </tr>
</ng-container>

Just change all of these and it should work fine. I would change the *ngFor to

travellerForm.get('children').controls

since its much cleaner.

You will need to make this changes for each form array accordingly. Ive made only for children as an example.

When you use formArrays to implement them properly you need to remember how you access normal arrays with objects

example array users = [{name:'Jack', age:20}, {name:'Peter', age:29}]

users[0] to access the user on position 0

formArrayName is users, formGroup is 0 (or i from the *ngFor), hence:

 <form [formGroup]="form">
    <div formArrayName="users">
     <div *ngFor="let user of form.get('users').controls; let i = index">
      <div [formGroupName]="i">
         /*user at position i*/
      </div>
     </div>
    </div>
</form>
Qellson
  • 532
  • 2
  • 7
  • Thank you. I'll do the changes. But as I'm using tables, if i add div box, to all the formarrays, the look of header and table body will not be in order, as i'm not giving fixed width to the inputs. – Asmitha j.s Apr 02 '19 at 07:59
  • no need for divs, it was just an example, it can be any other viable element, you can squeeze it to 2 element by moving formGroupName where ngFor is, but you cant to 1, becouse 1 element cant have 2 different fNames – Qellson Apr 02 '19 at 08:29
  • i forgot, you can use ng-container to avoid adding new html elements, i will edit the asnwer – Qellson Apr 02 '19 at 08:38
  • Great! Glad it helped! :) – Qellson Apr 02 '19 at 10:18