Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable autosort for Angular table on column value change

Is it possible to somehow disable the autosort in Angular table, when user changes value in column? Bcs immediately after change, the data are sorted, when there is active sorting on that column. If I set the dataSource.sort = null the sorting is disabled, but data sort returned to default sort. I wanna to sort data only on the column header click.

like image 224
niio Avatar asked Mar 14 '26 18:03

niio


2 Answers

You can try below approach. I don't know how you are updating your table. I just used a simple example to show you how you can disable existing sorting in mat-table

.ts

import {Component, OnInit, ViewChild} from '@angular/core';
import {MatSort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  {position: 1, name: 'Hydrogen', weight: 100, symbol: 'H'},
  {position: 2, name: 'Helium', weight: 40, symbol: 'He'},
  {position: 3, name: 'Lithium', weight: 60, symbol: 'Li'},
  {position: 4, name: 'Beryllium', weight: 90, symbol: 'Be'},
  {position: 5, name: 'Boron', weight: 100, symbol: 'B'},
  {position: 6, name: 'Carbon', weight: 10, symbol: 'C'},
  {position: 7, name: 'Nitrogen', weight: 140, symbol: 'N'},
  {position: 8, name: 'Oxygen', weight: 150, symbol: 'O'},
  {position: 9, name: 'Fluorine', weight: 180, symbol: 'F'},
  {position: 10, name: 'Neon', weight: 20, symbol: 'Ne'},
];

/**
 * @title Table with sorting
 */
var i =11;
@Component({
  selector: 'table-sorting-example',
  styleUrls: ['table-sorting-example.css'],
  templateUrl: 'table-sorting-example.html',
})
export class TableSortingExample implements OnInit {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = new MatTableDataSource(ELEMENT_DATA);

  @ViewChild(MatSort, {static: true}) sort: MatSort;

  ngOnInit() {
    this.dataSource.sort = this.sort;
  }
  AddNewItem(){
    this.dataSource.data = [...this.dataSource.data,{position: i, name: 'Neon', weight: 20, symbol: 'Ne'}];    
    this.sort.sort(
      {id:'',start:'asc',disableClear : false}
    )
    i++
  }  
}

.html

<button (click)="AddNewItem()">Add New Item</button>
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">

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

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

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

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

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

You can find working link here:

https://stackblitz.com/edit/angular-di4rp1

In component after updating your datasource just add these lines to remove existing sorting

this.sort.sort(
      {id:'',start:'asc',disableClear : false}
    )
like image 143
Passionate Coder Avatar answered Mar 17 '26 11:03

Passionate Coder


I found myself after long hour fighting a solution. I overrided the defaulf sort method with mine defined:

    this.dataSource.sortData = (
        dataArray: ServicePartnerCategory[],
        sortObj: MatSort
      ) => this.sortTableData(dataArray, sortObj);

In sortTableData I put an if isSortingEnabled and I either return sorted array, or previous sorted array. This solves the problem, that dataSource.sortData is executed everyTime data has changed (see documentation). I also needed to omit capital letters and put empty values everytime at the end, no matter on sorting.

    sortTableData(
    dataArray: ServicePartnerCategory[],
    sortObj: MatSort
    ): ServicePartnerCategory[] {
    if (this.isSortingEnabled) {
      switch (sortObj.direction) {
        case 'asc':
          dataArray.sort((a, b) => this.getSortIndex(a, b, sortObj, 'asc'));
          break;
        case 'desc':
          dataArray.sort((a, b) => this.getSortIndex(a, b, sortObj, 'desc'));
          break;
        default:
          dataArray.sort(
            (a, b) =>
              this.dataSource.data.indexOf(a[sortObj.active]) -
              this.dataSource.data.indexOf(b[sortObj.active])
          );
          break;
      }
      this.lastSortArray = cloneDeep(dataArray);
    }

    return this.lastSortArray;
    }

Then in change function I set the isSortingEnabled to false. This change function is called on form.valueChanges

    onChange: any = () => {
    this.isSortingEnabled = false;
    }

after clicking on sort header, this function is executed:

    onSortData($event) {
    this.isSortingEnabled = true;
     }

just the rest of the functions:

    /**
    * Returns index wether the a should be sorted before or after b.
    * Capitals are omited
    * Empty value is always sorted to end of the list
    * @param a first object for compare
    * @param b second object to compare
    * @param sortObj name of the object property to sort by
    * @param sortDirection asc or desc
    */
    getSortIndex(
    a: ServicePartnerCategory,
    b: ServicePartnerCategory,
    sortObj: MatSort,
    sortDirection: string
    ): number {
    if (a[sortObj.active] === '' || a[sortObj.active] === null) return 1; //always move 
    //empty value to the end of the list
    if (sortDirection === 'asc')
      return this.getProperty(a, sortObj.active) >
        this.getProperty(b, sortObj.active)
        ? 1
        : -1;

    return this.getProperty(a, sortObj.active) <
      this.getProperty(b, sortObj.active)
      ? 1
      : -1;
  }
like image 25
niio Avatar answered Mar 17 '26 09:03

niio



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!