TreeTable TreeTable is used to display hierarchical data in tabular format.

Basic

Name Size Type {{rowData.name}} {{rowData.size}} {{rowData.type}}

Dynamic Columns

{{col.header}} {{rowData[col.field]}}

Import


import {TreeTableModule} from 'primeng/treetable';
import {TreeNode} from 'primeng/api';

Getting Started

TreeTable component requires a collection of TreeNode objects as its value and templates for the presentation. TreeNode API represents a node with various properties, here is the list of properties utilized by the TreeTable.


export interface TreeNode {
    data?: any;
    children?: TreeNode[];
    leaf?: boolean;
    expanded?: boolean;
}

Usually nodes will be loaded from a remote datasoure, an example NodeService that fetches the data from a json file would be;


@Injectable()
export class NodeService {

    constructor(private http: Http) {}

    getFilesystem() {
        return this.http.get('showcase/resources/data/filesystem.json')
                    .toPromise()
                    .then(res => <TreeNode[]> res.json().data);
    }
}

The filesystem.json file consists of sample data. In a real application, this should be a dynamic response generated from the remote call.


{
    "data":
    [
        {
            "data":{
                "name":"Documents",
                "size":"75kb",
                "type":"Folder"
            },
            "children":[
                {
                    "data":{
                        "name":"Work",
                        "size":"55kb",
                        "type":"Folder"
                    },
                    "children":[
                        {
                            "data":{
                                "name":"Expenses.doc",
                                "size":"30kb",
                                "type":"Document"
                            }
                        },
                        {
                            "data":{
                                "name":"Resume.doc",
                                "size":"25kb",
                                "type":"Resume"
                            }
                        }
                    ]
                },
                {
                    "data":{
                        "name":"Home",
                        "size":"20kb",
                        "type":"Folder"
                    },
                    "children":[
                        {
                            "data":{
                                "name":"Invoices",
                                "size":"20kb",
                                "type":"Text"
                            }
                        }
                    ]
                }
            ]
        },
        {
            "data":{
                "name":"Pictures",
                "size":"150kb",
                "type":"Folder"
            },
            "children":[
                {
                    "data":{
                        "name":"barcelona.jpg",
                        "size":"90kb",
                        "type":"Picture"
                    }
                },
                {
                    "data":{
                        "name":"primeui.png",
                        "size":"30kb",
                        "type":"Picture"
                    }
                },
                {
                    "data":{
                        "name":"optimus.jpg",
                        "size":"30kb",
                        "type":"Picture"
                    }
                }
            ]
        }
    ]
}

Files get loaded from a service and then bound to the value property whereas header and body templates are used to define the content of these sections.


export class TreeTableDemoComponent implements OnInit {

    files: TreeNode[];

    constructor(private nodeService: NodeService) {}

    ngOnInit() {
        this.nodeService.getFileSystem().then(files => this.files = files);
    }

}

Body template gets the following parameters;

  • $implicit: Wrapper object of a node used to serialized a TreeNode.
  • node: TreeNode instance.
  • rowData: Data of the TreeNode instance.
  • columns: Columns of the TreeTable.

Toggle icon is configured using the p-treeTableToggler by binding the rowNode instance. Most of the time, toggler icon is added to the first column however there is no restriction on where the toggler should be located inside the row.


<p-treeTable [value]="files">
    <ng-template pTemplate="header">
        <tr>
            <th>Name</th>
            <th>Size</th>
            <th>Type</th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData">
        <tr>
            <td>
                <p-treeTableToggler [rowNode]="rowNode"></p-treeTableToggler>
                {{rowData.name}}
            </td>
            <td>{{rowData.size}}</td>
            <td>{{rowData.type}}</td>
        </tr>
    </ng-template>
</p-treeTable>

Dynamic Columns

Instead of configuring columns one by one, a simple ngFor can be used to implement dynamic columns. cols property below is an array of objects that represent a column, only property that table component uses is field, rest of the properties like header depend on your choice.


export class TreeTableDemo implements OnInit {

    files: TreeNode[];

    cols: any[];

    constructor(private nodeService: NodeService) { }

    ngOnInit() {
        this.nodeService.getFilesystem().then(files => this.files = files);

        this.cols = [
            { field: 'name', header: 'Name' },
            { field: 'size', header: 'Size' },
            { field: 'type', header: 'Type' }
        ];
    }
}

There are two ways to render dynamic columns, since cols property is in the scope of component you can just simply bind it to ngFor directive to generate the structure.


<p-treeTable [value]="files">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of cols">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData">
        <tr>
            <td *ngFor="let col of cols; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

Other alternative is binding the cols array to the columns property and then defining a template variable to access it within your templates. There is only 1 case where this is required which is reorderable columns.


<p-treeTable [value]="files" [columns]="cols">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

Tip: Use ngSwitch to customize the column content per dynamic column.

Table Layout

For performance reasons, default table-layout is fixed meaning the cell widths do not depend on their content. If you require cells to scale based on their contents set autoLayout property to true. Note that for scrollable tables or tables with resizable columns auto layout is not supported.

Templates

