Reputation: 3949
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
Upvotes: 4
Views: 18087
Reputation: 129
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.
Upvotes: 1
Reputation: 680
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;
}
Upvotes: 4