components: Cannot create md-table with sort
Bug, feature request, or proposal:
Bug
What is the expected behavior?
I would like to create a dataTable with sorting feature in columns as in example https://material.angular.io/components/table/overview
What is the current behavior?
ERROR TypeError: Cannot read property ‘mdSortChange’ of undefined
What are the steps to reproduce?
Bellow is my code
incidents-results.component.html
<!-- In order to Display the first two lines that follow -->
<div class="example-container mat-elevation-z8">
<md-table #table [dataSource]="dataSource" mdSort>
<ng-container cdkColumnDef="protocolNo">
<md-header-cell *cdkHeaderCellDef md-sort-header> Αρ. Πρωτοκόλλου</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.protocolNo}} </md-cell>
</ng-container>
<ng-container cdkColumnDef="date">
<md-header-cell *cdkHeaderCellDef md-sort-header> Ημερομηνία</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.date | date:'dd/MM/yyyy' }}</md-cell>
</ng-container>
<ng-container cdkColumnDef="patient">
<md-header-cell *cdkHeaderCellDef md-sort-header> Ασθενής</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.patient.lastName}} {{row.patient.firstName}}</md-cell>
</ng-container>
<ng-container cdkColumnDef="doctor">
<md-header-cell *cdkHeaderCellDef md-sort-header> Ιατρός</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.doctor.lastName}} {{row.doctor.firstName}}</md-cell>
</ng-container>
<ng-container cdkColumnDef="signingDoctor">
<md-header-cell *cdkHeaderCellDef md-sort-header> Υπογράφων Ιατρός</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.signingDoctor.lastName}} {{row.signingDoctor.firstName}}</md-cell>
</ng-container>
<ng-container cdkColumnDef="clinic">
<md-header-cell *cdkHeaderCellDef md-sort-header> Κλινική </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.clinic?.name}} </md-cell>
</ng-container>
<md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
<md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
</md-table>
</div>
incident-results.component.ts
import {Component, Input, OnInit, ViewChild} from '@angular/core';
import {CommunicationService} from '../search/communication.service';
import {CollectionViewer, DataSource} from '@angular/cdk';
import {Observable} from 'rxjs/Observable';
import {Incident} from '../incidents/incident';
import {MdSort} from '@angular/material';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
@Component({
selector: 'incidents-results',
templateUrl: './incidents-results.component.html',
styleUrls: ['./incidents-results.component.css']
})
export class IncidentsResultsComponent implements OnInit{
@Input() noOfResults;
displayedColumns = ['protocolNo', 'date','patient', 'doctor', 'signingDoctor', 'clinic'];
dataSource: MyDataSource | null;
// @ViewChild(MdPaginator) paginator: MdPaginator;
@ViewChild(MdSort) sort: MdSort;
constructor(private communicationService: CommunicationService) {
}
ngOnInit(): void {
this.dataSource = new MyDataSource(this.communicationService, this.sort);
}
}
class MyDataSource extends DataSource<any> {
constructor(private communicationService: CommunicationService, private sort: MdSort ){
super();
}
connect(collectionViewer: CollectionViewer): Observable<Incident[]> {
const displayDataChanges = [
this.sort.mdSortChange,
this.communicationService.getIncidents() //_exampleDatabase.dataChange,
];
return Observable.merge(...displayDataChanges).map(() => {
return this.getSortedData();
});
// return this.communicationService.getIncidents();
}
disconnect(collectionViewer: CollectionViewer): void {
// throw new Error('Method not implemented.');
// this.communicationService.clearMessage();
}
getSortedData(): Incident[] {
const data = this.communicationService.data.slice();
if (!this.sort.active || this.sort.direction == '') { return data; }
return data.sort((a, b) => {
let propertyA: number|string = '';
let propertyB: number|string = '';
switch (this.sort.active) {
case 'protocolNo': [propertyA, propertyB] = [a.protocolNo, b.protocolNo]; break;
case 'date': [propertyA, propertyB] = [a.date, b.date]; break;
case 'patient': [propertyA, propertyB] = [a.patient.lastName, b.patient.lastName]; break;
case 'doctor': [propertyA, propertyB] = [a.doctor.lastName, b.doctor.lastName]; break;
case 'signingDoctor': [propertyA, propertyB] = [a.ypografonIatros.lastName, b.ypografonIatros.lastName]; break;
case 'clinic': [propertyA, propertyB] = [a.clinic.name, b.clinic.name]; break;
}
let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
let valueB = isNaN(+propertyB) ? propertyB : +propertyB;
return (valueA < valueB ? -1 : 1) * (this.sort.direction == 'asc' ? 1 : -1);
});
}
}
communication.service.ts
import {Injectable} from '@angular/core';
import {Incident} from '../incidents/incident';
import {Observable} from 'rxjs/Observable';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
@Injectable()
export class CommunicationService {
private subject = new BehaviorSubject<Incident[]>([]);
get data(): Incident[] { return this.subject.value; }
sendIncidents(incidents: Incident[]) {
this.subject.next(incidents);
}
clearMessage() {
this.subject.next([]);
}
getIncidents(): Observable<any> {
return this.subject.asObservable();
}
constructor() { }
}
Providing a Plunker (or similar) is the *best* way to get the team to see your issue.
Plunker template: https://goo.gl/DlHd6U
#### What is the use-case or motivation for changing an existing behavior?
#### Which versions of Angular, Material, OS, TypeScript, browsers are affected?
"dependencies": {
"@angular/animations": "^4.3.2",
"@angular/cdk": "^2.0.0-beta.8",
"@angular/common": "^4.3.2",
"@angular/compiler": "^4.3.2",
"@angular/compiler-cli": "^4.3.2",
"@angular/core": "^4.3.2",
"@angular/flex-layout": "^2.0.0-beta.8",
"@angular/forms": "^4.3.2",
"@angular/http": "^4.3.2",
"@angular/material": "^2.0.0-beta.8",
"@angular/platform-browser": "^4.3.2",
"@angular/platform-browser-dynamic": "^4.3.2",
"@angular/platform-server": "^4.3.2",
"@angular/router": "^4.3.2",
"@ngui/auto-complete": "^0.13.3",
"@swimlane/ngx-datatable": "^10.0.3",
"angular-font-awesome": "^2.0.2",
"bootstrap": "^4.0.0-alpha.6",
"core-js": "^2.4.1",
"font-awesome": "^4.7.0",
"hammerjs": "^2.0.8",
"install": "^0.10.1",
"jquery": "^3.2.1",
"ngx-bootstrap": "^2.0.0-beta.2",
"npm": "^5.3.0",
"rxjs": "^5.1.0",
"tether": "^1.4.0",
"typescript": "^2.4.2",
"zone.js": "^0.8.4"
},
"devDependencies": {
"@angular/cli": "^1.2.6",
"@angular/compiler-cli": "4.3.2",
"@angular/language-service": "^4.0.0",
"@types/jasmine": "2.5.45",
"@types/node": "~6.0.60",
"codelyzer": "~3.0.1",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-node": "~3.0.4",
"tslint": "~5.3.2",
"typescript": "~2.3.3"
}
}
#### Is there anything else we should know?
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 22 (7 by maintainers)
If you want a working example of the MdTable with filtering, sorting, pagination, and selection, check out this StackBlitz: https://stackblitz.com/edit/angular-material2-issue-sct3gm
If the majority of your trouble is based on getting a good data source to do these things, I’m submitting PR #6747 soon that will add an already-built data source that handles filtering, sorting, and pagination.
In addition, I’m currently working on the design of an
md-simple-table
which will be a more opinionated md-table that comes with sorting, pagination, etc. It’ll be a much easier template API (though less configurable about what goes into cells).Well i think angular is going to fail because of its complexity. Just to write a HalloWorld application you only need to make a trip around Earth… And to use a third party Library you need to be the cousin of Yuri Geller. (Famous Magician)
Is it normal in order to use a dataTable to spend more than two days, and finally ending up in switching to a different library?? Well this is completely unacceptable for a library to have such a steep learning curve.
Ah I’m glad you got it up and working. Sorry for the complexity here in this table templating and datasource. We took the route of creating the complex foundation first so that we got it right in terms of performance, accessibility, and cell-templating architecture. However we knew that it’d be a bit of a struggle for early-users of the table since it uses pretty deep core Angular concepts (e.g. ng-template,
let row
, etc.)My main priority now is to simplify and build on top of the foundation, starting with the
MdTableDataSouce
and then the simple table that comes pre-built with a lot of cool features. Hopefully once these pieces our out, reading out table docs won’t feel like quite so much of a chore to get started.I am working with angular a year now, but by the time this project finishes i am switching to react. Angular is very difficult to learn an use. I can’t get it. You had a great tool for single page apps, GWT. What the heck happened to that. Why haven’t you supported it. I had used if for a project in the past and i had found it great. Why are you creating new Libraries that are very difficult to learn and use and you don’t support your old projects by making them more complete and easier to use???
Either i am completely stupid, or this dataTable Implementation is just for the developer. Could you at least write some documentation with examples, and please can your library just read data from a
source: Array<any>
and not only from a stream/observable of data???Never Mind I will just use jQuery DataTables…
Stupid material DataTable. Why does it have to be so difficult to use a data table. Why can’t it just support <row *nfFor='let item of items> … </row> or something similar.
Well i really can’t see it working. I don’t know if you can. I just see Loading Material Docs example… and nothing gets Loaded.
It would be really great if you could put a working example of data table in the docs site that includes: filtering, paging and sorting which is the most likely scenario and apparently the most difficult to get working. Including a simple data set rather than one generated on the fly would also help people understand better, thanks!
Thanks, the component code looks a lot simpler now than the Angular 4 version, I’ll try it out again.
On Mon, Jan 22, 2018 at 5:16 PM, Andrew Seguin notifications@github.com wrote:
You should read up on how array sorting works using comparators (just in general) to implement a good sort algorithm for your unstructured phone numbers (I suspect you’ll want to store a more structured number to make life easier on you)
Also, check out the
MatTableDataSource
which will also simplify a lot of your code. It natively handles the sort and pagination for you. Youll still want to override the sort function thoughHonestly, I agree. Datatable is much too complicated. I’ve spent several days just trying to get something that can filter, sort, and paginate. It’s almost getting to the point where it’d be easier to start from scratch.