TreeTable is a template driven component with named templates such as header and body that we've used so far. Templates grant a great level of customization and flexibility where you have total control over the presentation while table handles the features such as paging, sorting and more. This speeds up development without sacrifing flexibility. Here is the full list of available templates.

Name Parameters Description
caption - Caption content of the table.
header $implicit: Columns Content of the thead element.
body $implicit: Wrapper object of a node used to serialized a TreeNode
node: TreeNode instance.
rowData: Data of the TreeNode instance
columns: Columns of the TreeTable
Content of the tbody element.
footer $implicit: Columns Content of the tfoot element.
summary - Summary section to display below the table.
colgroup $implicit: Columns ColGroup element of the table to customize columns.
frozenheader $implicit: Columns Content of the thead element in frozen side.
frozenbody $implicit: Wrapper object of a node used to serialized a TreeNode
node: TreeNode instance.
rowData: Data of the TreeNode instance
columns: Columns of the TreeTable
Content of the tbody element in frozen side.
frozenfooter $implicit: Columns Content of the tfoot element in frozen side.
frozencolgroup $implicit: Columns ColGroup element of the table to customize frozen columns.
emptymessage $implicit: Columns Content to display when there is no value to display.
paginatorleft state: $implicit state.page: Current page
state.rows: Rows per page
state.first: Index of the first records
state.totalRecords: Number of total records
Content to display when there is no value to display.
paginatorright state: $implicit state.page: Current page
state.rows: Rows per page
state.first: Index of the first records
state.totalRecords: Number of total records
Content to display when there is no value to display.

Change Detection

TreeTable may need to be aware of changes in its value in some cases. For the sake of performance, this is only done when the reference of the value changes meaning a setter is used instead of ngDoCheck/IterableDiffers which can reduce performance. So when you manipulate the value such as removing a node, adding a node or changing children of a node, instead of using array methods such as push, splice create a new array reference using a spread operator or similar.


this.value = [...this.value];

Sections

Table offers various templates to display additional information about the data such as a caption, header, summary and footer.


<p-treeTable [value]="files" [columns]="cols">
    <ng-template pTemplate="caption">
        FileSystem
    </ng-template>
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                &123;&123;col.header&125;&125;
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                &123;&123;rowData[col.field]&125;&125;
            </td>
        </tr>
    </ng-template>
    <ng-template pTemplate="footer" let-columns>
        <tr>
            <td *ngFor="let col of columns">
                &123;&123;col.header&125;&125;
            </td>
        </tr>
    </ng-template>
    <ng-template pTemplate="summary">
        There are &123;&123;files?.length&125;&125; Root Folders
    </ng-template>
</p-treeTable>

See the live example.

Column Grouping

Columns can easily be grouped using templating. Let's start with sample data of sales of brands per year.


export class TreeTableColGroupDemo implements OnInit {

    sales: TreeNode[];

    cols: any[];

