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.
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}
)
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With