4

I have a Angular 8 application that uses Angular Material. I want to sort the colums in a angular 8 application, using Angular Material

googled, courses

So this is how the file looks where sorting is implemented ts file looks like:

import { ActivatedRoute } from '@angular/router';
import { Component, OnInit, ViewChild, Inject, Input } from '@angular/core';
import { QRCodeDefinitionInfoApi, EcheqSubmissionInfoApi, QRCodeMedicalService } from 'src/app/generated';
import { MatPaginator, MatSort } from '@angular/material';
import { MAT_DIALOG_DATA, MatTableDataSource } from '@angular/material';
import { PublishState } from 'src/app/qrcode-definition/list/list-item';
import { I18n } from '@ngx-translate/i18n-polyfill';

class SortedSubmissions {
  [key: string]: {
    submissions: EcheqSubmissionInfoApi[];
  };
}


@Component({
  selector: 'app-echeq-qrcode',
  templateUrl: './echeq-qrcode.component.html',
  styleUrls: ['./echeq-qrcode.component.scss']
})
export class EcheqQrcodeComponent implements OnInit {

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  readonly ScanFequencyType = QRCodeDefinitionInfoApi.ScanFrequencyTypeEnum;
  readonly PublishState = QRCodeDefinitionInfoApi.PublishStateEnum;
  readonly ActionType = QRCodeDefinitionInfoApi.ActionTypeEnum;
  source: QRCodeDefinitionInfoApi[];
  datasource: MatTableDataSource<QRCodeDefinitionInfoApi>;

  patientId: string;
  submissions: EcheqSubmissionInfoApi[];


  @Inject(MAT_DIALOG_DATA) public data: any;
  @Input() item;
  sortedSubmissions: SortedSubmissions;

  public readonly displayedColumns = [

    'title',
    'lastScannedOn',
    'totalScanned',
    'publishState',
  ];

  constructor(private i18n: I18n, route: ActivatedRoute,  private qrCodeDefintion: QRCodeMedicalService ) {

    this.patientId = route.snapshot.paramMap.get('patientId');
    const data = route.snapshot.data;
    this.source = data.definition;

    }

  ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
    (this.source = subs);
    });

    if (this.data && this.data.definition) {
      this.source = this.data.definition;
    }
    // this.datasource.paginator = this.paginator;
    this.datasource.sort = this.sort;
  }

  translatePublished(publishState: PublishState): string {
    switch (publishState) {
      case PublishState.DRAFT:
        return this.i18n('Not published');
      case PublishState.PUBLISHED:
        return this.i18n('Published');
    }
    switch ( String(publishState) ) {
      case 'Draft':
          return this.i18n('Not published');
      case 'Published':
        return this.i18n('Published');
      default:
        return this.i18n( 'Not Published' );
    }
  }
}

and this is the html of the page:

<div class="header">
    <h1 class="heading page-heading patient-list-heading">Scanned QR Codes </h1>
  <div class="qrcode-menu">
  </div>
</div>

  <div class="mat-elevation-z8">
    <table
      mat-table
      class="full-width-table"
      [dataSource]="source"
      matSort
      aria-label="Elements"
    >
    <ng-container matColumnDef="title">
      <th mat-header-cell *matHeaderCellDef mat-sort-header i18n>Name</th>
      <td mat-cell *matCellDef="let row">{{ row.title }}</td>
    </ng-container>


    <ng-container matColumnDef="lastScannedOn">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>lastScannedOn</th>
      <td mat-cell *matCellDef="let row">{{ row.lastScannedOn | date: 'dd MMM yy' }}</td>
    </ng-container>

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

    <ng-container matColumnDef="publishState">
      <th mat-header-cell *matHeaderCellDef mat-sort-header="wasPublished" i18n>publishState</th>
      <td mat-cell *matCellDef="let row">{{ translatePublished(row.publishState) }}</td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
  </table>
  <mat-paginator [pageSizeOptions]="[25, 50, 100, 250]"></mat-paginator>
  </div>




