Page 1 of 1

Wrap turbotable

Posted: 03 Oct 2018, 11:46
by glennsymons
Hi,

How do i wrap the turbotable into my own component? I tried by passing the header and body template as ContentChildren and this works until i add pSortableColumn. Then i get the error:

Code: Select all

TableContainerPageComponent.html:55 ERROR Error: StaticInjectorError(AppModule)[TableBody -> Table]: 
  StaticInjectorError(Platform: core)[TableBody -> Table]: 
    NullInjectorError: No provider for Table!
Is there another way?

Wrapper html:

Code: Select all

<p-table>
<ng-template let-item [pTemplate]="template.name" *ngFor="let template of templates">
    <ng-template *ngTemplateOutlet="template.template; context: { $implicit: item }"></ng-template>
 </ng-template>
</p-table>
Wrapper ts:

Code: Select all

@ContentChildren(PrimeTemplate)
  templates: QueryList<any>;
Usage:

Code: Select all

<fw-table>
    <ng-template pTemplate="header">
      <tr>
        <th [pSortableColumn]="'username'">Gebruikersnaam</th>
        <th >Voornaam</th>
        <th >Achternaam</th>
      </tr>
    </ng-template>

    <ng-template pTemplate="body" let-user>
      <tr [pSelectableRow]="user">
        <td>{{user.username}}</td>
        <td>{{user.voornaam}}</td>
        <td>{{user.achternaam}}</td>
      </tr>
    </ng-template>
  </fw-table>
Greets,
Glenn

Re: Wrap turbotable

Posted: 07 Oct 2018, 16:41
by glennsymons
Nobody did this????

Re: Wrap turbotable

Posted: 28 Dec 2018, 17:50
by cwittied
I found this post as I was attempting to wrap the turbo table myself, and I also ran into the "No provider for Table!" issue. It turns out this error only appears when one of my templates is using pSortableColumn or pSelectableRow

I really wasn't able to find any help through google, but after 2 days of messing with it I figure out that if I put the 'Table' class into the providers collection of my wrapper component this error went away.

But then I got 'No provider for DomHandler!', so I added this to the providers of my wrapper... then 'No provider for ObjectUtils!', and 'No provider for TableService!'. But after adding all of these to the providers for my wrapper it finally started working.

Code: Select all

import { Table, TableService } from 'primeng/table';
import { DomHandler } from 'primeng/api';
import { ObjectUtils } from 'primeng/components/utils/objectutils';

@Component({
  selector: 'app-data-list',
  templateUrl: './data-list.component.html',
  styleUrls: ['./data-list.component.scss'],
  providers: [Table, DomHandler, ObjectUtils, TableService],
})
export class DataListComponent implements OnInit {
  @ViewChild(('datatable')) datatable: Table;
  @ContentChildren(PrimeTemplate) templates: QueryList<any>;
  ...
}
I just thought I'd reply with this info in case it might save someone else some time.

Re: Wrap turbotable

Posted: 31 Dec 2018, 18:22
by cwittied
I wanted to follow up because later in the day I realized this wasn't the correct fix.

While it did get rid of the error, and allow me to pass templates from my parent component into my wrapper component, the pSortableColumn and pSelectableRow directive/components did not work when passed in from the parent component. They worked fine in the default templates that were defined inside the wrapper nested inside the p-table, but not when passed in.

The reasoning is that when I put the Table class into my wrapper's providers list, it simply returns a new instance of a Table to anything that requires it. So the pSortableColumn and pSelectableRow defined outside the wrapper are receiving and working on an empty table that never gets rendered.

I was able to fix this by creating a TableFactory function that requires my wrapper as a dependency. When it's called to provide a Table, it simply provides the Table nested inside the injected wrapper component.

Code: Select all

...
import { DomHandler } from 'primeng/api';
import { Table, TableService } from 'primeng/table';
import { ObjectUtils } from 'primeng/components/utils/objectutils';
...

export function tableFactory(datalist: DataListComponent) {
  return datalist.datatable;
}

@Component({
  selector: 'app-data-list',
  templateUrl: './data-list.component.html',
  styleUrls: ['./data-list.component.scss'],
  providers: [ DomHandler, ObjectUtils, TableService, {
    provide: Table,
    useFactory: tableFactory,
    deps: [DataListComponent]
  }],
})
export class DataListComponent implements OnInit {
  @ViewChild(('datatable')) datatable: Table;
...
}

Re: Wrap turbotable

Posted: 26 Mar 2021, 13:09
by Episodex
Hello, I have the same problem and I try to implement your solution, but looks like the factory is invoked too soon in my code (datatable is undefined still). Can you show your template code for the wrapper? Many thanks for sharing your solution!