Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular Material Table Error - Cannot read property 'find' of undefined ... #11427

Closed
jmpreston opened this issue May 20, 2018 · 15 comments
Closed

Comments

@jmpreston
Copy link

jmpreston commented May 20, 2018

Bug, feature request, or proposal:

Possible bug. Something changed in Angular Material 6 and was a breaking change for my project.

My table was working fine since it was introduced in Angular Material. I upgraded from Angular 5 to 6 and now I get this error when rendering the table:

TypeError: Cannot read property 'find' of undefined
at MatHeaderRowDef.ngOnChanges (table.js:47)

No data is yet loaded, a button does that. When I click the button:

TypeError: Cannot read property 'diff' of undefined
at MatRowDef.getColumnsDiff (table.js:57)

If I comment out a column then the error throws for the next column above it in the table so that all columns will produce this error, only one column at each render though.

The offending code in webpack:///./node_modules/@angular/cdk/esm2015/table.js:

    ngOnChanges(changes) {
        // Create a new columns differ if one does not yet exist. Initialize it based on initial value
        // of the columns property or an empty array if none is provided.
        const /** @type {?} */ columns = changes['columns'].currentValue || [];
        if (!this._columnsDiffer) {
Line 47:            this._columnsDiffer = this._differs.find(columns).create();
            this._columnsDiffer.diff(columns);
        }
    }

My table (shortened to two columns):

     <mat-table #table [dataSource]="dataSource" matSort>

        <ng-container matColumnDef="firstName">
          <mat-header-cell fxFlex="10%" *matHeaderCellDef> First Name </mat-header-cell>
          <mat-cell fxFlex="10%" *matCellDef="let row"> {{row.first_name}} </mat-cell>
        </ng-container>

        <ng-container matColumnDef="lastName">
          <mat-header-cell fxFlex="10%" *matHeaderCellDef mat-sort-header> Last Name </mat-header-cell>
          <mat-cell fxFlex="10%" *matCellDef="let row">  {{row.last_name}} </mat-cell>
        </ng-container>

       ...
        <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
        <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>

     </mat-table>

    <mat-paginator #paginator
                   [pageIndex]="0"
                   [pageSize]="5"
                   [pageSizeOptions]="[5, 10, 25, 100]">
    </mat-paginator>

In the component.ts file:

import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';

  private displayedColumns = [
    'firstName',
    'lastName',
    ...
    ];

    ngAfterViewInit() {
      this.dataSource.paginator = this.paginator;
    }

What is the expected behavior?

Table should compile with this error.

What is the current behavior?

The problem may be related to this closed issue but a bit different:
#6831

What are the steps to reproduce?

My first try with Stackblitz, never used Plunker, so probably something wrong. I shortened my code to just the problem code for the table. The error message goes away if I comment out the table. Other items on the page such as search don't affect this.

https://stackblitz.com/edit/angular-material2-issue-yp6jrt

What is the use-case or motivation for changing an existing behavior?

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

Angular CLI: 6.0.3
Node: 8.11.2
OS: darwin x64
Angular: 6.0.2
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.6.3
@angular-devkit/build-angular     0.6.3
@angular-devkit/build-optimizer   0.6.3
@angular-devkit/core              0.6.3
@angular-devkit/schematics        0.6.3
@angular/cdk                      6.0.0
@angular/cli                      6.0.3
@angular/flex-layout              6.0.0-beta.15
@angular/material                 6.0.0
@ngtools/webpack                  6.0.3
@schematics/angular               0.6.3
@schematics/update                0.6.3
rxjs                              6.1.0
typescript                        2.7.2
webpack                           4.8.3

Is there anything else we should know?

I followed upgrade.angular.io and used these magic lines in terminal:

npm install -g rxjs-tslint
rxjs-5-to-6-migrate -p src/tsconfig.app.json

I don't see how this could have affected my table. I suspect that something was changed for AM 6 and is causing a bug under some circumstances. My setup seems rather typical though.

@andrewseguin
Copy link
Contributor

andrewseguin commented May 21, 2018

This is due to an issue with how the Angular compiler was compiling our ES6 version. This should be fixed in the next patch release. See #9329 for details

Also, thanks for diving into the code and finding the offending line. That helped saved me a lot of time understanding the issue

@jmpreston
Copy link
Author

Thanks @andrewseguin for being on top of this! My table is the core of my app and not much dev work can be done until it renders. Rather stuck.

@andrewseguin
Copy link
Contributor

@svstartuplab Keep an eye out today or tomorrow for our next patch release 6.0.3 which should resolve the issue and get you unstuck

@jmpreston
Copy link
Author

Thanks @andrewseguin, the issue is fixed :-)

@andrewseguin
Copy link
Contributor

Glad to hear it! Thanks for verifying

@Narrator
Copy link

Narrator commented Aug 12, 2018

Hello, I'm pretty sure this issue is back with the release of 6.4.2.. i verified this by changing the @angular/material package from 6.4.1 to 6.4.2. I don't get the error with 6.4.1, but I do with 6.4.2.