but now I get this error:

ERROR TypeError: Cannot set property 'sort' of undefined
    at EcheqQrcodeComponent.push../src/app/components/echeq-qrcode/echeq-qrcode.component.ts.EcheqQrcodeComponent.ngOnInit (echeq-qrcode.component.ts:66)
    at checkAndUpdateDirectiveInline (core.js:18620)
    at checkAndUpdateNodeInline (core.js:19884)
    at checkAndUpdateNode (core.js:19846)
    at debugCheckAndUpdateNode (core.js:20480)
    at debugCheckDirectivesFn (core.js:20440)
    at Object.eval [as updateDirectives] (EcheqQrcodeComponent_Host.ngfactory.js?

That sorting will work for every column.

Thank you

and if I do this:

 ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
    (this.source = subs);
    });

    if (this.data && this.data.definition) {
      this.source = this.data.definition;
    }
    // this.datasource.paginator = this.paginator;
    this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>();
    this.datasource.sort = this.sort;
  }

I dont get an error. But sorting doesnt work at all

My ngOnit looks now like this:

ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
    (this.source = subs);


    });

    if (this.data && this.data.definition) {
      this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);
      this.datasource.sort = this.sort;
      this.datasource.paginator = this.paginator;
      this.source = this.data.definition;
    }
    // this.datasource.paginator = this.paginator;



  }

But if I do this:

 <div class="mat-elevation-z8">
    <table
      mat-table
      class="full-width-table"
      [dataSource]="datasource"
      matSort
      aria-label="Elements"
    >

Then the data is not visible anymore.

Thank you. But if I do that. I get this error:

Yes, thank you. But now I get this error: this.source =

this.data.definition;

core.js:12584 ERROR TypeError: Cannot read property 'definition' of undefined
    at SafeSubscriber._next (echeq-qrcode.component.ts:61)
    at SafeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:196)

This is how I have it now:

ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
      (this.source = subs);
        this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);
        this.datasource.sort = this.sort;
        this.datasource.paginator = this.paginator;
        this.source = this.data.definition;

      });
  }

And this is the html file:

<div class="header">
    <h1 class="heading page-heading patient-list-heading">Scanned QR Codes </h1>
  <div class="qrcode-menu">
  </div>
</div>

  <div class="mat-elevation-z8">
    <table
      mat-table
      class="full-width-table"
      [dataSource]="source"
      matSort
      aria-label="Elements"
    >
    <ng-container matColumnDef="title">
      <th mat-header-cell *matHeaderCellDef mat-sort-header i18n>Name</th>
      <td mat-cell *matCellDef="let row">{{ row.title }}</td>
    </ng-container>


    <ng-container matColumnDef="lastScannedOn">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>lastScannedOn</th>
      <td mat-cell *matCellDef="let row">{{ row.lastScannedOn | date: 'dd MMM yy' }}</td>
    </ng-container>

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

    <ng-container matColumnDef="publishState">
      <th mat-header-cell *matHeaderCellDef mat-sort-header="wasPublished" i18n>publishState</th>
      <td mat-cell *matCellDef="let row">{{ translatePublished(row.publishState) }}</td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
  </table>
  <mat-paginator [pageSizeOptions]="[25, 50, 100, 250]"></mat-paginator>
  </div>

I also tried this:

ngAfterViewInit () {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
      (this.source = subs);
    this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);
    setTimeout(() => {
      this.datasource.sort = this.sort;
      this.datasource.paginator = this.paginator;

    });
  });

Dont get any errors.But sorting doesnt work.

And if I do a console.log(this.datasource.sort) in the ngAfterViewInit(){}

then I see this:

