akveo / nebular

:boom: Customizable Angular UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode
https://akveo.github.io/nebular
MIT License
8.06k stars 1.51k forks source link

Error displaying NBTreeGrid components ERROR TypeError: Cannot read property 'elementRef' of undefined #2449

Open DJEnterprise opened 4 years ago

DJEnterprise commented 4 years ago

Issue type

I'm submitting a ... (check one with "x")

Issue description

I am trying to use Tree Grid component alone in my web application. But the table doesn't get displayed when the page gets loaded with below error.

core.js:4081 ERROR TypeError: Cannot read property 'elementRef' of undefined at NbTreeGridComponent._applyNativeTableSections (table.js:1743) at NbTreeGridComponent.ngOnInit (table.js:1250) at callHook (core.js:2922) at callHooks (core.js:2892) at executeInitAndCheckHooks (core.js:2844) at selectIndexInternal (core.js:6051) at Module.ɵɵadvance (core.js:6024) at TreetableComponent_Template (treetable.component.html:9) at executeTemplate (core.js:7329) at refreshView (core.js:7198) defaultErrorLogger @ core.js:4081 handleError @ core.js:4129 (anonymous) @ core.js:28062 invoke @ zone-evergreen.js:364 run @ zone-evergreen.js:123 runOutsideAngular @ core.js:27065 tick @ core.js:28062 _loadComponent @ core.js:28088 bootstrap @ core.js:28029 (anonymous) @ core.js:27731 _moduleDoBootstrap @ core.js:27731 (anonymous) @ core.js:27701 invoke @ zone-evergreen.js:364 onInvoke @ core.js:27138 invoke @ zone-evergreen.js:363 run @ zone-evergreen.js:123 (anonymous) @ zone-evergreen.js:857 invokeTask @ zone-evergreen.js:399 onInvokeTask @ core.js:27126 invokeTask @ zone-evergreen.js:398 runTask @ zone-evergreen.js:167 drainMicroTaskQueue @ zone-evergreen.js:569 Promise.then (async) scheduleMicroTask @ zone-evergreen.js:552 scheduleTask @ zone-evergreen.js:388 scheduleTask @ zone-evergreen.js:210 scheduleMicroTask @ zone-evergreen.js:230 scheduleResolveOrReject @ zone-evergreen.js:847 then @ zone-evergreen.js:979 bootstrapModule @ core.js:27726 ./src/main.ts @ main.ts:11 webpack_require @ bootstrap:78 0 @ main.ts:12 webpack_require @ bootstrap:78 checkDeferredModules @ bootstrap:44 webpackJsonpCallback @ bootstrap:31 (anonymous) @ main.js:1 core.js:26534 Angular is running in development mode. Call enableProdMode() to enable production mode. core.js:4081 ERROR TypeError: Cannot read property 'classList' of null at StickyStyler._addStickyStyle (table.js:826) at StickyStyler.updateStickyFooterContainer (table.js:799) at NbTreeGridComponent.updateStickyFooterRowStyles (table.js:1417) at NbTreeGridComponent._forceRenderFooterRows (table.js:1621) at NbTreeGridComponent.ngAfterContentChecked (table.js:1276) at callHook (core.js:2926) at callHooks (core.js:2892) at executeInitAndCheckHooks (core.js:2844) at refreshView (core.js:7239) at refreshComponent (core.js:8335)

Current behavior: When trying to load the tree grid component.

Expected behavior:

Just display the tree grid component in UI with sample data.

Steps to reproduce:

Related code:

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
//import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {MatSortModule} from '@angular/material/sort';
import { MatTableModule } from '@angular/material/table';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatIconModule } from '@angular/material/icon';

import { NbThemeModule, NbCardModule, NbIconModule, NbInputModule, NbTreeGridModule, NbSearchModule, NbMenuModule } from '@nebular/theme';
import  { Ng2CompleterModule } from '@akveo/ng2-completer';
import { Ng2SmartTableModule } from 'ng2-smart-table';

//import { FsIconComponent } from './treetable/treetable.component';
import { TreetableComponent } from './treetable/treetable.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
//import { ThemeModule } from './@theme/theme.module';

