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 { }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With