    ngOnInit() {
        this.sales = [
            {
                data: { brand: 'Bliss', lastYearSale: '51%', thisYearSale: '40%', lastYearProfit: '$54,406.00', thisYearProfit: '$43,342'},
                expanded: true,
                children: [
                    {
                        data: { brand: 'Product A', lastYearSale: '25%', thisYearSale: '20%', lastYearProfit: '$34,406.00', thisYearProfit: '$23,342' },
                        expanded: true,
                        children: [
                            {
                                data: { brand: 'Product A-1', lastYearSale: '20%', thisYearSale: '10%', lastYearProfit: '$24,406.00', thisYearProfit: '$13,342' },
                            },
                            {
                                data: { brand: 'Product A-2', lastYearSale: '5%', thisYearSale: '10%', lastYearProfit: '$10,000.00', thisYearProfit: '$10,000' },
                            }
                        ]
                    },
                    {
                        data: { brand: 'Product B', lastYearSale: '26%', thisYearSale: '20%', lastYearProfit: '$24,000.00', thisYearProfit: '$23,000' },
                    }
                ]
            },
            {
                data: { brand: 'Fate', lastYearSale: '83%', thisYearSale: '96%', lastYearProfit: '$423,132', thisYearProfit: '$312,122' },
                children: [
                    {
                        data: { brand: 'Product X', lastYearSale: '50%', thisYearSale: '40%', lastYearProfit: '$223,132', thisYearProfit: '$156,061' },
                    },
                    {
                        data: { brand: 'Product Y', lastYearSale: '33%', thisYearSale: '56%', lastYearProfit: '$200,000', thisYearProfit: '$156,061' },
                    }
                ]
            },
            {
                data: { brand: 'Ruby', lastYearSale: '38%', thisYearSale: '5%', lastYearProfit: '$12,321', thisYearProfit: '$8,500' },
                children: [
                    {
                        data: { brand: 'Product M', lastYearSale: '18%', thisYearSale: '2%', lastYearProfit: '$10,300', thisYearProfit: '$5,500' },
                    },
                    {
                        data: { brand: 'Product N', lastYearSale: '20%', thisYearSale: '3%', lastYearProfit: '$2,021', thisYearProfit: '$3,000' },
                    }
                ]
            },
            {
                data: { brand: 'Sky', lastYearSale: '49%', thisYearSale: '22%', lastYearProfit: '$745,232', thisYearProfit: '$650,323' },
                children: [
                    {
                        data: { brand: 'Product P', lastYearSale: '20%', thisYearSale: '16%', lastYearProfit: '$345,232', thisYearProfit: '$350,000' },
                    },
                    {
                        data: { brand: 'Product R', lastYearSale: '29%', thisYearSale: '6%', lastYearProfit: '$400,009', thisYearProfit: '$300,323' },
                    }
                ]
            },
            {
                data: { brand: 'Comfort', lastYearSale: '17%', thisYearSale: '79%', lastYearProfit: '$643,242', thisYearProfit: '500,332' },
                children: [
                    {
                        data: { brand: 'Product S', lastYearSale: '10%', thisYearSale: '40%', lastYearProfit: '$243,242', thisYearProfit: '$100,000' },
                    },
                    {
                        data: { brand: 'Product T', lastYearSale: '7%', thisYearSale: '39%', lastYearProfit: '$400,00', thisYearProfit: '$400,332' },
                    }
                ]
            },
            {
                data: { brand: 'Merit', lastYearSale: '52%', thisYearSale: ' 65%', lastYearProfit: '$421,132', thisYearProfit: '$150,005' },
                children: [
                    {
                        data: { brand: 'Product L', lastYearSale: '20%', thisYearSale: '40%', lastYearProfit: '$121,132', thisYearProfit: '$100,000' },
                    },
                    {
                        data: { brand: 'Product G', lastYearSale: '32%', thisYearSale: '25%', lastYearProfit: '$300,000', thisYearProfit: '$50,005' },
                    }
                ]
            },
            {
                data: { brand: 'Violet', lastYearSale: '82%', thisYearSale: '12%', lastYearProfit: '$131,211', thisYearProfit: '$100,214' },
                children: [
                    {
                        data: { brand: 'Product SH1', lastYearSale: '30%', thisYearSale: '6%', lastYearProfit: '$101,211', thisYearProfit: '$30,214' },
                    },
                    {
                        data: { brand: 'Product SH2', lastYearSale: '52%', thisYearSale: '6%', lastYearProfit: '$30,000', thisYearProfit: '$70,000' },
                    }
                ]
            },
            {
                data: { brand: 'Dulce', lastYearSale: '44%', thisYearSale: '45%', lastYearProfit: '$66,442', thisYearProfit: '$53,322' },
                children: [
                    {
                        data: { brand: 'Product PN1', lastYearSale: '22%', thisYearSale: '25%', lastYearProfit: '$33,221', thisYearProfit: '$20,000' },
                    },
                    {
                        data: { brand: 'Product PN2', lastYearSale: '22%', thisYearSale: '25%', lastYearProfit: '$33,221', thisYearProfit: '$33,322' },
                    }
                ]
            },
            {
                data: { brand: 'Solace', lastYearSale: '90%', thisYearSale: '56%', lastYearProfit: '$765,442', thisYearProfit: '$296,232' },
                children: [
                    {
                        data: { brand: 'Product HT1', lastYearSale: '60%', thisYearSale: '36%', lastYearProfit: '$465,000', thisYearProfit: '$150,653' },
                    },
                    {
                        data: { brand: 'Product HT2', lastYearSale: '30%', thisYearSale: '20%', lastYearProfit: '$300,442', thisYearProfit: '$145,579' },
                    }
                ]
            },
            {
                data:  { brand: 'Essence', lastYearSale: '75%', thisYearSale: '54%', lastYearProfit: '$21,212', thisYearProfit: '$12,533' },
                children: [
                    {
                        data: { brand: 'Product TS1', lastYearSale: '50%', thisYearSale: '34%', lastYearProfit: '$11,000', thisYearProfit: '$8,562' },
                    },
                    {
                        data: { brand: 'Product TS2', lastYearSale: '25%', thisYearSale: '20%', lastYearProfit: '$11,212', thisYearProfit: '$3,971' },
                    }
                ]
            }
        ];
    }
}


<p-treeTable [value]="sales">
    <ng-template pTemplate="header">
        <tr>
            <th rowspan="3">Brand</th>
            <th colspan="4">Sale Rate</th>
        </tr>
        <tr>
            <th colspan="2">Sales</th>
            <th colspan="2">Profits</th>
        </tr>
        <tr>
            <th>Last Year</th>
            <th>This Year</th>
            <th>Last Year</th>
            <th>This Year</th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData">
        <tr>
            <td>
                <p-treeTableToggler [rowNode]="rowNode"></p-treeTableToggler>
                {{rowData.brand}}
            </td>
            <td>{{rowData.lastYearSale}}</td>
            <td>{{rowData.thisYearSale}}</td>
            <td>{{rowData.lastYearProfit}}</td>
            <td>{{rowData.thisYearProfit}}</td>
        </tr>
    </ng-template>
    <ng-template pTemplate="footer">
        <tr>
            <td colspan="3">Totals</td>
            <td>$3,283,772</td>
            <td>$2,126,925</td>
        </tr>
    </ng-template>
</p-treeTable>

See the live example.

Paginator

Pagination is enabled by setting paginator property to true, rows property defines the number of rows per page and pageLinks specify the the number of page links to display. See paginator component for more information.


