Angular 4 Material table highlight a row

AngularAngular Material2

Angular Problem Overview


I'm looking for a good way to highlight the whole a row in md-table.
Should I do directive or what?

    <!--- Note that these columns can be defined in any order.
          The actual rendered columns are set as a property on the row definition" -->

    <!-- ID Column -->
    <ng-container cdkColumnDef="userId">
      <md-header-cell *cdkHeaderCellDef> ID </md-header-cell>
      <md-cell *cdkCellDef="let row"> {{row.id}} </md-cell>
    </ng-container>

    <!-- Progress Column -->
    <ng-container cdkColumnDef="progress">
      <md-header-cell *cdkHeaderCellDef> Progress </md-header-cell>
      <md-cell *cdkCellDef="let row"> {{row.progress}}% </md-cell>
    </ng-container>

    <!-- Name Column -->
    <ng-container cdkColumnDef="userName">
      <md-header-cell *cdkHeaderCellDef> Name </md-header-cell>
      <md-cell *cdkCellDef="let row"> {{row.name}} </md-cell>
    </ng-container>

    <!-- Color Column -->
    <ng-container cdkColumnDef="color">
      <md-header-cell *cdkHeaderCellDef>Color</md-header-cell>
      <md-cell *cdkCellDef="let row" [style.color]="row.color"> {{row.color}} </md-cell>
    </ng-container>

    <md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
    <md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
  </md-table>
</div>

Table from: https://material.angular.io/components/table/overview

Angular Solutions


Solution 1 - Angular

Update for Newer Material Version (md --> mat):

html:

<!-- Add the highlight class in row definiton of md-table -->
<!-- Add click event to pass the selected row index -->

<mat-row *cdkRowDef="let row; columns: displayedColumns;" 
         [ngClass]="{'highlight': selectedRowIndex == row.id}"
         (click)="highlight(row)">
</mat-row>

Original Answer:

You can do it by using ngClass and a flag like selectedRowIndex. Whenever clicked row index is equal to selectedRowIndex, the class will be applied.

Plunker demo

html:

<!-- Add the highlight class in row definiton of md-table -->
<!-- Add click event to pass the selected row index -->

<md-row *cdkRowDef="let row; columns: displayedColumns;" 
         [ngClass]="{'highlight': selectedRowIndex == row.id}"
         (click)="highlight(row)">
</md-row>

css:

.highlight{
  background: #42A948; /* green */
}

ts:

selectedRowIndex = -1;

highlight(row){
    this.selectedRowIndex = row.id;
}

Solution 2 - Angular

In the table overview examples page they explain the SelectionModel for handling selections - which incidentally also handles multi-selection.

selection is a SelectionModel defined in your component. I couldn't find any actual documentation for this but the implementation is extremely simple.

selection = new SelectionModel<CustomerSearchResult>(false, null);

The first parameter is allowMultiSelect, so to allow multiple items to be selected at once set it to true. When false the selection model will deselect any existing values when you set a new value.

Then add a click event to select() the row and create your own css class for when the row is selected.

   <mat-table>
        ...

        <mat-row *matRowDef="let row; columns: displayedColumns;"
                 [ngClass]="{ 'selected': selection.isSelected(row)}"
                 (click)="selection.select(row)"></mat-row>

    </mat-table>

The css class I added is below (the sample doesn't mention styling yet) and then you just need to add to your css

.mat-row {
   min-height: 65px;

   &.selected {
       background: #dddddd;
   }
}

If your background color is too dark you'll need to add styles yourself to invert the text color.

To handle selection use the onChange event of selection.

    // selection changed
    this.selection.onChange.subscribe((a) =>
    {
        if (a.added[0])   // will be undefined if no selection
        {
            alert('You selected ' + a.added[0].fullName);
        }
    });

Or alternatively the selected items are in this.selection.selected.

I'm hoping mat-table gets improved for common cases like this and they don't just leave everything up to the developer. Things like keyboard events etc. would be nice to be handled automatically with respect to the selection model.

Solution 3 - Angular

I did not have unique identifiers like id column in my table data but this worked for me (material 6):

HTML

 <tr mat-row *matRowDef="let row; columns: displayedColumns" 
     (click)="selectedRow = row" [ngClass]="{ 'selected': row === selectedRow }"> 
 </tr>

or HTML if you want to enable users to unselect on another click

 <tr mat-row *matRowDef="let row; columns: displayedColumns" 
     (click)="selectedRow = selectedRow === row ? null : row" [ngClass]="{ 'selected': row === selectedRow }"> 
 </tr>

add variable to TS

selectedRow;

(S)CSS

.selected {
  background-color: red;
}

If you want to do more things than just styling when selecting a row, replace (click)="selectedRow = row" with (click)="selectRow(row)" and add this function to your ts:

selectRow(row) {
    this.selectedRow = row;
    // more stuff to do...
}

Solution 4 - Angular

So, I ran into this issue as well. I'm using the newer 'mat-' instead of 'md-', but I'm GUESSING it will be about the same...

<mat-row
    *matRowDef="let row; columns: myColumns; let entry"
    [ngClass]="{ 'my-class': entry.someVal }">
</mat-row>

I didn't find that anywhere, I just tried it and it happened to work out, so I hope that's right. The big thing was tagging 'let entry' to the end of the other matRowDef stuff. Sorry I'm so late to the party. Hopefully this does someone some good.

Solution 5 - Angular

For material": "^7.0.3",

use the css name in html, without the single quote, to highlight the row

 .mat-row.highlighted {
  background: lightblue;
  }


<tr mat-row *matRowDef="let row; columns: displayedColumn;" 
[ngClass]="{highlighted: selectedRowIndex == row.id}"  (click)="highlight(row)" > 
</tr>


highlight(row){
this.selectedRowIndex = row.id;
}

Solution 6 - Angular

Building on Zuzzie's answer, which is the solution that mostly worked for me, I did the following:

HTML:

<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;" 
    (click)="onRowClicked(row)" [ngClass]="{ 'selected': row === selectedRow }">
</mat-row>

add variable to TS:

selectedRow : boolean;

add this function to TS:

onRowClicked(row) {

   if(!this.selectedRow)
   {
     this.selectedRow = row;
   }   
   else
   {
     this.selectedRow = row;
   }

}

(S)CSS

.selected {
  background-color: red;
}

Solution 7 - Angular

This will allow you to select multiple rows if the row is not previously selected and on clicking again it will deselect it.

HTML

<mat-row *matRowDef="let row; columns: displayedColumns;"
  (click)="findOut(row)"[style.background]="highlightedRows.indexOf(row) != -1 ? 'lightgrey' : ''"></mat-row>

Type Script

Create an array

highlightedRows = [];

Define the findOut function

findOut(row){
  if(this.highlightedRows.indexOf(row) === -1){
    this.highlightedRows.push(row);
    }
    else{
    
      this.highlightedRows[this.highlightedRows.indexOf(row)] = -1;
    }
    
  }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTaison MorrisView Question on Stackoverflow
Solution 1 - AngularNehalView Answer on Stackoverflow
Solution 2 - AngularSimon_WeaverView Answer on Stackoverflow
Solution 3 - AngularZuzzeView Answer on Stackoverflow
Solution 4 - AngularNick LandkamerView Answer on Stackoverflow
Solution 5 - AngularPriyaView Answer on Stackoverflow
Solution 6 - AngularnoelView Answer on Stackoverflow
Solution 7 - AngularJaydeep NayakView Answer on Stackoverflow