1
votes

I am using Angular 4 reactive to create nested forms.My forms structures like below

  • Form Group(userform)

  • FormArray(users)

  • FormGroup(idx)

In complete table come under Form Group and each table row come under FormArray(users) and each table data cells come under Formgroup(idx).

Error:

appComponent.html:20 ERROR Error: Cannot find control with path: 'users -> 0 -> '

HTML:

<form [formGroup]="userForm" (ngSubmit)="onFormSubmit()">
    <tbody formArrayName="users">
        <tr *ngFor="let user of users.controls; index as idx">
            <div [formGroupName]="idx">
          <td>
            <div class="mdl-select mdl-js-select mdl-select--floating-label">
            <select class="mdl-select__input" id="projectname{{i}}" name="projectname{{i}}"  [formControlName]="projectname">
              <option *ngFor="let project of projects;let first=first;let last:last">{{project.projectname}}</option>
            </select>
            <label class="mdl-select__label" for="professsion">Select Project Name</label>
            </div>
          </td>
          <td>
            <div class="mdl-textfield mdl-js-textfield">
              <input class="mdl-textfield__input" type="text" pattern="[0-9]*" id="sunday{{i}}" name="sunday{{i}}"  [formControlName]="sunday">
              <span class="mdl-textfield__error">Digits only</span>
            </div>
          </td>
    </tr>
    </table>
</form>

TS:

export class appComponent implements OnInit {

  ngOnInit() {

  }

  userForm = new FormGroup({

      users: new FormArray([
               new FormControl()
            ])
      });

      get userName(): any {
        return this.userForm.get('name');
      }
      onFormSubmit(): void {
        this.logData();
      }
      get users(): FormArray { 
        return this.userForm.get('users') as FormArray; 
      }
      addUserField() { 
        this.users.push(new FormControl()); 
      }
      deleteUserField(index: number) {
        this.users.removeAt(index);
      }

      logData(){
        for(let i = 0; i < this.users.length; i++) {
          console.log(this.users.at(i).value);
        }
      }

    }
1
Well quickly looking at your code, we can at least determine that you are trying to display a formcontrol named projectname in template even though there is no such form control in your form :) Same goes for the form control sunday. - AT82
Giving index value for formcontrol , i am getting only last input table data input element - CodeMan
I didn't quite get the comment. But anyway, the form controls in template must match the form control in form, and right now they do not match. - AT82

1 Answers

1
votes

First of all, your form controls do not match your template. Right now in your users array you just have one unspecified form control. Instead you should have the two form controls that you are displaying in the template. Assumingly you want an initial empty form group in your array, do:

this.userForm = this.fb.group({
  users: this.fb.array([
    this.initUsers();
  ])
});

initUsers() {
  return this.fb.group({
    projectname: [''],
    sunday: ['']
  });
}

where fb refers to FormBuilder injected in constructor.

With the above you now have the two form controls in your form array. You also call initUsers() when you want to add a new form group (row) in your table.

Then you need to remove the brackets around formcontrolName in your template, so instead of

[formControlName]="projectname"
....
[formControlName]="sunday"

do:

formControlName="projectname"
...
formControlName="sunday"

DEMO: http://plnkr.co/edit/qraDXUYOaOL9eClTqjqh?p=preview

Also worth mentioning, I see you have a pattern validation for sunday in template, remove that and set the Validators.pattern() instead for your form control.