<p-treeTable [value]="files" [columns]="cols" [paginator]="true" [rows]="10">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

Paginator accepts custom content for the left and the right side via named templates.


<p-treeTable [value]="files" [columns]="cols" [paginator]="true" [rows]="10">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
    <ng-template pTemplate="paginatorleft" let-state>
        {{state.first}}
        <button type="button" pButton icon="fa-refresh"></button>
    </ng-template>
    <ng-template pTemplate="paginatorright">
        <button type="button" pButton icon="fa-cloud-upload"></button>
    </ng-template>
</p-treeTable>

Paginator templates gets the paginator state as an implicit variable that provides the following properties

  • first
  • rows
  • page
  • totalRecords

See the live example.

Sorting

A column can be made sortable by adding the ttSortableColumn directive whose value is the field to sort against and a sort indicator via p-treeTableSortIcon component. For dynamic columns, setting ttSortableColumnDisabled property as true disables sorting for that particular column.


<p-treeTable [value]="files" [columns]="cols">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" [ttSortableColumn]="col.field">
                {{col.header}}
                <p-treeTableSortIcon [field]="col.field"></p-treeTableSortIcon>
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

Default sorting is executed on a single column, in order to enable multiple field sorting, set sortMode property to "multiple" and use metakey when clicking on another column.


<p-treeTable [value]="cars" sortMode="multiple">

In case you'd like to display the table as sorted by default initially on load, use the sortField-sortOrder properties in single mode.


<p-treeTable [value]="files" [columns]="cols" sortField="year">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" [ttSortableColumn]="col.field">
                {{col.header}}
                <p-treeTableSortIcon [field]="col.field"></p-treeTableSortIcon>
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

In multiple mode, use the multiSortMeta property and bind an array of SortMeta objects.


<p-treeTable [value]="files" [columns]="cols" sortMode="multiple" [multiSortMeta]="multiSortMeta">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" [ttSortableColumn]="col.field">
                {{col.header}}
                <p-treeTableSortIcon [field]="col.field"></p-treeTableSortIcon>
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>


this.multiSortMeta = [];
this.multiSortMeta.push({field: 'year', order: 1});
this.multiSortMeta.push({field: 'brand', order: -1});

Instead of using the built-in sorting algorithm a custom sort can be attached by enabling customSort property and defining a sortFunction implementation. This function gets a SortEvent instance that provides the data to sort, sortField, sortOrder and multiSortMeta.


export class TreeTableSortDemo implements OnInit {

    files: TreeNode[];

    cols: any[];

    constructor(private nodeService: NodeService) { }

    ngOnInit() {
        this.nodeService.getFilesystem().then(files => this.files = files);

        this.cols = [
            { field: 'name', header: 'Name' },
            { field: 'size', header: 'Size' },
            { field: 'type', header: 'Type' }
        ];
    }

    customSort(event: SortEvent) {
        //event.data = Data to sort
        //event.mode = 'single' or 'multiple' sort mode
        //event.field = Sort field in single sort
        //event.order = Sort order in single sort
        //event.multiSortMeta = SortMeta array in multiple sort

        event.data.sort((data1, data2) => {
            let value1 = data1[event.field];
            let value2 = data2[event.field];
            let result = null;

            if (value1 == null && value2 != null)
                result = -1;
            else if (value1 != null && value2 == null)
                result = 1;
            else if (value1 == null && value2 == null)
                result = 0;
            else if (typeof value1 === 'string' && typeof value2 === 'string')
                result = value1.localeCompare(value2);
            else
                result = (value1 < value2) ? -1 : (value1 > value2) ? 1 : 0;

            return (event.order * result);
        });
    }
}


<p-treeTable [value]="files" [columns]="cols" (sortFunction)="customSort($event)" [customSort]="true">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" [ttSortableColumn]="col.field">
                {{col.header}}
                <p-treeTableSortIcon [field]="col.field"></p-treeTableSortIcon>
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

For screen reader support of sortable headers, use ariaLabelDesc and ariaLabelAsc properties on p-sortIcon directive.

See the live example.

Selection

TreeTable provides built-in single, multiple and checkbox selection features where selected rows are bound to the selection property and onRowSelect-onRowUnselect events are provided as optional callbacks. In order to enable this feature, define a selectionMode, bind a selection reference and add ttSelectableRow directive whose value is the rowNode to the rows that can be selected. Additionally if you prefer double click use ttSelectableRowDblClick directive instead and to disable selection events on a particular row use ttSelectableRowDisabled property.

By default each row click adds or removes the row from the selection, if you prefer a classic metaKey based selection approach enable metaKeySelection true so that multiple selection or unselection of a row requires metaKey to be pressed. Note that, on touch enabled devices, metaKey based selection is turned off automatically as there is no metaKey in devices such as mobile phones.

Alternative to the row click, checkbox elements can be used to implement row selection as well.

When resolving if a row is selected, by default TreeTable compares selection array with the datasource which may cause a performance issue with huge datasets that do not use pagination. If available the fastest way is to use dataKey property that identifies a unique row so that Table can avoid comparing arrays as internally a map instance is used instead of looping arrays, on the other hand if dataKey cannot be provided consider using compareSelectionBy property as "equals" which uses reference comparison instead of the default "deepEquals" comparison. Latter is slower since it checks all properties.