Here's my html:

<div class="mat-elevation-z2 usersContainer" *ngIf="datasource && datasource.data && datasource.data.length > 0">
  <table mat-table [dataSource]="datasource" style="text-align:center">

      <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef> Name </th>
        <td mat-cell *matCellDef="let element" class="name"> {{ element.firstName }} {{ element.lastName }} </td>
      </ng-container>

      <ng-container matColumnDef="email">
        <th mat-header-cell *matHeaderCellDef> E-mail </th>
        <td mat-cell *matCellDef="let element" class="email"> {{element.email}} </td>
      </ng-container>

      <ng-container matColumnDef="role">
        <th mat-header-cell *matHeaderCellDef> Role </th>
        <td mat-cell style="text-transform: capitalize;" *matCellDef="let element" class="role"> {{ resolveRole(element.roleId) }} </td>
      </ng-container>

      <ng-container matColumnDef="edit">
        <th mat-header-cell *matHeaderCellDef> Edit </th>
        <td mat-cell *matCellDef="let element" class="edit">
          <button class="edit-button" (click)="editProfile(element)" mat-button >
            <mat-icon>
              create
            </mat-icon> Edit
          </button>
        </td>
      </ng-container>

      <ng-container matColumnDef="remove">
          <th mat-header-cell *matHeaderCellDef> Remove </th>
          <td mat-cell *matCellDef="let element" class="rempve">
            <button class="remove-button" (click)="removeUser(element)" mat-button >
              <mat-icon>
                delete
              </mat-icon> Remove
            </button>
          </td>
      </ng-container>

      <ng-container matColumnDef="verified">
        <th mat-header-cell *matHeaderCellDef class="verified"> Verified </th>
        <td mat-cell *matCellDef="let element">

          <button *ngIf="element.verified" class="verified-button" mat-button disabled>
              <mat-icon>
                verified_user
              </mat-icon> Verified
          </button>

          <button *ngIf="!element.verified" class="send-button" (click)="resendEmail(element)" mat-button>
              <mat-icon>
                email
              </mat-icon> Resend
          </button>
        </td>
      </ng-container>


      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>

    <mat-paginator [pageSizeOptions]="[15, 10, 20]" showFirstLastButtons></mat-paginator>
</div>

<div class="no-users" *ngIf="!datasource || !datasource.data || datasource.data.length < 1">
  <div class="no-content-text">
    <mat-icon>person_pin</mat-icon><br><br>
    Use the add button to register users.
  </div>
</div>

And my component's ngOnInit:

public ngOnInit() {
    this._userApi.getAllUsers()
      .pipe(takeUntil(this._unsubscribe))
      .subscribe({
        next: users => {
          this.users = users;
          this.datasource = new MatTableDataSource<TransitApi.User>(this.users);
          this.datasource.paginator = this.paginator;
        },
        error: err => {
          this._snackbar.open('Error loading user list.');
        }
      });
}

@hvdscheer
Copy link

Same here V6.4.1 is working. V6.4.2 and V6.4.3 throws an error:

ERROR TypeError: Cannot read property 'find' of undefined
at MatHeaderRowDef.ngOnChanges (table.js:324)
at MatHeaderRowDef.ngOnChanges (table.js:376)
at checkAndUpdateDirectiveInline (core.js:11642)
at checkAndUpdateNodeInline (core.js:13252)
at checkAndUpdateNode (core.js:13191)
at debugCheckAndUpdateNode (core.js:14147)
at debugCheckDirectivesFn (core.js:14090)
at Object.eval [as updateDirectives] (ShoppingListComponent.html:11)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:14078)
at checkAndUpdateView (core.js:13156)

HTML:
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>

@jmpreston
Copy link
Author

hvdscheer, you have a coding error. A var isn't being populated with data so it is undefined.

@RyanHayden
Copy link

I was receiving the same error and reverting back to 6.4.1 (angular/material and angular/cdk) fixed this for me. Was on 6.4.5

@hvdscheer
Copy link

Although the error stack trace leads to my own component the error is thrown in the material code. The "displayedColumns" is a hardcoded string array in my code. Again, in 6.4.1 everything is working fine. When i upgrade to 6.4.2 or 6.4.3 this error occurs.
public displayedColumns: string[] = ['name', 'numberOfProducts'];

@MauricioArroyo
Copy link

MauricioArroyo commented Aug 21, 2018

6.4.6, still an issue. Revert to 6.4.1 as it's suggested fixed the problem.

@charlesritchea
Copy link

@andrewseguin Please re-open this issue, it is no longer fixed

@andzejsw
Copy link

Reverting back versions cannot ever be considered as fix. So issue should be reopened, until it is working on latest versions!

@andrewseguin
Copy link
Contributor

Sorry guys, this is something that needs to be fixed in Angular. See this issue for its status: angular/angular#27267

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 10, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants