0

here is the table.component.ts file. I want to sort the table like in this example of angular: https://material.angular.io/components/sort/overview but in this case, it didn't sort anything. I don't know what the problem is.

First I imported in the child.module.ts the modules:

import { MatTableModule } from '@angular/material/table';
import { MatSortModule } from "@angular/material/sort";

Import the module:

    import: [
        MatTableModule,
        MatSortModule
]

here is the table.component.ts file:

 import { MatPaginator } from '@angular/material/paginator';
    import { MatSort } from '@angular/material/sort';
    import { MatTableDataSource } from '@angular/material/table';

    export interface PeriodicElement {
      timestamp: string;  
      key: string;
      value: number;
    
    }
export class TableComponent implements OnInit {

  
  loadingData = false;


  displayedColumns: string[] = ['data', 'key', 'value'];

  ELEMENT_DATA: PeriodicElement[] = new Array<PeriodicElement>();

  dataSource = new MatTableDataSource<PeriodicElement>(this.ELEMENT_DATA);

  datastructure: Array<dataschema> = [];

  sortedData: PeriodicElement[];


   //sort data 
  @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator;  
  @ViewChild(MatSort, { static: false }) sort: MatSort; 

  constructor(private Service: Service) {
this.sortedData = this.ELEMENT_DATA.slice() }

  exportTable() {
    TableUtil.exportTableToExcel("ExampleTable");
  }


  ngAfterViewInit(): void {
    this.dataSource.sort = this.sort;
    
}


  ngOnInit(): void {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;

    
    this.loadingData = true;

    this.Service.getContent().then(results => {

      this.datastructure = results;
     
     
      this.loadingData = false;
      
      
      for (let i = 0; i < this.datastructure.length; i++) {

        

        cut off code 
      }

    })

  }

sortData(sort: Sort) {
const data = this.ELEMENT_DATA.slice();
if (!sort.active || sort.direction === '') {
  this.sortedData = data;
  return;
}
this.sortedData = data.sort((a, b) => {
  const isAsc = sort.direction === 'asc';
  switch (sort.active) {
    case 'data': return compare(a.data, b.data, isAsc);
    case 'key': return compare(a.key, b.key, isAsc);
    case 'value': return compare(a.value, b.value, isAsc);
    default: return 0;


   }
    })

    
  }
      
    
}
function compare(a: number | string, b: number | string, isAsc: boolean) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

The html view:

    <div *ngIf="!loadingData" class="mat-elevation-z8">
       <table id="ExampleTable" mat-table matTableExporter [dataSource]="dataSource"  matSort (matSortChange)="sortData($event)" class="mat-elevation-z8">
<!--Example Column/Row-->



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

    </table>
    </div>
teddy1995
  • 61
  • 1
  • 7
  • 1
    Have you visited this? https://stackblitz.com/angular/ekbxboqeaba?file=src%2Fapp%2Fsort-overview-example.ts – YOusaFZai Sep 07 '20 at 11:16
  • you are getting the mat through viewchild but i cannot see any subscription or change detection on sort(so you can sort the array). Simply put the event (matSortChange)="sortData($event)" in table tag and write the logic for sorting in sortData function. – YOusaFZai Sep 07 '20 at 11:21
  • could you give me a code example, how the sortData Function could looks like in my case? – teddy1995 Sep 07 '20 at 11:40
  • 1
    yes. just click on the link above. – YOusaFZai Sep 07 '20 at 11:45
  • @YOusaFZai I updated the code with your suggestion, but maybe I edited the code wrong, it still not sort the data. could you please check if I implemented the code right? – teddy1995 Sep 07 '20 at 12:08
  • @YOusaFZai the code works if i set 'this.loadingData = false' before I retrieve the data from the service 'this.Service.getContent().then(results => {--'. But I don't understand the reason? If I set it to false, the table doesnt load any data. – teddy1995 Sep 07 '20 at 12:15
  • 1
    use sortedData as datasource in html – YOusaFZai Sep 07 '20 at 12:17
  • that is because the default value needed for a variable otherwise it will be undefined. – YOusaFZai Sep 07 '20 at 12:21
  • but when I set 'this.loadingData = true' sorting didn't work anymore. But the table is filled up with the data when page is loading. – teddy1995 Sep 07 '20 at 13:13
  • 1
    because the condition says *ngIf="!loadingData" or to loadingData = false – YOusaFZai Sep 07 '20 at 13:16
  • do you know I can fix it? – teddy1995 Sep 07 '20 at 13:46

2 Answers2

1

The problem is in the ViewChild. There is a typo. You are trying to grab MatSort. But it is matSort.

TS

@ViewChild(MatSort, { static: false }) sort: MatSort; 

HTML

<table id="ExampleTable" mat-table matTableExporter [dataSource]="dataSource"  matSort class="mat-elevation-z8">

Instead, try the code below,

TS

@ViewChild('exampleTableTableSort, { static: false }) sort: MatSort; 

HTML

<table #exampleTableTableSort='matSort' id="ExampleTable" mat-table matTableExporter [dataSource]="dataSource"  matSort class="mat-elevation-z8">
Abdun Nahid
  • 311
  • 4
  • 9
1

if you has the data under a *ngIf Angular can not reach it so I suggest give to Angular a breath (Enclosed the dataSource.paginator and this.dataSource.sort in a setTimeout

this.Service.getContent().then(results => {
    this.datastructure = results;
    this.loadingData = false;
    setTimeout(()=>{
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
    })
})

Anyway, material Angular sort the data for you, I can not understand your functions sort and your variable sortedData. you only need equal datasource.data to the response of your API

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • Many thanks to Eliseo!!! You made my day. Yeah that was the problem. setTimeout() was the right attempt. But why Angular didn't reach it, if I set it under *ngIf? – teddy1995 Sep 08 '20 at 07:18
  • 1
    @teddy1995. You can see in this way: You has *ngIf="false", so there're nothing in DOM. You "write" *ngIf="true" and others instructions, but until all the instrucction not finished, the DOM not refresh, so in the others instruction can not make reference to some that not exist. Using setTimeout, you "write" *ngIf="true" and say Angular: "**after** refresh the DOM, make the instruction under the setTimeout" – Eliseo Sep 08 '20 at 07:40