Components: [Table] Uninitialized columns cause error in table

Created on 4 Sep 2017  路  17Comments  路  Source: angular/components

Bug, feature request, or proposal:

Hi, I am new to angular. I copy the example for md-table and trying to run it, but it says:

MyComponent.html:17 ERROR TypeError: Cannot read property 'diff' of undefined
at MdRowDef.webpackJsonp.../../../cdk/@angular/cdk/table.es5.js.BaseRowDef.getColumnsDiff (table.es5.js:53)
at table.es5.js:533
at Array.forEach ()
at QueryList.webpackJsonp.../../../core/@angular/core.es5.js.QueryList.forEach (core.es5.js:5534)
at MdTable.webpackJsonp.../../../cdk/@angular/cdk/table.es5.js.CdkTable._renderUpdatedColumns (table.es5.js:532)
at MdTable.webpackJsonp.../../../cdk/@angular/cdk/table.es5.js.CdkTable.ngAfterContentChecked (table.es5.js:493)
at callProviderLifecycles (core.es5.js:11191)
at callElementProvidersLifecycles (core.es5.js:11169)
at callLifecycleHooksChildrenFirst (core.es5.js:11153)
at checkAndUpdateView (core.es5.js:12258)

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

I am using angular 4.3.6, cdk 2.0.0-beta.10, and angular material 2.0.0-beta.10
I run it on google chrome

here is my dependencies:

"dependencies": {
"@angular/animations": "^4.3.6",
"@angular/cdk": "^2.0.0-beta.10",
"@angular/common": "^4.3.6",
"@angular/compiler": "^4.3.6",
"@angular/core": "^4.3.6",
"@angular/forms": "^4.3.6",
"@angular/http": "^4.3.6",
"@angular/material": "^2.0.0-beta.10",
"@angular/platform-browser": "^4.3.6",
"@angular/platform-browser-dynamic": "^4.3.6",
"@angular/router": "^4.3.6",
"@covalent/core": "^1.0.0-beta.6",
"@next-level-integration/nli-common-lib": "^0.1.4",
"@next-level-integration/nli-input-lib": "^0.2.7",
"@next-level-integration/nli-menu-lib": "^0.2.3",
"@next-level-integration/nli-search-bar-lib": "0.0.6",
"@next-level-integration/nli-timeline-lib": "^0.1.6",
"@ngui/map": "^0.18.4",
"@ngx-translate/core": "^7.2.0",
"@ngx-translate/http-loader": "^1.0.2",
"classlist.js": "^1.1.20150312",
"core-js": "^2.5.1",
"hammerjs": "^2.0.8",
"intl": "^1.2.5",
"ngx-webstorage": "^1.8.0",
"perfect-scrollbar": "^0.8.0",
"rxjs": "^5.4.3",
"start": "^5.1.0",
"web-animations-js": "^2.3.1",
"zone.js": "^0.8.17"
},

Thanks.

has pr

Most helpful comment

If columns are set to null or undefined when the table is setting up, then it encounters this error.

Workaround: Initialize your column input to at least an empty array. The row definitions expect that a valid array of columns is provided as input.

All 17 comments

Can you provide your template code?

Having the same issue and this is my template:
`


ID
{{row.id}}



Name
{{row.name}}



`

I'm also having the same issue. The following template used to work without any problems with beta.8, though I did change over all "md-" to "cdk-".

<cdk-table #factorsTable [dataSource]="factorsDataSource"> <ng-container cdkColumnDef="factor"> <cdk-header-cell *cdkHeaderCellDef> Averaged Factor </cdk-header-cell> <cdk-cell *cdkCellDef="let row"> {{row.factor}} </cdk-cell> </ng-container> <ng-container cdkColumnDef="benchmark"> <cdk-header-cell *cdkHeaderCellDef> {{ benchmark.name }} </cdk-header-cell> <cdk-cell *cdkCellDef="let row"> {{row.benchmark == null ? 'N/A' : displayTableValue(row.benchmark) }} </cdk-cell> </ng-container> <ng-container *ngFor="let i of rangeEtfs" cdkColumnDef="{{i}}"> <cdk-header-cell *cdkHeaderCellDef>{{ i < etfData.length ? etfData[i].ticker : 'N/A' }}</cdk-header-cell> <cdk-cell *cdkCellDef="let row">{{ row.etfs[i] == null ? 'N/A' : displayTableValue(row.etfs[i]) }} </cdk-cell> </ng-container> <cdk-header-row *cdkHeaderRowDef="factorsColumns"></cdk-header-row> <cdk-row *cdkRowDef="let row; columns: factorsColumns;"></cdk-row> </cdk-table> </div>

I'm not able to reproduce. Here is a working example, can you try and reproduce from that?

I haven't tried reproducing on plunker, but I did do some investigation. It looks like the error is being thrown because CdkRowDef's _columnsDiffer hasn't been initialized yet. Here's the relevant code block:

var BaseRowDef = (function () {
/*
* @param {?} template
* @param {?} _differs
*/
function BaseRowDef(template, _differs) {
this.template = template;
this._differs = _differs;
}
/
*
* @param {?} changes
* @return {?}
/
BaseRowDef.prototype.ngOnChanges = function (changes) {
// Create a new columns differ if one does not yet exist. Initialize it based on initial value
// of the columns property.
var /
* @type {?} / columns = changes['columns'].currentValue;
if (!this._columnsDiffer && columns) {
this._columnsDiffer = this._differs.find(columns).create();
this._columnsDiffer.diff(columns);
}
};
/
*
* Returns the difference between the current columns and the columns from the last diff, or null
* if there is no difference.
* @return {?}
*/
BaseRowDef.prototype.getColumnsDiff = function () {
return this._columnsDiffer.diff(this.columns);
};
return BaseRowDef;
}());

Looks like getColumnsDiff is getting called before ngOnChanges has been called?

@andrewseguin Is this a real issue?

Any reproducible steps or plunkers would be appreciated. The getColumnsDiff is called once the table's content has been checked, which should include the content's row definitions. The ngOnChanges would have been called.

I see that the differ does not set up until the columns are defined. Can you check if the columns are being set sometime after the data is set on the table?

Either way, we'll want some good error handing here to notify the user. Will look into finding how to reproduce

If columns are set to null or undefined when the table is setting up, then it encounters this error.

Workaround: Initialize your column input to at least an empty array. The row definitions expect that a valid array of columns is provided as input.

PR has been sent that should resolve this issue by initializing the columns to an empty array if none are provided.

That appears to have solved the problem. Thank you.

Thanks for so many help :) but our deadline for the project is Oktober, so I already changed back to an older version which is still work. Sorry it's a bit of hurry so I don't have time to prepare any example project to show this problem. Thanks again to our lovely community.

No problem @jlangnli, but just a heads up that it's trivial to fix on your end to avoid this error. Simply initialize your columns array to []. Otherwise you'll see the fix out soon

I got this error because I did not have an md-header-cell defined for one of my columns. The old api did not require it but the new one appears to need it even if you leave the value of the header blank.

@andrewseguin Is it possible to initialize with no column and cell definition.
Below is scenario where i need that,

for e.g
<ng-container matColumnDef=""> <mat-header-cell> #</mat-header-cell> <mat-cell><i class="material-icons">mode_edit</i></mat-cell> </ng-container>

It seems that we have to initialized each column to be used in data table, sometime we only need a empty column just to add edit , delete button.
Thank you

Just change ngAfterViewInit with ngOnInit

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