Search code examples
angularangular-materialmat-table

Angular Material: selected row goes to the first position in the table


With Angular and Material, I have created a simple table which displays list of data.

You can find the table here on Stackblitz> angular-mat-table-selected-cell

My purpose is to select a row with a higlight. When the row is selected, it takes the first place at the top of the table. I've tried many things but nothing works... Any idea to help ?

Thanks! =D

mat-table-cell-selected.html

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

    <!-- Position Column -->
    <ng-container matColumnDef="position">
      <th mat-header-cell *matHeaderCellDef> No. </th>
      <td mat-cell *matCellDef="let people"> {{people.position}} </td>
    </ng-container>

    <!-- Name Column -->
    <ng-container matColumnDef="name">
      <th mat-header-cell *matHeaderCellDef> Name </th>
      <td mat-cell *matCellDef="let people"> {{people.name}} </td>
    </ng-container>

    <!-- Age Column -->
    <ng-container matColumnDef="age">
      <th mat-header-cell *matHeaderCellDef> Age </th>
      <td mat-cell *matCellDef="let people"> {{people.age}} </td>
    </ng-container>

    <!-- Initials Column -->
    <ng-container matColumnDef="initials">
      <th mat-header-cell *matHeaderCellDef> Initials </th>
      <td mat-cell *matCellDef="let people"> {{people.initials}} </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
  </table>
</div>

mat-table-cell-selected.ts

import {Component} from '@angular/core';

/**
 * @title Table with sticky header
 */
@Component({
  selector: 'mat-table-cell-selected',
  styleUrls: ['mat-table-cell-selected.css'],
  templateUrl: 'mat-table-cell-selected.html',
})

export class MatTableCellSelected {
  displayedColumns = ['position', 'name', 'age', 'initials'];
  dataSource = ELEMENT_DATA;
}

export interface People {
  position: number;
  name: string;
  age: number;
  initials: string;
}

const ELEMENT_DATA: People[] = [
  {position: 1, name: 'Ben', age: 46, initials: 'BG'},
  {position: 2, name: 'Hugo', age: 9, initials: 'HG'},
  {position: 3, name: 'Theo', age: 6, initials: 'TG'},
  {position: 4, name: 'Emy', age: 42, initials: 'EC'},
  {position: 5, name: 'Wamwam', age: 24, initials: 'BB'},
  {position: 6, name: 'Defre', age: 12, initials: 'FK'},
  {position: 7, name: 'Zakk', age: 56, initials: 'ZW'},
  {position: 8, name: 'Ned', age: 61, initials: 'NF'},
  {position: 9, name: 'Tryphon', age: 91, initials: 'TT'},
  {position: 10, name: 'Misrilou', age: 19, initials: 'MF'},
];

mat-table-cell-selected.css

.example-container {
  height: 400px;
  overflow: auto;
}

table {
  width: 100%;
}

Solution

  • On your row definition, you want to add a click event for selection and a ngClass to highlight the selected row

    <tr mat-row 
       *matRowDef="let row; columns: displayedColumns;" 
       [ngClass]="{'highlight': selectedRowPosition == row.position}"
       (click)="moveToTop(row)"></tr>
    

    From there you want to add the following code to find the index of where the bad row is filtered out and then push it to the top of the dataset.

    export class MatTableCellSelected {
      displayedColumns = ['position', 'name', 'age', 'initials'];
      dataSource = ELEMENT_DATA;
      selectedRowPosition = -1;
    
      moveToTop(ev) {
         this.dataSource = this.dataSource.filter(r => r.position !== ev.position);
         this.dataSource = [ev].concat(this.dataSource);
         this.selectedRowPosition = ev.position;
      }
    }
    

    here is a working stackblitz


    EDIT: Here are the stackoverflows I used to get the answer
    remove item from list
    add to start of array
    highlight array row in angular table