saikrishna
saikrishna

Reputation: 3

Angular Material - Sort the data for mat-table

I am using Angular Material. How can I sort the data?

HTML file

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


    <ng-container matColumnDef="position">
        <mat-header-cell *matHeaderCellDef mat-sort-header> No. </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.assetId}} </mat-cell>
    </ng-container>


    <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
        <td mat-cell *matCellDef="let element"> {{element.assetName}} </td>
    </ng-container>


    <ng-container matColumnDef="weight">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th>
        <td mat-cell *matCellDef="let element"> {{element.cpuName}} </td>
    </ng-container>


    <ng-container matColumnDef="symbol">
        <th mat-header-cell *matHeaderCellDef mat-sort-header> Symbol </th>
        <td mat-cell *matCellDef="let element"> {{element.hddName}} </td>
    </ng-container>

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

.ts file

import { Component, OnInit, ViewChild } from '@angular/core';
import {MatPaginator} from '@angular/material/paginator';
import {MatTableDataSource} from '@angular/material/table';
import {MatSort} from '@angular/material/sort';
import { AddAssetService } from '../shared/add-asset.service';
export interface Element {
  assetId: any;
  assetName: any;
  cpuName: any;
  hddName:  any;
}

@Component({
  selector: 'app-material-two',
  templateUrl: './material-two.component.html',
  styleUrls: ['./material-two.component.css']
})
export class MaterialTwoComponent implements OnInit {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource:any;
  @ViewChild(MatSort, { static: false }) sort!: MatSort;
  constructor(private service:AddAssetService) { }

  ngOnInit(): void {

   this.assetGrid();
   this.ngAfterViewInit()
    console.log(this.dataSource);
  }
  assetGrid() {
    this.service.GetAssets().subscribe(user=>{
      this.dataSource = new MatTableDataSource<Element>(user);
       console.log("this.listData",this.dataSource);
       console.log("this.user",user)
    });
  }
    ngAfterViewInit() {
      this.dataSource.sort = this.sort;
  }

}

Getting the error:

core.js:6210 ERROR TypeError: Cannot set property 'sort' of undefined.

Upvotes: 0

Views: 2647

Answers (1)

Yong Shun
Yong Shun

Reputation: 51440

You can avoid this error

core.js:6210 ERROR TypeError: Cannot set property 'sort' of undefined.

by checking this.dataSource must not be undefined nor null first before assigning as below:

.component.ts

if (this.dataSource) {
  this.dataSource.sort = this.sort;
}

Concerns

Concern 1: Missing implements AfterViewInit

You must implement AfterViewInit on your component. Otherwise, ngAfterViewInit will not be executed. And remove calling this.ngAfterViewInit method from ngOnInit method.

.component.ts

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

export class MaterialTwoComponent implements OnInit, AfterViewInit {
  ngOnInit(): void {
    this.assetGrid();
    console.log(this.dataSource);
  }

  ...
}

Concern 2: matColumnDef must be exact with property name

matColumnDef must be the same as the data's property name. If not, the sorting will not works. Hence, you also need to update displayedColumns for the properties.

.component.html

<ng-container matColumnDef="assetId">
  ...
</ng-container>

<ng-container matColumnDef="assetName">
  ...
</ng-container>

<ng-container matColumnDef="cpuName">
  ...
</ng-container>

<ng-container matColumnDef="hddName">
  ...
</ng-container>

.component.ts

displayedColumns: string[] = ['assetId', 'assetName', 'cpuName', 'hddName'];

Sample Solution on StackBlitz


References

Angular Material Table Sorting

Upvotes: 1

Related Questions