How to add a button on each row of a table in Angular Material?

Issue

I want to display a button on each row of a table.

Code from html component

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

<ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
    <th id="head" mat-header-cell *matHeaderCellDef> {{column}} </th>
    <td mat-cell *matCellDef="let element"> {{element[column]}} </td>
    <td mat-cell *matCellDef="let element" class="action-link"><a>See details</a></td>
</ng-container>

    <tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
    <tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
</table>

Code from ts component

export class LoginComponent implements OnInit {

     displayedColumns: string[] = ['idItem', 'nameItem', 'options'];
     columnsToDisplay: string[] = this.displayedColumns.slice();

     itemList: Items[] = [];
     dataSource = [];

     constructor(private itemService: ItemsService) { }

     ngOnInit(): void {
          this.itemList = [];
          this.itemService.list().subscribe(data => {
          data.forEach(element => {
              this.itemList.push({idItem: element.idItem, nameItem: element.nameItem});
          });
          this.dataSource = this.itemList;
      });
   }
}

The data of the table is obtained from a service that returns a list, in the table for each row I want to put a button that obtains the id of the item in each row. I’ve been reviewing how to do this, but the button is not showing up in the table.

Solution

You need <ng-container> element to check whether the current column value is ‘options’ or not with *ngIf. If not, it will use <ng-template #optionsTemplate>.

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
    <th id="head" mat-header-cell *matHeaderCellDef>{{ column }}</th>

    <ng-container *ngIf="column != 'options'; else optionsTemplate">
      <td mat-cell *matCellDef="let element">{{ element[column] }}</td>
    </ng-container>

    <ng-template #optionsTemplate>
      <td mat-cell *matCellDef="let element" class="action-link">
        <a>See details</a>
      </td>
    </ng-template>
  </ng-container>

  ...
</table>

Sample Solution on StackBlitz

Note:

According to Define the column templates, each column definition should only have single mat-header-cell and mat-cell element.

Each column definition should be given a unique name and contain the content for its header and row cells.

Answered By – Yong Shun

Answer Checked By – David Marino (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.