Reputation: 10704
I have a simple design I was working with. In the module file, I have added the imports: MatSortModule and MatTableModule. When looking at the component I created, it was simple:
<table mat-table [dataSource]="dataSource"
matSort>
<ng-container matColumnDef="interface"> <!-- vvv This area may have some importance vvv -->
<th mat-header-cell *matHeaderCellDef mat-sort-header id="interface">Interface</th>
<td mat-cell *matCellDef="let element"><span>{{element.interface}}</span></td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
and then the TS file:
class GridComponent {
dataSource = null
displayedColumns = ["interface"];
@ViewChild(MatSort, {static: true}) sort: MatSort;
@Input() set data(val: any[]) {
this._data = val;
getInfo();
}
get data () { return this._data; }
private _data: any[];
ngOnInit() {
this.dataSource = new MatTableDataSource([])
this.dataSource.sort = this.sort
}
getInfo() {
this._service.get(this._data).subscribe( data => {
/// For the ease of understanding. assume data is defined below.
const arr = [{"interface":"foo"},{"interface":"bar"}]
this.dataSource = new MatTableDataSource(arr)
this.dataSource.sort = this.sort
});
}
}
The grid renders all the rows, and the toggle button shows etc. When I toggle it though the information does not reorder.
Is there something I am missing? I saw some samples which said I needed to do: this.dataSource.sort = this.sort
but I dont really understand that purpose and if it is somehow interfering with the sorting mechanism.
When looking at the coding sample at the bottom of: https://material.angular.io/components/sort/overview , I was confused as I didnt see any sort of ID being used, or assigned to the mat-sort-header property, but in some of the API it was stating to do that
I would love some clarification.
Edit: I am looking for a dynamic answer, one which allows me to easily change the data in the datasource. Right now, beyond the scope of the issue, I have an input which allows me to change the array of data associated with the datasource, so i am working towards keeping it encapsulated in such a way that I can handle setting properties outside of Initializers of components.
Upvotes: 4
Views: 2600
Reputation: 10704
There is a built in change for matSort you can catch to handle sorting. This bypasses the: this.dataSource.sort = this.sort;
lines. So you can trim all of that code out.
<table mat-table
[dataSource]="dataSource"
matSort
(matSortChange)="sortData($event)"></table>
and then in the code you can put:
sortData(sort: Sort){
// Sort sorts the current list, but it wasnt updating it unless i reassigned.
this.dataSource.data = this.dataSource.data.sort((a, b) => {
const isAsc = sort.direction === 'asc';
return this._compare(a[sort.active], b[sort.active], isAsc);
});
}
private _compare(a: number | string, b: number | string, isAsc: boolean) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
The other answer was not working at all for me, but now, everything flows well.
Since there are 3 states for sort.direction
, 'asc', 'desc', and '', so for the empty string, I would set datasource equal to the original list order.
Here is the modified Component, with commented out areas which can now be deleted
class GridComponent {
/// Initialize the datasource we will be augmenting its inner data.
dataSource: MatTableDataSource<any> = new MatTableDataSource();
displayedColumns = ["interface"];
//@ViewChild(MatSort, {static: true}) sort: MatSort;
@Input() set data(val: any[]) {
this._data = val;
getInfo();
}
get data () { return this._data; }
private _data: any[];
ngOnInit() {
//this.dataSource = new MatTableDataSource([])
//this.dataSource.sort = this.sort
}
getInfo() {
this._service.get(this._data).subscribe( data => {
/// For the ease of understanding. assume data is defined below.
const arr = [{"interface":"foo"},{"interface":"bar"}]
/// Updated the below line to just update data.
this.dataSource.data = arr;
//this.dataSource.sort = this.sort
});
}
sortData(sort: Sort){
// Sort sorts the current list, but it wasnt updating it unless i reassigned.
this.dataSource.data = this.dataSource.data.sort((a, b) => {
const isAsc = sort.direction === 'asc';
return this._compare(a[sort.active], b[sort.active], isAsc);
});
}
private _compare(a: number | string, b: number | string, isAsc: boolean) {
return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}
}
Upvotes: 3
Reputation: 147
Yes, in order for the sort to work for the mat data table you will need to use this.dataSource.sort = this.sort within ngOnInit()
ngOnInit() {
this.dataSource = new MatTableDataSource<FooModel>(foobar);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
Notice how the datasource can be updated from your service subscription:
this.fooService.getFoobar(this.isFoo).subscribe((foobar: Foo[]) => {
if (foobars != null) {
this.dataSource = new MatTableDataSource<Foo>(foobar);
this.dataSource.sort = this.sort;
Upvotes: 0