Search code examples
arraysangulartypescriptangular-materialangular-material-table

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


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.