MatSort {_disabled: false, _isInitialized: true, _pendingSubscribers: null, initialized: Observable, sortables: Map(4), …}
direction: (...)
disableClear: (...)
disabled: (...)
initialized: Observable {_isScalar: false, _subscribe: ƒ}
sortChange: EventEmitter
closed: false
hasError: false
isStopped: false
observers: (5) [Subscriber, Subscriber, Subscriber, Subscriber, Subscriber]
thrownError: null
__isAsync: false
_isScalar: false
__proto__: Subject
sortables: Map(4)
size: (...)
__proto__: Map
[[Entries]]: Array(4)
0: {"title" => MatSortHeader}
key: "title"
value: MatSortHeader {_disabled: false, _intl: MatSortHeaderIntl, _sort: MatSort, _columnDef: MatColumnDef, _showIndicatorHint: false, …}
1: {"lastScannedOn" => MatSortHeader}
2: {"totalScanned" => MatSortHeader}
3: {"wasPublished" => MatSortHeader}
length: 4
start: "asc"
_direction: ""
_disabled: false
_isInitialized: true
_pendingSubscribers: null
_stateChanges: Subject {_isScalar: false, observers: Array(4), closed: false, isStopped: false, hasError: false, …}
__proto__: class_1

So it seems that this is correctly. Isnt?

if I do this:

  sortData(sort: Sort)     {
       this.datasource.sort = this.sort;
       console.log(this.datasource.sort);
      }

I see this:

MatSort {_disabled: false, _isInitialized: true, _pendingSubscribers: null, initialized: Observable, sortables: Map(4), …}
active: "totalScanned"
direction: (...)
disableClear: (...)
disabled: (...)
initialized: Observable {_isScalar: false, _subscribe: ƒ}
sortChange: EventEmitter {_isScalar: false, observers: Array(6), closed: false, isStopped: false, hasError: false, …}
sortables: Map(4) {"title" => MatSortHeader, "lastScannedOn" => MatSortHeader, "totalScanned" => MatSortHeader, "wasPublished" => MatSortHeader}
start: "asc"
_direction: "desc"
_disabled: false
_isInitialized: true
_pendingSubscribers: null
_stateChanges: Subject {_isScalar: false, observers: Array(4), closed: false, isStopped: false, hasError: false, …}
__proto__: class_1
6
  • You never initialized datasource: MatTableDataSource<QRCodeDefinitionInfoApi>; so it is undefined. Commented Aug 8, 2019 at 13:05
  • It means you're applying sort on the field which is not defined Commented Aug 8, 2019 at 13:05
  • I updated the post. Commented Aug 8, 2019 at 13:06
  • You need to pass the data which should appear in the mat table in the constructor of new MatTableDataSource<QRCodeDefinitionInfoApi>(here); Commented Aug 8, 2019 at 13:08
  • Can you please post your ngOnInit method code after changes Commented Aug 9, 2019 at 7:44

2 Answers 2

4

You have to change this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>();

with this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);

And in HTML you have to pass [dataSource]="datasource" instead of [dataSource]="source"

Edit:

can you please change your ngOnInit method like give below


ngOnInit() {

    this.qrCodeDefintion.getQRCodeList(1, this.patientId).subscribe((subs) => {
    (this.source = subs);
      this.datasource = new MatTableDataSource<QRCodeDefinitionInfoApi>(this.source);
      this.datasource.sort = this.sort;
      this.datasource.paginator = this.paginator;
      this.source = this.data.definition;

    });
    // this.datasource.paginator = this.paginator;



  }

Sign up to request clarification or add additional context in comments.

10 Comments

I have added edit in given solution can you please try that
DO you have other suggestions?
Can somebody help me? Will be nice
you can try add (matSortChange)="sortData($event)" in HTML and in .ts file add this method sortData(sort: Sort) { this.dataSource.sort = this.sort; }
Thank you. I have done that. But nothing happens. I see the arrow but the sorting doesnt do anything. Also no errors
|
1

In your html file add the below code<table mat-table [dataSource]="listData" matSort (matSortChange)="sortData($event)" >

In ng container add below code <th mat-header-cell *matHeaderCellDef mat-sort-header >Display

In your .ts (typescript code) add the below function as it: sortData(sort: Sort) { this.listData.sort = this.sort; }

This should fix your sorting issue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.