Можно ли как-то отключить автосортировку в таблице Angular, когда пользователь изменяет значение в столбце? Bcs сразу после изменения данные сортируются, когда есть активная сортировка по этому столбцу. Если я установил dataSource.sort = null, сортировка отключена, но сортировка данных вернулась к сортировке по умолчанию. Я хочу отсортировать данные только по щелчку заголовка столбца.
Отключить автосортировку для угловой таблицы при изменении значения столбца
Ответы (2)
Вы можете попробовать следующий подход. Я не знаю, как вы обновляете свою таблицу. Я просто использовал простой пример, чтобы показать вам, как вы можете отключить существующую сортировку в 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>
Вы можете найти рабочую ссылку здесь:
https://stackblitz.com/edit/angular-di4rp1
В компоненте после обновления источника данных просто добавьте эти строки, чтобы удалить существующую сортировку
this.sort.sort(
{id:'',start:'asc',disableClear : false}
)
Я обнаружил, что после долгого часа борьбы с решением проблемы. Я переопределил метод сортировки по умолчанию, определив свой:
this.dataSource.sortData = (
dataArray: ServicePartnerCategory[],
sortObj: MatSort
) => this.sortTableData(dataArray, sortObj);
В sortTableData я помещаю if isSortingEnabled и либо возвращаю отсортированный массив, либо предыдущий отсортированный массив. Это решает проблему, заключающуюся в том, что dataSource.sortData выполняется каждый раз, когда данные были изменены (см. Документацию). Мне также нужно было опускать заглавные буквы и каждый раз ставить пустые значения в конце, независимо от сортировки.
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;
}
Затем в функции изменения я установил для isSortingEnabled значение false. Эта функция изменения вызывается в form.valueChanges
onChange: any = () => {
this.isSortingEnabled = false;
}
после нажатия на заголовок сортировки выполняется эта функция:
onSortData($event) {
this.isSortingEnabled = true;
}
просто остальные функции:
/**
* 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;
}