@NgModule({
  declarations: [
    TreetableComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    NbThemeModule.forRoot(), 
    BrowserAnimationsModule,
    MatSortModule,
    MatTableModule,
    MatFormFieldModule,
    MatInputModule,
    FlexLayoutModule,
    MatIconModule,
    NbCardModule,
    NbTreeGridModule,
    NbMenuModule,
    NbSearchModule,
    NbIconModule,
    NbInputModule,
    Ng2CompleterModule,
    Ng2SmartTableModule,
    NgbModule,
  ],
  providers: [],
  bootstrap: [TreetableComponent]
})
export class AppModule { }

treetable.component.html

<nb-card>
    <nb-card-body>

      <label class="search-label" for="search">Search:</label>
      <input nbInput [nbFilterInput]="dataSource2" id="search" class="search-input"> 

      <table [nbTreeGrid]="dataSource2" [nbSort]="dataSource2" (sort)="updateSort($event)">

        <tr nbTreeGridHeaderRow *nbTreeGridHeaderRowDef="allColumns"></tr>
        <tr nbTreeGridRow *nbTreeGridRowDef="let row; columns: allColumns"></tr>

        <ng-container [nbTreeGridColumnDef]="customColumn">
          <th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(customColumn)" *nbTreeGridHeaderCellDef>
            {{customColumn}}
          </th>
          <td nbTreeGridCell *nbTreeGridCellDef="let row">
           <!-- <nbfsicon [kind]="row.data.kind" [expanded]="row.expanded"></nbfsicon> -->
            {{row.data[customColumn]}}
          </td>
        </ng-container>

        <ng-container *ngFor="let column of defaultColumns; let index = index"
                      [nbTreeGridColumnDef]="column"
                      [showOn]="getShowOn(index)">
          <th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(column)" *nbTreeGridHeaderCellDef>
            {{column}}
          </th>
          <td nbTreeGridCell *nbTreeGridCellDef="let row">{{row.data[column] || '-'}}</td>
        </ng-container>

      </table>

    </nb-card-body>
  </nb-card>

treetable.component.ts

/*
 * @license
 * Copyright Akveo. All Rights Reserved.
 * Licensed under the MIT License. See License.txt in the project root for license information.
 */

import { Component } from '@angular/core';
import { NbSortDirection, NbSortRequest, NbTreeGridDataSource, NbTreeGridDataSourceBuilder } from '@nebular/theme';

interface TreeNode<T> {
  data: T;
  children?: TreeNode<T>[];
  expanded?: boolean;
}

interface FSEntry {
  name: string;
  size: string;
  kind: string;
  items?: number;
}

@Component({
  selector: 'app-root',
  templateUrl: './treetable.component.html',
  styleUrls: ['./treetable.component.css'],
})
export class TreetableComponent {
  customColumn = 'name';
  defaultColumns = [ 'size', 'kind', 'items' ];
  allColumns = [ this.customColumn, ...this.defaultColumns ];

  dataSource2: NbTreeGridDataSource<FSEntry>;

  sortColumn: string;
  sortDirection: NbSortDirection = NbSortDirection.NONE;

  constructor(private dataSourceBuilder: NbTreeGridDataSourceBuilder<FSEntry>) {
    this.dataSource2 = this.dataSourceBuilder.create(this.data);
  }

  //@ViewChild(dataSource2, {static: true}) sort: nbSort;

   ngOnInit() {
    console.log("Hello");
  }

  updateSort(sortRequest: NbSortRequest): void {
    this.sortColumn = sortRequest.column;
    this.sortDirection = sortRequest.direction;
  }

  getSortDirection(column: string): NbSortDirection {
    if (this.sortColumn === column) {
      return this.sortDirection;
    }
    return NbSortDirection.NONE;
  }

  private data: TreeNode<FSEntry>[] = [
    {
      data: { name: 'Projects', size: '1.8 MB', items: 5, kind: 'dir' },
      children: [
        { data: { name: 'project-1.doc', kind: 'doc', size: '240 KB' } },
        { data: { name: 'project-2.doc', kind: 'doc', size: '290 KB' } },
        {
          data: { name: 'project-3', kind: 'dir', size: '466 KB', items: 3 },
          children: [
            { data: { name: 'project-3A.doc', kind: 'doc', size: '200 KB' } },
            { data: { name: 'project-3B.doc', kind: 'doc', size: '266 KB' } },
            { data: { name: 'project-3C.doc', kind: 'doc', size: '0' } },
          ],
        },
        { data: { name: 'project-4.docx', kind: 'docx', size: '900 KB' } },
      ],
    },
    {
      data: { name: 'Reports', kind: 'dir', size: '400 KB', items: 2 },
      children: [
        {
          data: { name: 'Report 1', kind: 'dir', size: '100 KB', items: 1 },
          children: [
            { data: { name: 'report-1.doc', kind: 'doc', size: '100 KB' } },
          ],
        },
        {
          data: { name: 'Report 2', kind: 'dir', size: '300 KB', items: 2 },
          children: [
            { data: { name: 'report-2.doc', kind: 'doc', size: '290 KB' } },
            { data: { name: 'report-2-note.txt', kind: 'txt', size: '10 KB' } },
          ],
        },
      ],
    },
    {
      data: { name: 'Other', kind: 'dir', size: '109 MB', items: 2 },
      children: [
        { data: { name: 'backup.bkp', kind: 'bkp', size: '107 MB' } },
        { data: { name: 'secret-note.txt', kind: 'txt', size: '2 MB' } },
      ],
    },
  ];

  getShowOn(index: number) {
    const minWithForMultipleColumns = 400;
    const nextColumnStep = 100;
    return minWithForMultipleColumns + (nextColumnStep * index);
  }
}

// @Component({
//   selector: 'nbfsicon',
//   template: `
//     <nb-tree-grid-row-toggle [expanded]="expanded" *ngIf="isDir(); else fileIcon">
//     </nb-tree-grid-row-toggle>
//     <ng-template #fileIcon>
//       <nb-icon icon="file-text-outline"></nb-icon>
//     </ng-template>
//   `,
// })
// export class FsIconComponent {
//   @Input() kind: string;
//   @Input() expanded: boolean;

//   isDir(): boolean {
//     return this.kind === 'dir';
//   }
// }

Other information:

npm, node, OS, Browser

<!--
Node, npm: `v12.16.2` and `6.14.4`
OS: Windows 7
Browser: Chrome
-->

Node: v12.16.2  npm: 6.14.4
OS: Windows 7
Browser: Chrome

Angular, Nebular

<!--
Check your `package-lock.json` or locate a `package.json` in the `node_modules` folder.
-->
Angular : 10.0.2
Nebular : 5.1.0
gvonhagel commented 4 years ago

Also experiencing this issue in Angular 10.0.1. Even the basic NbTreeGrid example in the Nebular docs does not work

Edit: Fixed by downgrading @angular/cdk to version 9.2.4

n0th1ng-else commented 4 years ago

Seems that the team worked hard to deliver the fix. Version 6 seems to fix the issue. @DJEnterprise @gvonhagel try updating to Nebular 6.0.0

Just updated my project and it works fine

DJEnterprise commented 4 years ago

Thanks @n0th1ng-else for looking into this. The issue seem to have fixed now.

Suroor-Ahmmad commented 4 years ago

This issue isn't fixed I guess, I'm getting below error

    ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'nativeElement' of null
    TypeError: Cannot read property 'nativeElement' of null
    at new CdkTable (table.js:formatted:1)
    at new NbTable (table.js:formatted:1)
    at new NbTreeGridComponent (table.js:formatted:1)
    at NodeInjectorFactory.NbTreeGridComponent_Factory [as factory] (table.js:formatted:1)
    at getNodeInjectable (table.js:formatted:1)
    at instantiateAllDirectives (table.js:formatted:1)
    at createDirectivesInstances (table.js:formatted:1)
    at ɵɵelementStart (table.js:formatted:1)
    at StudentDetailsComponent_Template (template.html:59)
    at executeTemplate (table.js:formatted:1)
    at resolvePromise (zone.js:1215)
    at resolvePromise (zone.js:1165)
    at zone.js:1277
    at ZoneDelegate.invokeTask (zone.js:407)
    at Object.onInvokeTask (table.js:formatted:1)
    at ZoneDelegate.invokeTask (zone.js:406)
    at Zone.runTask (zone.js:179)
    at drainMicroTaskQueue (zone.js:583)
    at ZoneTask.invokeTask [as invoke] (zone.js:492)
    at invokeTask (zone.js:1598)