Adding a new line in the table with Angular

Viewed 864

So I am trying to add a new line in a table which is populated from an API but it looks that I miss something. Here is my code:

HTML:

<button mat-flat-button color="primary" class="btn-add" 
    (click)="addRow()" 
    [disabled]="isLoading">ADD</button>

<table mat-table [dataSource]="dataSource" class="mat-elevation-z2" *ngIf="show">
  <ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
    <th mat-header-cell *matHeaderCellDef>{{column}}</th>
    <td mat-cell *matCellDef="let element; index as i;">
      <span *ngIf="element.editing; then editBlock else displayBlock"></span>
      <ng-template #displayBlock>{{element[column]}}</ng-template>
      <ng-template #editBlock>
        <mat-form-field appearance="fill">
          <input matInput [(ngModel)]="element[column]">
        </mat-form-field>
      </ng-template>
    </td>
  </ng-container>
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

TS file:

displayedColumns: string[] = [];
dataSource: any;

addRow() {
  console.log("Adding new row");
  let newRow = {
    editing: true
  };
  this.displayedColumns.forEach(x => newRow[x] = "");
  this.dataSource.push(newRow);
}
2 Answers

Reference to the variable dataSource is not updated. Angular change detector not always can (while sometimes can) recognize such changes. Creating new reference (new array in this case) should solve this issue:

addRow() {
  let newRow = { editing: true };
  this.displayedColumns.forEach(x => newRow[x]="");
  this.dataSource = [...dataSource, newRow];
}

You are missing the table.renderRows() call

Documentation:

If a data array is provided, the table must be notified when the array's objects are added, removed, or moved. This can be done by calling the renderRows() function which will render the diff since the last table render. If the data array reference is changed, the table will automatically trigger an update to the rows.

HTML

<table #elementTable mat-table class="mat-elevation-z2"
    *ngIf="show"
    [dataSource]="dataSource">

TS

@ViewChild('elementTable') matTable: MatTable<any>;

And in addRow() function

addRow() {
  console.log("Adding new row");
  const newRow: any = {
    column: '',
    editing: true
  };
  this.dataSource.push(newRow);
  this.table.renderRows();
}
Related