TreeTable TreeTable is used to display hierarchical data in tabular format..
Basic Single Selection

Selected Node: {{selectedFile ? selectedFile.data.name : 'none'}}

Multiple Selection with MetaKey

Selected Nodes: {{file.data.name}}

Checkbox Selection

Selected Nodes: {{file.data.name}}

Editable Cells with Templating Context Menu Lazy Loading

Import


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

Getting Started

TreeTable component requires an array of TreeNode objects as its value. Let's begin with the TreeNode api.

Name Type Default Description
label string null Label of the node.
data any null Data represented by the node.
icon string null Icon of the node to display next to content. Not used by TreeTable.
expandedIcon string null Icon to use in expanded state. Not used by TreeTable.
collapsedIcon string null Icon to use in collapsed state. Not used by TreeTable.
children TreeNode[] null An array of treenodes as children.
leaf boolean null Specifies if the node has children. Used in lazy loading.
style string null Inline style of the node.
styleClass string null Style class of the node.

Most of the time, nodes will be loaded from a remote datasoure, here is an example NodeService that fetches the data from a json file.


@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"
                    }
                }
            ]
        }
    ]
}

The component that uses this service makes a call to getFiles() and assigns them back to files property that is bound to the tree.


export class TreeTableDemoComponent implements OnInit {
    
    files: TreeNode[];

    constructor(private nodeService: NodeService) {}
    
    ngOnInit() {
        this.nodeService.getFileSystem().then(files => this.files = files);
    }

}


<p-treeTable [value]="files">
    <p-column field="name" header="Name"></p-column>
    <p-column field="size" header="Size"></p-column>
    <p-column field="type" header="Type"></p-column>
</p-treeTable>

Column Component

TreeTable utilizes the following options defined by a column component.

Properties

Name Type Default Description
field string null Property of a row data.
header string null Header text of a column.
footer string null Footer text of a column.
style string null Inline style of the column.
styleClass string null Style class of the column.

<p-column field="vin" header="Vin"></p-column>

Dynamic Colums

Columns can be instantiated using an array as well by iterating with ngFor.


export class TreeTableDemoComponent implements OnInit {

    files: TreeNode[];

    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]="cars">
    <p-column *ngFor="let col of cols" [field]="col.field" [header]="col.header"></p-column>
</p-treeTable>

Facets

Header and Footer are the two sections aka facets that are capable of displaying custom content.


<p-treeTable [value]="files">
    <p-header>List of Files</p-header>
    <p-footer>Choose from the list.</p-footer>
    <p-column field="name" header="Name"></p-column>
    <p-column field="size" header="Size"></p-column>
    <p-column field="type" header="Type"></p-column>
</p-treeTable>

Selection

TreeTable supports three selection methods, single, multiple and checkbox. Selection is enabled by setting selectionMode property and providing a single TreeNode or an array of TreeNodes to reference the selections depending on the selection mode.


export class TreeTableDemoComponent implements OnInit {
    
    files: TreeNode[];
    
    selectedFile: TreeNode;

    constructor(private nodeService: NodeService) {}
    
    ngOnInit() {
        this.nodeService.getFiles().then(files => this.files = files);
    }

}


<p-treeTable [value]="files" selectionMode="single" [(selection)]="selectedFile"></p-treeTable>

In multiple mode or checkbox mode, selection property should be an array. In multiple mode, items can either be selected using metaKey or toggled individually depending on the value of metaKeySelection property value which is true by default. On touch enabled devices metaKeySelection is turned off automatically. In checkbox mode, when inititing a tree with preselections, also set partialSelected property on node so that minus icon can be displayed when necessary.


    export class TreeTableDemoComponent implements OnInit {
        
        files: TreeNode[];
        
        selectedFiles: TreeNode[];

        constructor(private nodeService: NodeService) {}
        
        ngOnInit() {
            this.nodeService.getFiles().then(files => this.files = files);
        }

    }


<p-treeTable [value]="files" selectionMode="single" [(selection)]="selectedFiles"></p-treeTable>

