2
votes

Angular Material table utilizes a MatTableDataSource method called sortData() to sort the table's data source. (https://material.angular.io/components/table/api#MatTableDataSource). It is an arrow function:

sortData: ((data: T[], sort: MatSort) => T[])

I need to view the sorted data without actually changing the sort. For example,

this.dataSource.sortData = (sortData) => {
    console.log(sortData);
    return sortData;
};

The problem here is that I am overriding the native sort functionality. return sortData returns the original data, without any sorting. All I want to do is observe the sorted data without modifying it. Is it possible to do this?

4
Maybe use lodash, deep cloning to keep a separate copy of data.Zonaib

4 Answers

4
votes

You could overwrite sortData function:

this.dataSource.sortData = this.sortData;

...

sortData = function(data: any, sort: MatSort) {
  const active = sort.active;
  const direction = sort.direction;
  if (!active || direction == '') { return data; }

  const sorted = data.sort((a, b) => {
    let valueA = this.sortingDataAccessor(a, active);
    let valueB = this.sortingDataAccessor(b, active);

    // If both valueA and valueB exist (truthy), then compare the two. Otherwise, check if
    // one value exists while the other doesn't. In this case, existing value should come last.
    // This avoids inconsistent results when comparing values to undefined/null.
    // If neither value exists, return 0 (equal).
    let comparatorResult = 0;
    if (valueA != null && valueB != null) {
      // Check if one value is greater than the other; if equal, comparatorResult should remain 0.
      if (valueA > valueB) {
        comparatorResult = 1;
      } else if (valueA < valueB) {
        comparatorResult = -1;
      }
    } else if (valueA != null) {
      comparatorResult = 1;
    } else if (valueB != null) {
      comparatorResult = -1;
    }

    return comparatorResult * (direction == 'asc' ? 1 : -1);
  });

  console.log(sorted)
  return sorted;
}

As you can see, I barely changed the original function. Add removed types as per your needs.

p.s. overwriting some of the functions inside MatTableDataSource is a common practise:

May be overridden for a custom implementation of data ordering.

0
votes

You can do one thing that before sorting the data you can store actual data in another variable and use it.

0
votes

I hope I understood your question correctly.

So, you need to sort data without modifying it.

You should create a copy of your data and sort it. You can use a global variable or a property.

let sortedData;
this.dataSource.sortData = (sortData) => {
    this.sortedData = {...sortData};
    // Any kind of sorting
    console.log(sortedData);
    return sortData;
};
0
votes

Konnichiwa ebakunin,

I have the same issue about the overriding of the native element, and there is an easy way to get the sort data that it wouldn't change the native value of your data.

The first you have to manage to grasp the reference in the Array. All we have to do, make a deep clone. JSON methods are the most compatible to apply this situation without another method called, and there is not any modified with the native-angular method.

cloneDeep (Data:any){
  return JSON.parse(JSON.stringify(Data));
}

After that, create the method in dataSource observes the data as you want. As an alternative, you want to customize the special sortData then follow it. Instead of modified directly, return the method called and you will get the easier use and flexible like you don't want to put MatSort in args, just rid it off.

constructor(){
  //add the new method of the dataSource.
  this.sortedData.observeSortData = (data : T[],sort: MatSort) : T[] =>{
    let clone_data = this.cloneDeep(data);
    console.log(clone_data.sort((a,b)=> a - b)); // what order you want, place your fomula in your call back
    return this.sortData(data,sort);
  }
}