In single mode, selection binding is an object reference.


export class TreeTableSelectionDemo {

    files: TreeNode[];

    selectedNode: TreeNode;

    constructor(private carService: CarService) { }

    ngOnInit() {
        this.nodeService.getFilesystem().then(files => this.files = files);
    }
}


<p-treeTable [value]="files" [columns]="cols" selectionMode="single" [(selection)]="selectedNode" dataKey="name">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr [ttSelectableRow]="rowNode">
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

In multiple mode, selection binding should be an array.


export class TreeTableSelectionDemo {

    files: TreeNode[];

    selectedNodes: TreeNode[];

    constructor(private carService: CarService) { }

    ngOnInit() {
        this.nodeService.getFilesystem().then(files => this.files = files);
    }
}


<p-treeTable [value]="files" [columns]="cols" selectionMode="multiple" [(selection)]="selectedNodes" dataKey="name">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr [ttSelectableRow]="rowNode">
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

Checkbox selection utilizes p-treeTableCheckbox component whose value should be the rowNode. Optionally p-treeTableHeaderCheckbox is available to select or unselect all the nodes.


<p-treeTable [value]="files" [columns]="cols" selectionMode="checkbox" [(selection)]="selectedNodes">
    <ng-template pTemplate="caption">
        <div style="text-align:left">
            <p-treeTableHeaderCheckbox></p-treeTableHeaderCheckbox>
            <span style="margin-left: .25em; vertical-align: middle">Toggle All</span>
        </div>
    </ng-template>
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                <p-treeTableCheckbox [value]="rowNode" *ngIf="i == 0"></p-treeTableCheckbox>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

See the live example.

ContextMenu

TreeTable has exclusive integration with contextmenu component. In order to attach a menu to a treetable, add ttContextMenuRow directive to the rows that can be selected with context menu, define a local template variable for the menu and bind it to the contextMenu property of the treetable. This enables displaying the menu whenever a row is right clicked. A separate contextMenuSelection property is used to get a hold of the right clicked row. For dynamic columns, setting ttContextMenuRowDisabled property as true disables context menu for that particular row.


<p-toast [style]="{marginTop: '80px'}"></p-toast>

<p-treeTable [value]="files" [columns]="cols" dataKey="name" [(contextMenuSelection)]="selectedNode" [contextMenu]="cm">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr [ttContextMenuRow]="rowNode">
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

<p-contextMenu #cm [model]="items"></p-contextMenu>

See the live example.

Editing

Incell editing is enabled by adding ttEditableColumn directive to an editable cell that has a p:treeTableCellEditor helper component to define the input-output templates for the edit and view modes respectively.


<p-treeTable [value]="files" [columns]="cols">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index" ttEditableColumn>
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                <p-treeTableCellEditor>
                    <ng-template pTemplate="input">
                        <input type="text" [(ngModel)]="rowData[col.field]">
                    </ng-template>
                    <ng-template pTemplate="output">
                        {{rowData[col.field]}}
                    </ng-template>
                </p-treeTableCellEditor>
            </td>
        </tr>
    </ng-template>
</p-treeTable>

If you require the edited row data and the field at onEditComplete event, bind the data to the ttEditableColumn directive and the field to the ttEditableColumnField directive


<td [ttEditableColumn]="rowData" [ttEditableColumnField]="'year'">

See the live example.

Column Resize

Columns can be resized using drag drop by setting the resizableColumns to true. There are two resize modes; "fit" and "expand". Fit is the default one and the overall table width does not change when a column is resized. In "expand" mode, table width also changes along with the column width. onColumnResize is a callback that passes the resized column header as a parameter. For dynamic columns, setting ttResizableColumnDisabled property as true disables resizing for that particular column. When you need to change column widths, since table width is 100%, giving fixed pixel widths does not work well as browsers scale them, instead give percentage widths.


<p-treeTable [value]="files" [columns]="cols" [resizableColumns]="true">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" ttResizableColumn>
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

Note: Scrollable tables require a column group to support resizing.


<p-treeTable [value]="files" [columns]="cols" [scrollable]="true" scrollHeight="200px" [resizableColumns]="true">
    <ng-template pTemplate="colgroup" let-columns>
        <colgroup>
            <col *ngFor="let col of columns" >
        </colgroup>
    </ng-template>
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" ttResizableColumn>
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

See the live example.

Column Reordering

Columns can be reordered using drag drop by setting the reorderableColumns to true and adding ttReorderableColumn directive to the columns that can be dragged. Note that columns should be dynamic for reordering to work. For dynamic columns, setting ttReorderableColumnDisabled property as true disables reordering for that particular column.


<p-treeTable [value]="files" [columns]="cols" [reorderableColumns]="true">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns" ttReorderableColumn>
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

See the live example.

Scrolling

TreeTable supports both horizontal and vertical scrolling as well as frozen columns.

Sample below uses vertical scrolling where headers are fixed and data is scrollable.


<p-treeTable [value]="files" [columns]="cols" [scrollable]="true" scrollHeight="200px">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