TreeTable provides onNodeSelect and onNodeUnselect options as callbacks for selection feature.


<p-treeTable [value]="files" selectionMode="single" [(selection)]="selectedFiles" (onNodeSelect)="nodeSelect($event)"></p-treeTable>


export class TreeTableDemoComponent implements OnInit {
    
    files: TreeNode[];
    
    selectedFiles: TreeNode[];

    constructor(private nodeService: NodeService) {}
    
    ngOnInit() {
        this.nodeService.getFiles().then(files => this.files = files);
    }
    
    nodeSelect(event) {
        //event.node = selected node
    }

}

Selection of a particular node can be disabled by setting the selectable property of the node to false.

ContextMenu

TreeTable has exclusive integration with contextmenu component. In order to attach a menu to a treetable, define a local template variable for the menu and bind it to the contextMenu property of the treetable. This enables showing the menu whenever a row is right clicked.


<p-treeTable [value]="files" selectionMode="single" [(selection)]="selectedFile" [contextMenu]="cm">
    <p-header>Context Menu</p-header>
    <p-column field="name" header="Name"></p-column>
    <p-column field="size" header="Size"></p-column>
    <p-column field="type" header="Type"></p-column>
</p-treeTable>

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


export class TreeTableDemoComponent implements OnInit {
    
    files: TreeNode[];
    
    selectedFile: TreeNode;

    constructor(private nodeService: NodeService) {}
    
    ngOnInit() {
        this.nodeService.getFiles().then(files => this.files = files);
        
        this.items = [
            {label: 'View', icon: 'fa-search', command: (event) => this.viewNode(this.selectedFile2)},
            {label: 'Delete', icon: 'fa-close', command: (event) => this.deleteNode(this.selectedFile2)}
        ];
    }
    
    viewNode(node: TreeNode) {
        this.msgs = [];
        this.msgs.push({severity: 'info', summary: 'Node Selected', detail: node.data.name});
    }

    deleteNode(node: TreeNode) {
        node.parent.children = node.parent.children.filter( n => n.data !== node.data);
        this.msgs = [];
        this.msgs.push({severity: 'info', summary: 'Node Deleted', detail: node.data.name});
    }

}

Templating

By default label of a treenode is displayed inside a tree node, in case you need to place custom content define a ng-template inside a column that gets the column as an implicit variable and rowData as the node instance. Similarly, custom content can be placed at the header and footer of a column with templating. Example below places an input field to create editable treenodes.


<h3>ng-template</h3>
<p-treeTable [value]="files">
    <p-column>
        <ng-template let-col let-node="rowData" pTemplate="header">
            <button type="button" pButton label="Refresh"></button>
        </ng-template>
        <ng-template let-col let-node="rowData" pTemplate="body">
            <input [(ngModel)]="node.data.name" type="text" style="width:100%">
        </ng-template>
    </p-column>
</p-treeTable>

Lazy Loading

Lazy loading is handy to deal with large datasets. Instead of loading the whole tree, nodes can be loaded at onNodeExpand event. Important part of implementing lazy loading is defining leaf property of a node as false, this will instruct tree to display an arrow icon to indicate there are children of this node although they are not loaded yet. When the lazy node is expanded, onNodeExpand is called and a remote call can be made to add the children to the expanded node.


<p-treeTable [value]="files" (onNodeExpand)="loadNode($event)"></p-treeTable>


export class TreeTableDemoComponent implements OnInit {
    
    files: TreeNode[];
    
    selectedFiles: TreeNode[];

    constructor(private nodeService: NodeService) {}
    
    ngOnInit() {
        //initial nodes
        this.nodeService.getFiles().then(files => this.files = files);
    }
    
    loadNode(event) {
        if(event.node) {
            //in a real application, make a call to a remote url to load children of the current node and add the new nodes as children
            this.nodeService.getLazyFilesystem().then(nodes => event.node.children = nodes);
        }
    }

}

Assume at ngOnInit treetable is initialized with a data like below that has nodes having no actual children but leaf property is set false.


