Home > front end >  How to sort Angular material table based on button click
How to sort Angular material table based on button click

Time:12-11

I want to sort mat table when I click buttons.

Mat table has sort functionalities when you click the column name it sorts the table based on the column.

I want to sort the table based on price when I click the button "low to high" Here is my code: shopping component `

import { AfterViewInit, Component, OnInit, ViewChild, Input, EventEmitter } from '@angular/core';
import {MatTableDataSource} from '@angular/material/table';
import { HttpClient } from '@angular/common/http';
import { IItem } from '../items';
import {MatSort, Sort} from '@angular/material/sort';
import { LoginComponent } from '../login/login.component';
import { SharedService } from '../shared.service';
import { MatDialog } from '@angular/material/dialog';
import { AddItemComponent } from '../add-item/add-item.component';


@Component({
  selector: 'app-shopping',
  templateUrl: './shopping.component.html',
  styleUrls: ['./shopping.component.scss']
})
export class ShoppingComponent implements AfterViewInit, OnInit{

  constructor(private http: HttpClient, private sharedService: SharedService,
    private dialog: MatDialog) {}

  @Input() loginSuccess!: EventEmitter<string>;
  @ViewChild(MatSort) sort!: MatSort;
  @ViewChild(LoginComponent) loginComponent!: LoginComponent;
  @ViewChild('empTbSort') empTbSort = new MatSort();

  private url = 'assets/items.json';
  username!: any;
  data!: any;
  displayedColumns: string[] = ['id', 'name', 'quantity', 'price', 'count', 'add'];
  dataSource = new MatTableDataSource<IItem>(this.data);
  labelCount = 0
  
  ngOnInit() {
    this.http.get(this.url)
    .subscribe(response => {
      this.data = response;
      this.dataSource = new MatTableDataSource(this.data);
    })

    this.username = this.sharedService.username
  } 

  ngAfterViewInit() {
    this.priceHighToLow();
  }

  openCart() {}

  updateItems(row: any) {
    for(let i = 0; i < this.data.length;   i) {
      if(this.data[i]["add"] == row.add) {
        this.data[i]["count"] -= 1;
        this.labelCount  = 1
      }
    }
    this.dialog.open(AddItemComponent, {width: "20%"})
  }

  priceHighToLow() {}
}

shopping html

<mat-toolbar color="primary">
    <button mat-icon-button>
        <mat-icon>polymer</mat-icon>
    </button>
    <span>Welcome <b>{{username}}</b></span>
    <span ></span>
    <button mat-icon-button (click)="openCart()">
        <mat-icon [matBadge]="labelCount" matBadgeColor="warn">add_shopping_cart</mat-icon>
    </button>
</mat-toolbar>
<div >
    <table mat-table [dataSource]="dataSource" matSort >
        <ng-container matColumnDef="id">
            <th mat-header-cell *matHeaderCellDef>ID</th>
            <td mat-cell *matCellDef="let item">{{ item.id }}</td>
        </ng-container>
        <ng-container matColumnDef="name">
            <th mat-header-cell *matHeaderCellDef>Product Name</th>
            <td mat-cell *matCellDef="let item">{{ item.name }}</td>
        </ng-container>
        <ng-container matColumnDef="quantity">
            <th mat-header-cell *matHeaderCellDef>Quantity</th>
            <td mat-cell *matCellDef="let item">{{ item.quantity }}</td>
        </ng-container>
        <ng-container matColumnDef="price">
            <th mat-header-cell *matHeaderCellDef>Price</th>
            <td mat-cell *matCellDef="let item">{{ item.price | currency }}</td>
        </ng-container>
        <ng-container matColumnDef="count">
            <th mat-header-cell *matHeaderCellDef >Count</th>
            <td mat-cell *matCellDef="let item">{{ item.count }}</td>
        </ng-container>
        <ng-container matColumnDef="add">
            <th mat-header-cell *matHeaderCellDef >Action</th>
            <td mat-cell *matCellDef="let item">
                <button mat-raised-button color="warn" (click)="updateItems(item)">Add item</button>
            </td>
        </ng-container>
        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>
</div>
<table> 
    <h2>Price</h2>
    <button (click)="priceHighToLow()"> High to low</button><br>
    <!-- <button (click)="priceLowToHigh()"> High to low</button>
    <h2>Quantity</h2>
    <button (click)="quantityHighToLow()"> High to low</button><br>
    <button (click)="quantityLowToHigh()"> High to low</button> -->
</table>

` Once I click the High to low button I want the table to be sorted based on the price. I want to sort the price from low to high as well.

I need a way to custom sort mat table based on button clicks.

CodePudding user response:

Component.html

<button mat-raised-button (click)="sortDataSource('price', 'asc')">ASC</button>
<button mat-raised-button
          (click)="sortDataSource('price', 'desc')">DESC</button>
<table mat-table [dataSource]="dataSource" matSort
                       #empTbSort="matSort" >
            <ng-container matColumnDef="id">
                <th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
                <td mat-cell *matCellDef="let item">{{ item.id }}</td>
            </ng-container>
            <ng-container matColumnDef="name">
                <th mat-header-cell *matHeaderCellDef mat-sort-header>Product Name</th>
                <td mat-cell *matCellDef="let item">{{ item.name }}</td>
            </ng-container>
            <ng-container matColumnDef="quantity">
                <th mat-header-cell *matHeaderCellDef mat-sort-header>Quantity</th>
                <td mat-cell *matCellDef="let item">{{ item.quantity }}</td>
            </ng-container>
            <ng-container matColumnDef="price">
                <th mat-header-cell *matHeaderCellDef mat-sort-header>Price</th>
                <td mat-cell *matCellDef="let item">{{ item.price | currency }}</td>
            </ng-container>
            <ng-container matColumnDef="count">
                <th mat-header-cell *matHeaderCellDef mat-sort-header>Count</th>
                <td mat-cell *matCellDef="let item">{{ item.count }}</td>
            </ng-container>
            <ng-container matColumnDef="add">
                <th mat-header-cell *matHeaderCellDef >Action</th>
                <td mat-cell *matCellDef="let item">
                    <button mat-raised-button color="warn" (click)="updateItems(item)">Add item</button>
                </td>
            </ng-container>
            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
            <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>

Component.ts

@ViewChild('empTbSort') empTbSort = new MatSort();

ngAfterViewInit() {

this.dataSource.sort = this.empTbSort;
}

ngOnInit() {
    this.http.get(this.url)
    .subscribe(response => {
      this.data = response;
      this.dataSource = new MatTableDataSource(this.data);
      this.dataSource.sort = this.empTbSort;
    })

    this.username = this.sharedService.username
  }

Description of changes as below for sort column using table header:

  • add code as mention to table tag - matSort #empTbSort="matSort"
  • add mat-sort-header to mat-header-cell
  • changes to component using ref variable of type MatSort() using this reference give control of sorting.

Approach of button click

 sortDataSource(id: string, start: string) {
    this.dataSource.data.sort((a, b) => {
      return start === 'asc'
        ? a[id] - b[id]
        : start === 'desc'
        ? b[id] - a[id]
        : a[id] - b[id];
    });
    this.dataSource._updateChangeSubscription();
  }

Description Add two button for manually apply sorting of column using above method calling with FieldName & Method of sorting.

Find finalize Working Demo here

  • Related