0

I'm trying to create FormArray inside Angular Material Table for each rows(it means I have 6 rows in my table and I want create 6 form arrays but it should add automatically for each rows, there is no option like adding row). I am facing error like:

ERROR Error: Cannot find control with path: 'time_sheet_array -> 4' for each rows and after creating form arrays I want to submit the whole form which contains 6 form arrays with values, please help me to come out of this problem, thanks in advance.

I have created material table and able to display all values. But I am unable to create form arrays for each rows.

table.html:

<div>
  <form [formGroup]="time_form">
    <table mat-table [dataSource]="dataSource" formArrayName="time_sheet_array" class="mat-elevation-z8">

      <!-- Position Column -->
      <ng-container matColumnDef="DAYS">
        <th mat-header-cell *matHeaderCellDef> DAYS </th>

        <td mat-cell *matCellDef="let element;let i = index;" [formGroupName]="i">
          <mat-form-field>
            <input matInput type="text" formControlName="days" [value]="element.dayOfWeek">
          </mat-form-field>
        </td>

      </ng-container>

      <!-- Name Column -->
      <ng-container matColumnDef="DATE">
        <th mat-header-cell *matHeaderCellDef> DATE </th>

        <td mat-cell *matCellDef="let element;let i = index;" [formGroupName]="i">
          <mat-form-field>
            <input matInput type="text" formControlName="date" [value]="element.dateOfDay">
          </mat-form-field>
        </td>

      </ng-container>

      <!-- Weight Column -->
      <ng-container matColumnDef="HOURS">
        <th mat-header-cell *matHeaderCellDef> HOURS </th>

        <td mat-cell *matCellDef="let element;let i = index;" [formGroupName]="i">
          <mat-form-field>
            <input matInput formControlName="hours" [value]="element.hours" placeholder="HOURS">
          </mat-form-field>
        </td>

      </ng-container>

      <ng-container matColumnDef="ACTIVITIES">
        <th mat-header-cell *matHeaderCellDef> ACTIVITIES </th>

        <td mat-cell *matCellDef="let element;let i = index;" [formGroupName]="i">
          <mat-form-field>
            <input matInput formControlName="activities" [value]="element.activity" placeholder="ACTIVITIES">
          </mat-form-field>
        </td>

      </ng-container>


      <!-- Symbol Column -->
      <ng-container matColumnDef="MODIFIED_BY">
        <th mat-header-cell *matHeaderCellDef> MODIFIED-BY </th>

        <td mat-cell *matCellDef="let element;let i = index;" [formGroupName]="i">
          <mat-form-field>
            <input matInput formControlName="modified_by" [value]="element.timesheetFilledByUserName" placeholder="ACTIVITIES">
          </mat-form-field>
        </td>

      </ng-container>

      <ng-container matColumnDef="TIME">
        <th mat-header-cell *matHeaderCellDef> TIME </th>

        <td mat-cell *matCellDef="let element;let i = index;" [formGroupName]="i">
          <mat-form-field>
            <input matInput formControlName="time" [value]="element.timesheetFilledByUserTime" placeholder="ACTIVITIES">
          </mat-form-field>
        </td>

      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
    </table>
  </form>
  <br>
  <div class="buttoncenter">
    <button mat-raised-button type="submit" color="primary" class="button" (click)="save_timesheet(time_form.value)">SAVE TIMESHEET</button>
  </div>
</div>

table.ts:

time_form: FormGroup;
private time_sheet_array: Array < any > = [];

response: user_timesheet[];
dataSource: MatTableDataSource < user_timesheet > ;

displayedColumns = ['DAYS', 'DATE', 'HOURS', 'ACTIVITIES', 'MODIFIED_BY', 'TIME'];

constructor(private _formBuilder: FormBuilder, private service: ServicesService) {}

ngOnInit() {
  this.time_form = this._formBuilder.group({
    time_sheet_array: this._formBuilder.array([
      this._formBuilder.group({
        days: [''],
        date: [''],
        hours: [''],
        activities: [''],
        modified_by: [''],
        time: ['']
      })
    ])
  })
  this.user_timesheet();
}