In horizontal scrolling on the other hand, it is important to give fixed widths to columns. In general when customizing the column widths of scrollable tables, use colgroup as below to avoid misalignment issues as it will apply both the header, body and footer sections which are different separate elements internally.


<p-treeTable [value]="files" [columns]="cols" [scrollable]="true" [style]="{width:'600px'}">
    <ng-template pTemplate="colgroup" let-columns>
        <colgroup>
            <col *ngFor="let col of columns" style="width:350px">
        </colgroup>
    </ng-template>
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

Horizontal and Vertical scrolling can be combined as well on the same table.


<p-treeTable [value]="files" [columns]="cols" [scrollable]="true" scrollHeight="200px" [style]="{width:'600px'}">
    <ng-template pTemplate="colgroup" let-columns>
        <colgroup>
            <col *ngFor="let col of columns" style="width:350px">
        </colgroup>
    </ng-template>
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

Particular columns can be made fixed where others remain scrollable, there are to ways to implement this functionality, either define a frozenColumns property if your frozen columns are dynamic or use frozenbody template. The width of the frozen section also must be defined with frozenWidth property. Templates including header, body and footer apply to the frozen section as well, however if require different content for the frozen section use frozenheader, frozenbody and frozenfooter instead.


<p-treeTable [value]="files" [columns]="scrollableCols" [frozenColumns]="frozenCols" [scrollable]="true" scrollHeight="200px" frozenWidth="200px">
    <ng-template pTemplate="colgroup" let-columns>
        <colgroup>
            <col *ngFor="let col of columns" style="width:250px">
        </colgroup>
    </ng-template>
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
    <ng-template pTemplate="frozenbody" let-rowNode let-rowData="rowData">
        <tr>
            <td>
                <p-treeTableToggler [rowNode]="rowNode"></p-treeTableToggler>
                {{rowData.name}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

When frozen columns are enabled, frozen and scrollable cells may have content with varying height which leads to misalignment. To avoid a performance hit, TreeTable avoids expensive calculations to align the row heights as it can be easily done with CSS manually.


.ui-treetable .ui-treetable-frozen-view .ui-treetable-tbody > tr > td,
.ui-treetable .ui-treetable-unfrozen-view .ui-treetable-tbody > tr > td {
    height: 24px !important;
}

See the live example.

Lazy Loading

Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking onLazyLoad callback everytime paging and sorting. To implement lazy loading, enable lazy attribute and provide a method callback using onLazyLoad that actually loads the data from a remote datasource. onLazyLoad gets an event object that contains information about how the data should be loaded. It is also important to assign the logical number of rows to totalRecords by doing a projection query for paginator configuration so that paginator displays the UI assuming there are actually records of totalRecords size although in reality they aren't as in lazy mode, only the records that are displayed on the current page exist.


<p-treeTable [value]="files" [columns]="cols" [paginator]="true" [rows]="10" [lazy]="true"
    (onLazyLoad)="loadNodes($event)" [totalRecords]="totalRecords">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>


loadNodes(event: LazyLoadEvent) {
    //event.first = First row offset
    //event.rows = Number of rows per page
    //event.sortField = Field name to sort in single sort mode
    //event.sortOrder = Sort order as number, 1 for asc and -1 for dec in single sort mode
    //multiSortMeta: An array of SortMeta objects used in multiple columns sorting. Each SortMeta has field and order properties.

    this.files = //do a request to a remote datasource using a service and return the cars that match the lazy load criteria
}

Lazy loading applies to the first level nodes in the tree hierarchy, instead if you need to lazy load the children of a node, set leaf as true on that node and use onNodeExpand event to load children when a node is expanded only.


<p-treeTable [value]="files" [columns]="cols" (onNodeExpand)="onNodeExpand($event)">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>


onNodeExpand(event) }
    //const node = event.node;
    //populate node.children

    //refresh the data
    this.files = [...this.files];
}

See the live example.

Responsive

TreeTable does not provide a built-in responsive feature as it is easy to implement as you have full control over the presentation, here is an example with media queries.


@Component({
    templateUrl: './treetableresponsivedemo.html',
    styles: [`
        :host ::ng-deep .priority-2,
        :host ::ng-deep .priority-3,
        :host ::ng-deep .visibility-sm {
            display: none;
        }

        @media screen and (max-width: 39.938em) {
            :host ::ng-deep .visibility-sm {
                display: inline;
            }
        }

        @media screen and (min-width: 40em) {
            :host ::ng-deep .priority-2 {
                display: table-cell;
            }
        }

        @media screen and (min-width: 64em) {
            :host ::ng-deep .priority-3 {
                display: table-cell;
            }
        }
    `]
})
export class TreeTableResponsiveDemo {

    files: TreeNode[];

    cols: any[];

    constructor(private nodeService: NodeService) { }

    ngOnInit() {
        this.nodeService.getFilesystem().then(files => this.files = files);

        this.cols = [
            { field: 'name', header: 'Name' },
            { field: 'size', header: 'Size' },
            { field: 'type', header: 'Type' }
        ];
    }
}


