Components: Cannot create md-table with sort

Created on 14 Jul 2017  路  15Comments  路  Source: angular/components

Bug, feature request, or proposal:

Bug

What is the expected behavior?

I wanted to implement the md-table with sorting as in the example https://material.angular.io/components/table/overview

What is the current behavior?

Got error:

ERROR TypeError: Cannot read property 'mdSortChange' of undefined

<md-table #table [dataSource]="dataSource" mdSort>

...
import {MdSort} from '@angular/material';

@ViewChild(MdSort) sort: MdSort;

    ngAfterViewInit() {
        console.log({SORT:this.sort});
    }

SORT : undefined

What are the steps to reproduce?

Copy example code from https://material.angular.io/components/table/overview

#### 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.2.6",
"@angular/cdk": "^2.0.0-beta.8",
"@angular/common": "^4.0.0",
"@angular/compiler": "^4.0.0",
"@angular/core": "^4.0.0",
"@angular/forms": "^4.0.0",
"@angular/http": "^4.0.0",
"@angular/material": "^2.0.0-beta.8",
"@angular/platform-browser": "^4.0.0",
"@angular/platform-browser-dynamic": "^4.0.0",
"@angular/router": "^4.0.0",
"core-js": "^2.4.1",
"rxjs": "^5.1.0",
"zone.js": "^0.8.4"
},
"devDependencies": {
"@angular/cli": "1.2.1",
"@angular/compiler-cli": "^4.0.0",
"@angular/language-service": "^4.0.0",
"@t褍pes/jasmine": "~2.5.53",
"@t褍pes/jasminewd2": "~2.0.2",
"@t褍pes/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"
}

Windows 7 x64, Google Chrome 59.0.3071.115

Is there anything else we should know?

Most helpful comment

You might forget to import the module : MdSortModule.
@see material2/src/demo-app/demo-app-module.ts

All 15 comments

Got same problem...
IMO the problem is with the @Viewchild, that doesn't get the reference to the table (there's no component MdSort in de CDK-table)

You might forget to import the module : MdSortModule.
@see material2/src/demo-app/demo-app-module.ts

There are two things you need to do:
1) Import MdSort and View Child:

import { MdSort } from '@angular/material';
import { Component, ViewChild } from '@angular/core';

2) Add ViewChild in your export class:

@ViewChild(MdSort) sort: MdSort;
That will fix the problem.

@fad250 : I have 1) the imports, and 2) the ViewChild declaration.
Debugging info shows that
@ViewChild(MdSort) sort: MdSort;
remains undefined.

Do I have to include a specific element in the HTML-file? I now only inserted a mdsort directive in the md-tabel tag:

<md-table #table [dataSource]="dataSource" mdSort>

edit: I also got the md-sort-header directives
<md-header-cell *cdkHeaderCellDef md-sort-header>Name</md-header-cell>

fixed it...
bug had nothing to do with the CDK table...
the md-table was in a *ngIf (which was set to true, but nonetheless caused an undefined mdSort)
I (temporarily) fixed it with an [style.visibility] binding.

anyboddy suggestions how to solve undefined instances due to an *ngIf?

@TomDevolder would you be able to show the html code snippet for *ngIf? As I have attempt this before with no issues as such.

Here you go, @fad250

<!-- viewAsTable:boolean -->
<div *ngIf="viewAsTable">
  <div class="example-container" fxLayout="column">

    <md-table  #table [dataSource]="dataSource" mdSort>

      <!--- Note that these columns can be defined in any order.
          The actual rendered columns are set as a property on the row definition" -->


      <!-- ID Column -->
      <ng-container cdkColumnDef="personId">
        <md-header-cell *cdkHeaderCellDef >ID</md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.id}} </md-cell>
      </ng-container>

      <!-- EIN Column -->
      <ng-container cdkColumnDef="EIN">
        <md-header-cell *cdkHeaderCellDef >EIN</md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.EIN}} </md-cell>
      </ng-container>

      <!-- Name Column -->
      <ng-container cdkColumnDef="personName">
        <md-header-cell *cdkHeaderCellDef md-sort-header>Name</md-header-cell>
        <md-cell *cdkCellDef="let row">{{row.lastName}}, {{row.firstName}}</md-cell>
      </ng-container>

      <!-- Function Column -->
      <ng-container cdkColumnDef="job">
        <md-header-cell *cdkHeaderCellDef md-sort-header>Function</md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.jobTitle}} </md-cell>
      </ng-container>

      <!-- Phone Column -->
      <ng-container cdkColumnDef="telephone">
        <md-header-cell *cdkHeaderCellDef md-sort-header>Telephone</md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.telephone[0].telephoneNumber}} </md-cell>
      </ng-container>

      <!-- Email Column -->
      <ng-container cdkColumnDef="email">
        <md-header-cell *cdkHeaderCellDef md-sort-header>Email</md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.email[0].address}} </md-cell>
      </ng-container>

      <!-- DoE Column -->
      <ng-container cdkColumnDef="dateOfEmployment">
        <md-header-cell *cdkHeaderCellDef md-sort-header>dateOfEmployment</md-header-cell>
        <md-cell *cdkCellDef="let row"> {{row.dateOfEmployment}} </md-cell>
      </ng-container>

      <md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
      <md-row *cdkRowDef="let row; columns: displayedColumns;" class="mat-caption" style="height:60px; font-size:5px" (click)="openAlbum(row.id)">

      </md-row>
    </md-table>

  </div>
</div>

<!-- Paginator is outside *ngIf because it is also used for a custom made Tiles component  -->
<md-paginator #paginator [length]="persons.length" [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]" (page)="getTilesPageView()" fixed>
</md-paginator>

this results in:
image

The paginator component, that resides out of the *ngIf, instantiates without a problem

@TomDevolder What if I need to have a ngIf to wait for data? In my OnInit, I'm getting data from WEB API and need to wait for it to initialize DataBase and therefore the DataSource needed for the table. Do you have any suggestion for that?

@TomDevolder I managed to get a work around by only requesting the API on the TableDataBase class, by filling the DataBase with the data from the API response. Thanks anyways

Do have the same error. Does anyone have a proper solution?

Same problem.
Sometimes it works to make the logic below (in others not):

import { ..., ChangeDetectorRef } from '@angular/core';
(...)
constructor(...,
private _detector: ChangeDetectorRef) { (...) }
(...)
this._detector.detectChanges(); // before get de datasource and after set the data in database

If you are defining a module that contains your table component above, you need to add MdSortModule to your imports:

@NgModule({
    imports: [MdSortModule],
    ....
})

Call your dataSource in ngOnInit function then you will not get any Errors

seanharr11 - yes, that was problem. Now (material 5) it is imports: [MatSortModule],. mat-table do not show any error or warning if missing MatSortModule.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

LoganDupont picture LoganDupont  路  3Comments

kara picture kara  路  3Comments

RoxKilly picture RoxKilly  路  3Comments

constantinlucian picture constantinlucian  路  3Comments

Hiblton picture Hiblton  路  3Comments