user_timesheet() {
  this.service.user_timesheet(credentials).subscribe(
    response => {
      this.dataSource = response;
    }
  );
}

save_timesheet(value) {
  console.log("timesheet values:::", value);
}

Result:->

actually this is kind of time sheet form which contains many form arrays, i want to display it through angular material table, so it will be very easy for me and field should be editable. after displaying through table i want to submit full form.

enter image description here

pk_teckie
  • 147
  • 3
  • 17
  • not use formGroupName, use directly formControl, see an example in https://stackoverflow.com/questions/56566003/array-of-formgroup-within-mat-table-for-each-row/56571113#56571113. If you want to add columns or rows, https://stackoverflow.com/questions/56562871/angular-6-html-table-create-dynamic-columns-and-rows/56664523#56664523 – Eliseo Jul 12 '19 at 06:09
  • yes i gone through the solution, but its hard coded. You are creating each form array manually but i don't want to create manually based on response i want to create form arrays, there is no logic at all. – pk_teckie Jul 12 '19 at 06:29
  • the form array creation should be based on back end response, suppose response contains 7 arrays and i have to create 7 form arrays in UI. – pk_teckie Jul 12 '19 at 06:43
  • In https://stackblitz.com/edit/angular-wmfjhh-td3dm4?file=app%2Ftable-basic-example.ts, I put some more "scalable", Yes, I hard coded the data. You need put all under the susbcribe function. But I don't understand so much. I think you want to create a unique array of object, not severals arrays. (note you can also create the variables displayedColumns and displayedControls after read the data – Eliseo Jul 12 '19 at 06:47
  • I just updated the code using a service – Eliseo Jul 12 '19 at 07:10
  • can u just tell me, how to assign values to form controls, because i am getting some response form back end. in above you hard coded values by creating const(const dataReceived = [{ name: "one", surname: "surname one" }, { name: "two", surname: "surname two" }, { name: "three", surname: "surname three" }]). but in response i am getting some arrays. – pk_teckie Jul 12 '19 at 09:25
  • @Eliseo everything is ok, its creating form controls but i stucked while assigning values, its not rendering values there, please help we are almost at the end. in response each key name is different so that i am unable assign values – pk_teckie Jul 12 '19 at 09:42
  • can you updated your question including an example of the data received? NOTE: I use directly new FormArray, new FormGroup and new FormControl, not formBuilder, but it's the same. When you receiver de data, make a forEach with the data, create a formGroup and push in the formArray – Eliseo Jul 12 '19 at 09:51
  • see my answer, I hope this can help you – Eliseo Jul 12 '19 at 10:11

1 Answers1

0

If you has a formArray of formgroup it's only equal dataSource to the array.controls

this.dataSource = this.myformArray.controls;

Each column has a *matCellDef="let element", and we make a input using formControl="element.get('nameOfControl')"

e.g. for a formArray of formGroup that has a propertie "prop1"

myFormArray=FormArray([new FormGroup({
    prop1:new FormControl()
  })
])

The table is like

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <ng-container *matColumnDef="prop1">
    <th mat-header-cell *matHeaderCellDef> Name </th>
    <td mat-cell *matCellDef="let element">
       <input arrow-div [formControl]="element.get('prop1')">
       </td>
  </ng-container>
  ...
</table>

Update supose that you has

user_timesheet() {
  this.service.user_timesheet(credentials).subscribe(
    response => {
        response.data.forEach(data => {
        const formGroup = new FormGroup({
          days:new FormControl(data.days),
          date:new FormControl(data.date),
          ...
        })
        (this.time_form.get('time_sheet_array') as FormArray).push(formGroup)
      })
      this.dataSource = (this.time_form.get('time_sheet_array') as FormArray).controls;
    }
  );
}
Eliseo
  • 50,109
  • 4
  • 29
  • 67