<p-treeTable [value]="files">
    <ng-template pTemplate="header">
        <tr>
            <th>Name</th>
            <th class="priority-2">Size</th>
            <th class="priority-3">Type</th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData">
        <tr>
            <td>
                <p-treeTableToggler [rowNode]="rowNode"></p-treeTableToggler>
                {{rowData.name}}
                <span class="visibility-sm">
                    / {{rowData.size}} - {{rowData.type}}
                </span>
            </td>
            <td class="priority-2">{{rowData.size}}</td>
            <td class="priority-3">{{rowData.type}}</td>
        </tr>
    </ng-template>
</p-treeTable>

See the live example.

EmptyMessage

When there is no data, emptymessage template can be used to display a message.


<p-treeTable [value]="files">
    <ng-template pTemplate="header">
        <tr>
            <th>Name</th>
            <th>Size</th>
            <th>Type</th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData">
        <tr>
            <td>
                <p-treeTableToggler [rowNode]="rowNode"></p-treeTableToggler>
                {{rowData.name}}
            </td>
            <td>{{rowData.size}}</td>
            <td>{{rowData.type}}</td>
        </tr>
    </ng-template>
    <ng-template pTemplate="emptymessage" let-columns>
        <tr>
            <td [attr.colspan]="columns.length">
                No records found
            </td>
        </tr>
    </ng-template>
</p-treeTable>

Loading Status

TreeTable has a loading property, when enabled a spinner icon is displayed to indicate data load. An optional loadingIcon property can be passed in case you'd like a different loading icon.


<p-treeTable [value]="files" [columns]="cols" [loading]="loading">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>


export class TreeTableDemo implements OnInit {

    files: TreeNode[];

    loading: boolean;

    cols: any[];

    constructor(private nodeService: NodeService) { }