{
    "data":
    [  
        {  
            "data":{  
                "name":"Lazy Folder 0",
                "size":"75kb",
                "type":"Folder"
            },
            "leaf": false
        },
        {  
            "data":{  
                "name":"Lazy Folder 1",
                "size":"150kb",
                "type":"Folder"
            },
            "leaf": false
        }
    ]
}

Properties

Name Type Default Description
value array null An array of treenodes.
labelExpand string Expand Tooltip and screenreader text for expand icon.
labelCollapse string Collapse Tooltip and screenreader text for collapse icon.
expandedIcon string fa-caret-down Icon to display on an expanded node.
collapsedIcon string fa-caret-right Icon to display on an expanded node.
selectionMode string null Defines the selection mode, valid values are "single", "multiple" and "checkbox".
selection any null A single treenode instance or an array to refer to the selections.
style string null Inline style of the component.
styleClass string null Style class of the component.
metaKeySelection boolean true Defines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically.
toggleColumnIndex number 0 Index of the column that contains the toggler element.
tableStyle string null Inline style of the table element.
tableStyleClass string null Style class of the table element.

Events

Name Parameters Description
onNodeSelect event.originalEvent: browser event
event.node: Selected node instance.
Callback to invoke when a node is selected.
onNodeUnselect event.originalEvent: browser event
event.node: Unselected node instance.
Callback to invoke when a node is unselected.
onNodeExpand event.originalEvent: browser event
event.node: Expanded node instance.
Callback to invoke when a node is expanded.
onNodeCollapse event.originalEvent: browser event
event.node: Collapsed node instance.
Callback to invoke when a node is collapsed.
onContextMenuSelect event.originalEvent: browser event
event.node: Selected node instance.
Callback to invoke when a node is selected with right click.
onRowDblclick event.originalEvent: Browser event
event.node: Selected node instance.
Callback to invoke when a row is double clicked.

Styling

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

Name Element
ui-treetable Main container element
ui-treetable-header Header element
ui-treetable-tablewrapper Container of table
ui-treetable-footer Footer element

Dependencies

None.

View on GitHub

<p-growl [value]="msgs"></p-growl>

<p-treeTable [value]="files1">
    <p-header>Basic</p-header>
    <p-column field="name" header="Name"></p-column>
    <p-column field="size" header="Size"></p-column>
    <p-column field="type" header="Type"></p-column>
</p-treeTable>
    
<p-treeTable [value]="files2" selectionMode="single" [(selection)]="selectedFile"
    (onNodeSelect)="nodeSelect($event)" (onNodeUnselect)="nodeUnselect($event)" [style]="{'margin-top':'50px'}">
    <p-header>Singe Selection</p-header>
    <p-column field="name" header="Name"></p-column>
    <p-column field="size" header="Size"></p-column>
    <p-column field="type" header="Type"></p-column>
</p-treeTable>
<p>Selected Node: {{selectedFile ? selectedFile.data.name : 'none'}}</p>
    
<p-treeTable [value]="files3" selectionMode="multiple" [(selection)]="selectedFiles" 
    (onNodeSelect)="nodeSelect($event)" (onNodeUnselect)="nodeUnselect($event)" [style]="{'margin-top':'50px'}">
    <p-header>Multiple Selection</p-header>
    <p-column field="name" header="Name"></p-column>
    <p-column field="size" header="Size"></p-column>
    <p-column field="type" header="Type"></p-column>
</p-treeTable>
<p>Selected Nodes: <span *ngFor="let file of selectedFiles">{{file.data.name}} </span></p>

<p-treeTable [value]="files4" selectionMode="checkbox" [(selection)]="selectedFiles2" [style]="{'margin-top':'50px'}">
    <p-header>Checkbox Selection</p-header>
    <p-column field="name" header="Name"></p-column>
    <p-column field="size" header="Size"></p-column>
    <p-column field="type" header="Type"></p-column>
</p-treeTable>
<p>Selected Nodes: <span *ngFor="let file of selectedFiles2">{{file.data.name}} </span></p>

