skip to Main Content

TS :

ngOnChanges() { 
    this.dataSource = new MatTableDataSource<Data>(this.someData); //work order data
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
}

HTML :

<table mat-table [dataSource]="dataSource" matSort>

<!-- column which does not sort is  : -->
            <ng-container matColumnDef="Name">
                <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
                <td data-th="Customer Name" mat-cell *matCellDef="let element"> {{element.party.name}} </td>
            </ng-container>

I have tried all the way search in Google along with this site also still no answer, Have tried all the answers related to : mat-sort-header / mat-sort not working on a particular column

but no solution please help.

4

Answers


  1. There are actually 2 issues here.

    1. you are not initializing the matSort correctly.
      The code you put in the ngOnChanges should be in the ngAfterViewInit (see [official doc](https://material.angular.io/components/table/overview#sorting with working code)

    2. you have to help material to understand how to sort your column. Material assumes the column name is the same as your object property. So here, Material is trying to sort based on element.Name, which does not exists. You have to define sortingDataAccessor, telling something like "if you want to sort Name column, have a look to element.party.name instead".

    Login or Signup to reply.
  2. Update sorry, I just check and not work, please remove upvote

    use mat-sort-header='party.name'

    <ng-container matColumnDef="Name">
           <th mat-header-cell *matHeaderCellDef 
                            mat-sort-header="party.name"> Name </th>
           <td data-th="Customer Name" mat-cell *matCellDef="let element">
               {{element.party.name}}
           </td>
    </ng-container>
    

    By defect short-header gets the value of the columnName but you want to sort by party.name

    The best bet is add a new property "name" to the elements of your array.

    Update 2 About your comment

    If you received from the API an array of object like

    {party:{name:'',prop1:`''},prop2:''}
    

    You can use pipe map in the way

     return httpClient.get(your url).pipe(map(res:any[])=>{
        //return your array transform
        return res.map(x=>({
             name:x.party.name,
             prop1:x.party.prop1,
             prop2:x.prop2
        })
    }))
    

    So your elements are in the way

    {name:'',prop1:'',prop2:''}
    

    And use a mat-table in the "normal way"

    Login or Signup to reply.
  3. I’ve also faced the same issue.

    matColumnDef and the property name should be same.

    in HTML:

      <ng-container matColumnDef="party.name">
                    <th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
                    <td data-th="Customer Name" mat-cell *matCellDef="let element"> {{element.party.name}} </td>
                </ng-container>
    

    in TS:

    displayedColumns = ['party.name']; //change the column name in ts as well.
    

    Also, where you are assigning the datasource:

          this.datasource.sortingDataAccessor = (item, property) => {
                  switch (property) {
                    case 'party.name': return item.party.name;
    case 'party.age': return item.party.age //if you have other properties as well.
                    default: return item[property];
                  }
                };
    
    
     this.datasource.sort = this.sort;
    
    Login or Signup to reply.
  4. We can not use an object to order because how is defined the function sortingDataAccessor in the MatTableDataSource (see the github).

    But we can create a class that override this function

    export class ObjectMatTableDataSource<T> extends MatTableDataSource<T>{
      override sortingDataAccessor= (
        data: T,
        sortHeaderId: string,
      ): string | number => {
        const part=sortHeaderId.split('.')
        let value = (data as unknown as Record<string, any>)[part[0]];
        for (let i=1;i<part.length;i++)
          value = value[part[i]];
      
        if (!isNaN(parseFloat(value as any)) && !isNaN(Number(value))) {
          const numberValue = Number(value);
          const MAX_SAFE_INTEGER = 9007199254740991;
      
          return numberValue < MAX_SAFE_INTEGER ? numberValue : value;
        }
      
        return value;
      };
    }
    

    Now, we can use

    dataSource = new ObjectMatTableDataSource(ELEMENT_DATA);
    

    And we can use mat-sort-header a name like: "party.name"

    See an example in stackblitz

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search