[SOLVED] Angular – How to update table element via its index in a filtered table?

Issue

I have a table which gets its data from a MatTableDataSource. The data source contains a filter which can be used to only show elements in the table which have a specific attribute set to either true or false. This is how I add the filter to the data source in my ngOnInit() function:

this.dataSource.filterPredicate = function (record, filter) {
  return record.disabled === ConverterService.toBoolean(filter);
};

this.dataSource.filter = "false";

Inside the table I have a button for each element which can be clicked to open an edit dialog so the user can change any of the element attributes. After closing the dialog, I use the table index to overwrite the old element with the new element that was returned by the edit dialog. This is how the function which opens the dialog and updates the table data looks like:

  editProjectDialog(projectId: number, index: number, $event: MouseEvent) {
    $event.stopPropagation();
    const dialogRef = this.dialog.open(EditProjectDialogComponent, {
      data: projectId,
    });
    dialogRef.afterClosed().subscribe((result) => {
      this.projects[index] = result;
      this.dataSource.data = this.projects;
    });
  }

This is how the function is called:

 <ng-container matColumnDef="edit">
    <th mat-header-cell *matHeaderCellDef>Edit</th>
    <td mat-cell *matCellDef="let element; let index = index">
      <button
        mat-icon-button
        (click)="editProjectDialog(element.id, index, $event)"
        matTooltip="Edit"
      >
        <mat-icon>edit</mat-icon>
      </button>
    </td>
  </ng-container>

This code used to work just fine while there was no filter added to the data source, but now it no longer works because the index in the table does not match the index in the projects array (because the projects array contains all elements and the index is only for the filtered elements which are displayed in the table). I also tried to directly modify the element by replacing this.projects[index] with this.dataSource.data[index] or even with this.dataSource.filteredData[index] but none of this seemed to work. How can I update the edited element in the data source to apply the changes to the table?

Solution

You could probably get the right index using another method. How about looking for the element in the projects array like this:

const rightIndex = this.projects.findIndex(item => item.id === result.id);
this.projects[rightIndex] = result;
this.dataSource.data = this.projects;

After you find the correct index, then you can go ahead and replace the element. You might need to destructure the projects array when assigning it as the dataSource.data like this: this.dataSource.data = [...this.projects];

Answered By – Octavian M─ârculescu

Answer Checked By – Marilyn (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *