Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template parse errors when overriding DataTable component of primeNg

I want to override the template of the DataTable component of primeng and this is how my code looks like:

my-datatable.component.ts

import { Component, OnInit, ElementRef, Renderer2, ChangeDetectorRef } from '@angular/core';
import { DataTable, DomHandler } from 'primeng/primeng';
import { ObjectUtils } from '../../../../node_modules/primeng/components/utils/ObjectUtils'
import { ColumnHeaders } from '../../../../node_modules/primeng/components/datatable/datatable'

@Component({
  selector: 'my-datatable',
  templateUrl: './my-datatable.component.html',
  styleUrls: ['./my-datatable.component.scss']    
})
export class MyDatatableComponent extends DataTable {

    constructor(el: ElementRef, domHandler: DomHandler, renderer: Renderer2, changeDetector: ChangeDetectorRef, objectUtils: ObjectUtils) { 
        super(el, domHandler, renderer, changeDetector, objectUtils);
        console.log('MyDatatableComponent');
    }

}

my-datatable.component.html, this file has the same template as of the base component. Idea was to first run and then make modifications

<div [ngStyle]="style" [class]="styleClass" [style.width]="containerWidth" [ngClass]="{'ui-datatable ui-widget':true,'ui-datatable-reflow':responsive,'ui-datatable-stacked':stacked,'ui-datatable-resizable':resizableColumns,'ui-datatable-scrollable':scrollable}">
  <div class="ui-datatable-loading ui-widget-overlay" *ngIf="loading"></div>
  <div class="ui-datatable-loading-content" *ngIf="loading">
    <i class="fa fa-circle-o-notch fa-spin fa-2x"></i>
  </div>
  <div class="ui-datatable-header ui-widget-header" *ngIf="header">
    <ng-content select="p-header"></ng-content>
  </div>
  <p-paginator [rows]="rows" [first]="first" [totalRecords]="totalRecords" [pageLinkSize]="pageLinks" styleClass="ui-paginator-bottom" (onPageChange)="paginate($event)" [rowsPerPageOptions]="rowsPerPageOptions" *ngIf="paginator && paginatorPosition!='bottom' || paginatorPosition =='both'"></p-paginator>
  <div class="ui-datatable-tablewrapper" *ngIf="!scrollable">
    <table [class]="tableStyleClass" [ngStyle]="tableStyle">
      <thead class="ui-datatable-thead">
        <tr *ngIf="!headerColumnGroup" class="ui-state-default" [pColumnHeaders]="columns"></tr>
        <ng-template [ngIf]="headerColumnGroup">
          <tr *ngFor="let headerRow of headerColumnGroup.rows" class="ui-state-default" [pColumnHeaders]="headerRow.columns"></tr>
        </ng-template>
      </thead>
      <tfoot *ngIf="hasFooter()" class="ui-datatable-tfoot">
        <tr *ngIf="!footerColumnGroup" class="ui-state-default" [pColumnFooters]="columns"></tr>
        <ng-template [ngIf]="footerColumnGroup">
          <tr *ngFor="let footerRow of footerColumnGroup.rows" class="ui-state-default" [pColumnFooters]="footerRow.columns"></tr>
        </ng-template>
      </tfoot>
      <tbody [ngClass]="{'ui-datatable-data ui-widget-content': true, 'ui-datatable-hoverable-rows': (rowHover||selectionMode)}" [pTableBody]="columns"></tbody>
    </table>
  </div>

  <ng-template [ngIf]="scrollable">
    <div class="ui-datatable-scrollable-wrapper ui-helper-clearfix" [ngClass]="{'max-height':scrollHeight}">
      <div *ngIf="frozenColumns" [pScrollableView]="frozenColumns" frozen="true" [ngStyle]="{'width':this.frozenWidth}" class="ui-datatable-scrollable-view ui-datatable-frozen-view"></div>
      <div [pScrollableView]="scrollableColumns" [ngStyle]="{'width':this.unfrozenWidth, 'left': this.frozenWidth}" class="ui-datatable-scrollable-view" [virtualScroll]="virtualScroll" (onVirtualScroll)="onVirtualScroll($event)" [ngClass]="{'ui-datatable-unfrozen-view': frozenColumns}"></div>
    </div>
  </ng-template>

  <p-paginator [rows]="rows" [first]="first" [totalRecords]="totalRecords" [pageLinkSize]="pageLinks" styleClass="ui-paginator-bottom" [alwaysShow]="alwaysShowPaginator" (onPageChange)="paginate($event)" [rowsPerPageOptions]="rowsPerPageOptions" *ngIf="paginator && paginatorPosition!='top' || paginatorPosition =='both'"></p-paginator>
  <div class="ui-datatable-footer ui-widget-header" *ngIf="footer">
    <ng-content select="p-footer"></ng-content>
  </div>

  <div class="ui-column-resizer-helper ui-state-highlight" style="display:none"></div>
  <span class="fa fa-arrow-down ui-datatable-reorder-indicator-up" style="position: absolute; display: none;"></span>
  <span class="fa fa-arrow-up ui-datatable-reorder-indicator-down" style="position: absolute; display: none;"></span>
</div>

Also I have added this new component in the declarations array in the app.module.ts file. So, I know that it is being included, which is the reason why I am getting a parse error.

The errors which I encounter in the console is:

Unhandled Promise rejection: Template parse errors:
Can't bind to 'pColumnHeaders' since it isn't a known property of 'tr'. ("ass="ui-datatable-thead">
                  <tr *ngIf="!headerColumnGroup" class="ui-state-default" [ERROR ->][pColumnHeaders]="columns"></tr>
                  <ng-template [ngIf]="headerColumnGroup">
         "): ng:///AppModule/CsxDatatableComponent.html@14:74
Can't bind to 'pColumnHeaders' since it isn't a known property of 'tr'. ("                      <tr *ngFor="let headerRow of headerColumnGroup.rows" class="ui-state-default" [ERROR ->][pColumnHeaders]="headerRow.columns"></tr>
                  </ng-template>
              </thead>
"): ng:///AppModule/CsxDatatableComponent.html@16:100
Can't bind to 'pColumnFooters' since it isn't a known property of 'tr'. ("ass="ui-datatable-tfoot">
                  <tr *ngIf="!footerColumnGroup" class="ui-state-default" [ERROR ->][pColumnFooters]="columns"></tr>
                  <ng-template [ngIf]="footerColumnGroup">
         "): ng:///AppModule/CsxDatatableComponent.html@20:74
Can't bind to 'pColumnFooters' since it isn't a known property of 'tr'. ("                      <tr *ngFor="let footerRow of footerColumnGroup.rows" class="ui-state-default" [ERROR ->][pColumnFooters]="footerRow.columns"></tr>
                  </ng-template>
              </tfoot>
"): ng:///AppModule/CsxDatatableComponent.html@22:100
Can't bind to 'pTableBody' since it isn't a known property of 'tbody'. ("datatable-data ui-widget-content': true, 'ui-datatable-hoverable-rows': (rowHover||selectionMode)}" [ERROR ->][pTableBody]="columns"></tbody>
          </table>
      </div>
"): ng:///AppModule/CsxDatatableComponent.html@25:137
Can't bind to 'pScrollableView' since it isn't a known property of 'div'. ("-helper-clearfix" [ngClass]="{'max-height':scrollHeight}">
              <div *ngIf="frozenColumns" [ERROR ->][pScrollableView]="frozenColumns" frozen="true" 
                  [ngStyle]="{'width':this.frozenWid"): ng:///AppModule/CsxDatatableComponent.html@31:41
Can't bind to 'pScrollableView' since it isn't a known property of 'div'. ("ozenWidth}" class="ui-datatable-scrollable-view ui-datatable-frozen-view"></div>
              <div [ERROR ->][pScrollableView]="scrollableColumns" [ngStyle]="{'width':this.unfrozenWidth, 'left': this.frozenWidt"): ng:///AppModule/CsxDatatableComponent.html@33:19
Can't bind to 'virtualScroll' since it isn't a known property of 'div'. ("is.unfrozenWidth, 'left': this.frozenWidth}"
                  class="ui-datatable-scrollable-view" [ERROR ->][virtualScroll]="virtualScroll" (onVirtualScroll)="onVirtualScroll($event)"
                  [ngClas"): ng:///AppModule/CsxDatatableComponent.html@34:55 ; Zone: <root> ; Task: Promise.then ;

pColumnHeaders, pColumnFooters are all components which are already exported via the DataTableModule. I am unable to figure out how to make these parsing errors go away, I am sure I am missing something.

Any help is much appreciated.

Update: This is how my app.module.ts looks. I have the DataTableModule, BrowserModule and FormsModule imported. I am able to use the standard primeNg datatable component on my views, just not able to override it.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

/* PRIME NG */
import { 
          AutoCompleteModule,
          PanelMenuModule, 
          MenuItem, 
          MenubarModule, 
          OverlayPanelModule, 
          TabViewModule, 
          ButtonModule, 
          CodeHighlighterModule,
          DropdownModule,
          DialogModule, 
          MultiSelectModule ,
          InputTextModule,
          TooltipModule,
          CheckboxModule,
          SplitButtonModule,
          RadioButtonModule,
          MessagesModule,
          ConfirmDialogModule,
          ConfirmationService,
          AccordionModule,
          PanelModule,
          FieldsetModule,
          CalendarModule,
          DataTableModule,
          MenuModule,
          BreadcrumbModule,
          TreeModule,
          DomHandler,
          ChartModule
        } from 'primeng/primeng';
import { ObjectUtils } from '../../node_modules/primeng/components/utils/ObjectUtils';


/* APP-SPECIFIC */
import { WindowRef } from './windowref';
import { routing } from './app.routing';
import { MyDatatableComponent } from './components/my-datatable.component';


@NgModule({
  declarations: [ 
    DatatableComponent,   
    ChartsGraphsComponent,
    CsxDatatableComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    routing,
    AutoCompleteModule,
    BrowserAnimationsModule,
    PanelMenuModule,
    MenubarModule,
    OverlayPanelModule, 
    TabViewModule,
    ButtonModule,
    CodeHighlighterModule,
    DropdownModule,
    MultiSelectModule,
    DialogModule,
    InputTextModule,
    TooltipModule,
    CheckboxModule,
    SplitButtonModule,
    RadioButtonModule,
    MessagesModule,
    ConfirmDialogModule,
    AccordionModule,
    PanelModule,
    FieldsetModule,
    CalendarModule,
    DataTableModule,
    MenuModule,
    BreadcrumbModule,
    TreeModule,
    ChartModule
  ],
  providers: [
    DomHandler,
    ObjectUtils
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
like image 722
Himanshu Arora Avatar asked Jun 05 '17 18:06

Himanshu Arora


1 Answers

You see this error because the selectors you're trying to use are not exported by their respective modules, because they're part of the internal/private part of the PrimeNG framework.

Importing the DataTableModule will make no difference if the selectors you're trying to use are not exported.

In the case of [pColumnHeaders], defined in datatable.ts by the ColumnHeaders component, you'll see that the ColumnHeaders component is not exported in the DataTableModule definition:

@NgModule({
    imports: [CommonModule,SharedModule,PaginatorModule,FormsModule],
    exports: [DataTable,SharedModule],
    declarations: [DataTable,DTRadioButton,DTCheckbox,ColumnHeaders,ColumnFooters,TableBody,ScrollableView,RowExpansionLoader]
})
export class DataTableModule { }

Source of datatable.ts

For you to be able to use the [pColumnHeaders] selector, the DataTableModule would have to export the ColumnHeaders component like so:

@NgModule({
    imports: [CommonModule,SharedModule,PaginatorModule,FormsModule],
    exports: [DataTable,SharedModule,ColumnHeaders],
    declarations: [DataTable,DTRadioButton,DTCheckbox,ColumnHeaders,ColumnFooters,TableBody,ScrollableView,RowExpansionLoader]
})
export class DataTableModule { }

My guess is that this design is intentional and that you're trying to use 'private' and undocumented selectors that are not part of the API.

The question you have to ask yourself is what it is you're trying to achieve. Chances are that the PrimeNG DataTable API provides the interface to do that.

like image 164
Elwin Arens Avatar answered Oct 26 '22 10:10

Elwin Arens