10
votes

I have a mat-table in which I have several sort-able column. I can set the initial sort of the table with the matSortActive and matSortDirection properties on the mat-table. Using this, the arrow indicating the sorting direction in the headers is displayed correctly.

Now when I am trying to reset the sorting to the initial state by using a button the sorting is correctly reset. However, the arrow in the header is not updated. So the arrow is still displayed in the header of the previous sorted column. How can I get the arrow to be displayed in the initial state again?

My table and reset button in HTML:

<button mat-button mat-raised-button (click)="removeFilters()" class="reset-button">Verwijder filters</button>

<mat-table #table [dataSource]="dataSource" matSort (matSortChange)="sortData($event)" matSortActive="comp_name_sort" matSortDirection="asc">
  <ng-container matColumnDef="assetName">
    <mat-header-cell *matHeaderCellDef mat-sort-header="comp_name_sort">Systeem</mat-header-cell>
    <mat-cell *matCellDef="let asset"> {{asset.comp_name}} </mat-cell>
  </ng-container>

  <ng-container matColumnDef="softwareName">
    <mat-header-cell *matHeaderCellDef mat-sort-header="soft_name_sort">Software</mat-header-cell>
    <mat-cell *matCellDef="let asset"> {{asset.soft_name}} </mat-cell>
  </ng-container>

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

My ts file:

  export class AssetsComponent implements OnInit {

  @ViewChild(MatSort) sort: MatSort;

  assets: Asset[];
  displayedColumns = ['assetName', 'softwareName',];
  dataSource = new MatTableDataSource<Asset>(this.assets);

  constructor( private assetsService: AssetsService) { }

  ngOnInit() {
    this.getAssets();
  }

  getAssets(): void {
    this.assetsService.getAssets().subscribe(
      assets => {
        this.assets = assets;
        this.dataSource = new MatTableDataSource<Asset>(this.assets);
      }
    );
  }

  sortData(event): void {
    this.assetsQueryService.setSorts(event);
    this.getAssets();
  }

  removeFilters() {
    this.sort.active = 'comp_name_sort';
    this.sort.direction = 'asc';
    this.sort.sortChange.emit({active: 'comp_name_sort', direction: 'asc'});
    this.assetsQueryService.removeFilters();
    this.getAssets();
  }

}

The sorting column and direction are passed to the assetsService because sorting is done in the backend (because of server-side pagination, not shown here). This is all working well, also with the reset button. The only problem is the displayed arrow. So in summary, how do I reset the sorting arrow that is displayed in the table to it's initial state programmatically?

Any help would be appreciated.

5
im having the same issuerj.learn

5 Answers

10
votes

For anyone else looking for an answer for this particular problem. As ericbea pointed out in the comments, Angular is aware of this problem and an issue is still open on github about this: https://github.com/angular/components/issues/10242. The only workaround that I found that worked for me is also listed there. It's something like this:

this.sort.sort({ id: null, start: 'desc', disableClear: false });
this.sort.sort({ id: 'comp_name_sort', start: 'asc', disableClear: false });
(this.sort.sortables.get('comp_name_sort') as MatSortHeader)._setAnimationTransitionState({ toState: 'active' });

The first line is used to clear the sort in case the column you want the sort to is currently the active column.

6
votes

I don't know if you still need help with this, but I encountered the same issue and here's my solution. After you reset the active and direction for your sort, add the following line:

this.sort._stateChanges.next();

This should remove the sort arrow from your UI. Hopefully this helps!

2
votes

I know this question is old but in case anyone else comes looking...

To set the arrow in the sort header, this worked for me:

import { MatSort } from '@angular/material/sort'

Then, in the class:

@ViewChild(MatSort) myMatSort:MatSort

Finally, you can do this:

myMatSort.sort({
  id: 'column-name', // The column name specified for matColumnDef attribute
  start: 'asc', // Can be 'asc', 'desc' or null,
  disableClear: false
})

See the sort method and MatSortable interface here.

1
votes

Maybe you should try ChangeDetectorRef, it could just be that the view is not being refreshed properly after the change.

This is usually useful when the view needs a refresh after a change that doesn't require user interaction with the view.

Just inject the change detector in your component like this:

constructor( private changeDetector: ChangeDetectorRef  ) { }

and then use it just after reset the sort state programatically to force the view to detect changes like this:

this.changeDetector.detectChanges();

Hope it helps ;)

1
votes

Using Angular 6+,

if you want sort-reset DESCENDING:

defaultSortStart: 'desc', defaultSortDirection: 'asc'

if you want sort-reset ASCENDING:

defaultSortStart: 'asc', defaultSortDirection: 'desc'



    // Reset sort: FIELD_NAME/DESC.
    let defaultSortStart: ('asc' | 'desc') = 'desc';
    let defaultSortDirection: ('asc' | 'desc') = 'asc';
    let defaultSortField = this.matListColumnName.FIELD_NAME;
    this.sort.direction = defaultSortDirection;
    this.sort.sort({
        id: defaultSortField,
        start: defaultSortStart,
        disableClear: true
    });

    // Reset sort: FIELD_NAME/ASC.
    let defaultSortStart: ('asc' | 'desc') = 'asc';
    let defaultSortDirection: ('asc' | 'desc') = 'desc';
    let defaultSortField = this.matListColumnName.FIELD_NAME;
    this.sort.direction = defaultSortDirection;
    this.sort.sort({
        id: defaultSortField,
        start: defaultSortStart,
        disableClear: true
    });