<p-treeTable [value]="files5" [style]="{'margin-top':'50px'}">
    <p-header>Editable Cells with Templating</p-header>
    <p-column field="name" header="Name">
        <ng-template let-node="rowData" pTemplate="body">
            <input type="text" [(ngModel)]="node.data.name" style="width:100%;border-width:0px 0px 1px 0px">
        </ng-template>
    </p-column>
    <p-column field="size" header="Size">
        <ng-template let-node="rowData" pTemplate="body">
            <input type="text" [(ngModel)]="node.data.size" style="width:100%;border-width:0px 0px 1px 0px">
        </ng-template>
    </p-column>
    <p-column field="type" header="Type">
        <ng-template let-node="rowData" pTemplate="body">
            <input type="text" [(ngModel)]="node.data.type" style="width:100%;border-width:0px 0px 1px 0px">
        </ng-template>
    </p-column>
</p-treeTable>

<p-treeTable [value]="files6" selectionMode="single" [(selection)]="selectedFile2" [style]="{'margin-top':'50px'}" [contextMenu]="cm">
    <p-header>Context Menu</p-header>
    <p-column field="name" header="Name"></p-column>
    <p-column field="size" header="Size"></p-column>
    <p-column field="type" header="Type"></p-column>
</p-treeTable>

<p-treeTable [value]="lazyFiles" [style]="{'margin-top':'50px'}"
    (onNodeExpand)="nodeExpand($event)">
    <p-header>Lazy Loading</p-header>
    <p-column field="name" header="Name"></p-column>
    <p-column field="size" header="Size"></p-column>
    <p-column field="type" header="Type"></p-column>
</p-treeTable>


export class TreeTableDemo implements OnInit {
    
    msgs: Message[];
    
    files1: TreeNode[];
    
    files2: TreeNode[];
    
    files3: TreeNode[];
    
    files4: TreeNode[];
    
    files5: TreeNode[];
    
    files6: TreeNode[];
            
    lazyFiles: TreeNode[];
        
    selectedFile: TreeNode;
    
    selectedFile2: TreeNode;
    
    selectedFiles: TreeNode[];
    
    selectedFiles2: TreeNode[];
    
    items: MenuItem[];
        
    constructor(private nodeService: NodeService) { }

    ngOnInit() {
        this.nodeService.getFilesystem().then(files => this.files1 = files);
        this.nodeService.getFilesystem().then(files => this.files2 = files);
        this.nodeService.getFilesystem().then(files => this.files3 = files);
        this.nodeService.getFilesystem().then(files => this.files4 = files);
        this.nodeService.getFilesystem().then(files => this.files5 = files);
        this.nodeService.getFilesystem().then(files => this.files6 = files);
        this.nodeService.getLazyFilesystem().then(files => this.lazyFiles = files);
        
        this.items = [
            {label: 'View', icon: 'fa-search', command: (event) => this.viewNode(this.selectedFile2)},
            {label: 'Delete', icon: 'fa-close', command: (event) => this.deleteNode(this.selectedFile2)}
        ];
    }
    
    nodeSelect(event) {
        this.msgs = [];
        this.msgs.push({severity: 'info', summary: 'Node Selected', detail: event.node.data.name});
    }
    
    nodeUnselect(event) {
        this.msgs = [];
        this.msgs.push({severity: 'info', summary: 'Node Unselected', detail: event.node.data.name});
    }
    
    nodeExpand(event) {
        if(event.node) {
            //in a real application, make a call to a remote url to load children of the current node and add the new nodes as children
            this.nodeService.getLazyFilesystem().then(nodes => event.node.children = nodes);
        }
    }
    
    viewNode(node: TreeNode) {
        this.msgs = [];
        this.msgs.push({severity: 'info', summary: 'Node Selected', detail: node.data.name});
    }

    deleteNode(node: TreeNode) {
        node.parent.children = node.parent.children.filter( n => n.data !== node.data);
        this.msgs = [];
        this.msgs.push({severity: 'info', summary: 'Node Deleted', detail: node.data.name});
    }
}