I would like to add a slightly different take on
Sudarshana Dayananda's answer so you don't have to add new fields to your data:
1) Ensure that your data object (for each row) has an "id" field.
2) Add the following to the mat-row:
<tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="onRowClicked(row)"
(mouseover)='mouseOverRow(row)' (mouseleave)='mouseLeaveRow(row)'></tr>
3) And then in .ts set the currently hovered row as a class variable:
mouseOverRow(row) {
this.hoveredRow = row;}
mouseLeaveRow(row) {
this.hoveredRow = null;}
4) So on the checkbox/button you can add:
[class.buttonInvisible]='!hoveredRow || (element.id !== hoveredRow.id)'
My component looks like this:
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<!-- {{ 'Generic.select' | translate }} -->
</th>
<td mat-cell *matCellDef="let element" style='text-align:end; width:40px;'>
<button [class.buttonInvisible]='!hoveredRow || (element.id !== hoveredRow.id)' class='tableActionButton' mat-icon-button
color="accent" aria-label="Delete" (click)="onDeleteClicked(element);$event.stopPropagation();">
<mat-icon>delete</mat-icon>
</button>
</td>
</ng-container>
where buttonInvisible css:
.buttonInvisible{
opacity: 0 !important;}
Let me quickly explain the logic here. The buttonInvisible class is conditionally applied to all checkboxes/buttons when (1) the class hoverRow is not initialised (so no hovering has happened yet) or (2) the row element id does not match the current hovered row's id. So you'll only see the checkbox over the specific row if the id matches the currently hovered set row.