    ngOnInit() {
        this.loading = true;
        this.nodeService.getFilesystem().then(files => {
            this.files = files;
            this.loading = false;
        {);

        this.cols = [
            { field: 'name', header: 'Name' },
            { field: 'size', header: 'Size' },
            { field: 'type', header: 'Type' }
        ];
    }
}

Styling Certain Rows and Columns

Certain rows and cells can easily be styled using templating features. In example below, the row whose vin property is '123' will get the 'success' style class. Example here paint the background of the last cell using a colgroup and highlights rows whose year is older than 2000.


<p-treeTable [value]="files" [columns]="cols">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr [ngClass]="{'kb-row': rowData.size.endsWith('kb')}">
            <td *ngFor="let col of columns; let i = index" [ngClass]="{'kb-cell': col.field === 'size' && rowData.size.endsWith('kb')}">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>

See the live example.

Performance Tips

  • When selection is enabled use dataKey to avoid deep checking when comparing objects.
  • Use rowTrackBy to avoid unnecessary dom operations.
  • Prefer lazy loading techniques for large datasets.

Properties

Name Type Default Description
value array null An array of objects to display.
columns array null An array of objects to represent dynamic columns.
style string null Inline style of the component.
styleClass string null Style class of the component.
autoLayout boolean false Whether the cell widths scale according to their content or not.
lazy boolean false Defines if data is loaded and interacted with in lazy manner.
paginator boolean false When specified as true, enables the pagination.
rows number null Number of rows to display per page.
first number 0 Index of the first row to be displayed.
totalRecords number null Number of total records, defaults to length of value when not defined.
pageLinks number null Number of page links to display in paginator.
rowsPerPageOptions array null Array of integer values to display inside rows per page dropdown of paginator
alwaysShowPaginator boolean true Whether to show it even there is only one page.
paginatorPosition string bottom Position of the paginator, options are "top","bottom" or "both".
paginatorDropdownAppendTo any null Target element to attach the paginator dropdown overlay, valid values are "body" or a local ng-template variable of another element.
defaultSortOrder number 1 Sort order to use when an unsorted column gets sorted by user interaction.
sortMode string single Defines whether sorting works on single column or on multiple columns.
resetPageOnSort boolean true When true, resets paginator to first page after sorting.
customSort boolean false Whether to use the default sorting or a custom one using sortFunction.
sortField string null Name of the field to sort data by default.
sortOrder number 1 Order to sort when default sorting is enabled.
multiSortMeta array null An array of SortMeta objects to sort the data by default in multiple sort mode.
sortFunction function null An event emitter to invoke on custom sorting, refer to sorting section for details.
selectionMode string null Specifies the selection mode, valid values are "single" and "multiple".
selection any null Selected row in single mode or an array of values in multiple mode.
contextMenuSelection any null Selected row with a context menu.
dataKey string null A property to uniquely identify a record in data.
metaKeySelection boolean true Defines whether metaKey is should be considered for the selection. On touch enabled devices, metaKeySelection is turned off automatically.
compareSelectionBy string deepEquals Algorithm to define if a row is selected, valid values are "equals" that compares by reference and "deepEquals" that compares all fields.
rowHover boolean false Adds hover effect to rows without the need for selectionMode.
loading boolean false Displays a loader to indicate data load is in progress.
loadingIcon string fa-circle-o-notch The icon to show while indicating data load is in progress.
scrollable boolean false When specifies, enables horizontal and/or vertical scrolling.
scrollHeight string null Height of the scroll viewport in fixed pixels or percentage.
frozenWidth string null Width of the frozen columns container.
frozenColumns array null An array of objects to represent dynamic columns that are frozen.
resizableColumns boolean false When enabled, columns can be resized using drag and drop.
columnResizeMode string fit Defines whether the overall table width should change on column resize, valid values are "fit" and "expand".
reorderableColumns boolean false When enabled, columns can be reordered using drag and drop.
contextMenu ContextMenu null Local ng-template varilable of a ContextMenu.
rowTrackBy Function null Function to optimize the dom operations by delegating to ngForTrackBy, default algoritm checks for object identity.

Events

Name Parameters Description
onNodeExpand event.originalEvent: Browser event
node: Expanded node.
Callback to invoke when a node is expanded.
onNodeCollapse event.originalEvent: Browser event
node: Collapsed node.
Callback to invoke when a node is collapsed.
onPage event.first: Index of first record in page
event.rows: Number of rows on the page
Callback to invoke when pagination occurs.
onSort event.field: Field name of the sorted column
event.order: Sort order as 1 or -1
event.multisortmeta: Sort metadata in multi sort mode. See multiple sorting section for the structure of this object.
Callback to invoke when a column gets sorted.
onLazyLoad event.first = First row offset
event.rows = Number of rows per page
event.sortField = Field name to sort with
event.sortOrder = Sort order as number, 1 for asc and -1 for dec
event.multiSortMeta: An array of SortMeta objects used in multiple columns sorting. Each SortMeta has field and order properties.
Callback to invoke when paging, sorting or filtering happens in lazy mode.
onColResize event.element: Resized column header
event.delta: Change of width in number of pixels
Callback to invoke when a column is resized.
onColReorder event.dragIndex: Index of the dragged column
event.dropIndex: Index of the dropped column
event.columns: Columns array after reorder.
Callback to invoke when a column is reordered.
onNodeSelect event.originalEvent: Browser event
event.nıde: Selected node
Callback to invoke when a node is selected.
onNodeUnselect event.originalEvent: Browser event
event.data: Unselected node
Callback to invoke when a node is unselected.
onContextMenuSelect event.originalEvent: Browser event
event.node: Selected node
Callback to invoke when a node is selected with right click.
onHeaderCheckboxToggle event.originalEvent: Browser event
event.checked: State of the header checkbox
Callback to invoke when state of header checkbox changes.
onEditInit event.column: Column object of the cell
event.data: Node data
Callback to invoke when a cell switches to edit mode.
onEditComplete event.column: Column object of the cell
event.data: Node data
Callback to invoke when cell edit is completed.
onEditCancel event.column: Column object of the cell
event.data: Node data
Callback to invoke when cell edit is cancelled with escape key.

Methods

Name Parameters Description
reset - Clears the sort and paginator state.

Styling

Following is the list of structural style classes, for theming classes visit theming page.

Name Element
ui-treetable Container element.
ui-treetable-caption Caption element.
ui-treetable-summary Section section.
ui-sortable-column Sortable column header.
ui-treetable-scrollable-header Container of header in a scrollable table.
ui-treetable-scrollable-body Container of body in a scrollable table.
ui-treetable-scrollable-footer Container of footer in a scrollable table.
ui-treetable-loading Loader mask.
ui-treetable-loading-content Loader content.
ui-treetable-wrapper Loader content.
ui-treetable-scrollable-wrapper Loader content.
ui-treetable-resizer-helper Vertical resize indicator bar.
ui-treetable-reorder-indicator-top Top indicator of column reordering.
ui-treetable-reorder-indicator-top Bottom indicator of column reordering.

Dependencies

None.

View on GitHub

<h3 class="first">Basic</h3>
<p-treeTable [value]="files1">
    <ng-template pTemplate="header">
        <tr>
            <th>Name</th>
            <th>Size</th>
            <th>Type</th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData">
        <tr>
            <td>
                <p-treeTableToggler [rowNode]="rowNode"></p-treeTableToggler>
                {{rowData.name}}
            </td>
            <td>{{rowData.size}}</td>
            <td>{{rowData.type}}</td>
        </tr>
    </ng-template>
</p-treeTable>

<h3>Dynamic Columns</h3>
<p-treeTable [value]="files2" [columns]="cols">
    <ng-template pTemplate="header" let-columns>
        <tr>
            <th *ngFor="let col of columns">
                {{col.header}}
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-rowNode let-rowData="rowData" let-columns="columns">
        <tr>
            <td *ngFor="let col of columns; let i = index">
                <p-treeTableToggler [rowNode]="rowNode" *ngIf="i == 0"></p-treeTableToggler>
                {{rowData[col.field]}}
            </td>
        </tr>
    </ng-template>
</p-treeTable>


export class TreeTableDemo implements OnInit {

    files1: TreeNode[];

    files2: TreeNode[];

    cols: any[];

    constructor(private nodeService: NodeService) { }

    ngOnInit() {
        this.nodeService.getFilesystem().then(files => this.files1 = files);
        this.nodeService.getFilesystem().then(files => this.files2 = files);

        this.cols = [
            { field: 'name', header: 'Name' },
            { field: 'size', header: 'Size' },
            { field: 'type', header: 'Type' }
        ];
    }
}