import {TreeTableModule,TreeNode,SharedModule} from 'primeng/primeng';
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)
.then(data => { return 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>
TreeTable utilizes the following options defined by a column component.
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>
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>
Header and Footer are the two sections aka facets that are capable of displaying custom content.
import {Header} from 'primeng/primeng';
import {Footer} from 'primeng/primeng';
<p-treeTable [value]="files">
<header>List of Files</header>
<footer>Choose from the list.</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>
TreeTable supports two selection methods, single and multiple. 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, selection property should be an array.
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
}
}
By default label of a treenode is displayed inside a tree node, in case you need to place custom content define a 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>Template</h3>
<p-treeTable [value]="files">
<p:column>
<template let-col #node="rowData" pTemplate type="header">
<button type="button" pButton label="Refresh"></button>
</template>
<template let-col #node="rowData" pTemplate type="body">
<input [(ngModel)]="node.data.name" type="text" style="width:100%">
</template>
</p:column>
</p-treeTable>
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
}
]
}
Name | Type | Default | Description |
---|---|---|---|
value | array | null | An array of treenodes. |
selectionMode | string | null | Defines the selection mode, valid values "single" and "multiple". |
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. |
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. |
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 |
Native component that requires the css of PrimeUI TreeTable.
<p-growl [value]="msgs"></p-growl>
<p-treeTable [value]="files" [style]="{'margin-bottom':'30px'}">
<header>Basic</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]="files" selectionMode="single" [(selection)]="selectedFile"
(onNodeSelect)="nodeSelect($event)" (onNodeUnselect)="nodeUnselect($event)">
<header>Singe Selection</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>
Selected Node: {{selectedFile ? selectedFile.data.name : 'none'}}
<p-treeTable [value]="files" selectionMode="multiple" [(selection)]="selectedFiles"
(onNodeSelect)="nodeSelect($event)" (onNodeUnselect)="nodeUnselect($event)" [style]="{'margin-top':'30px'}">
<header>Multiple Selection</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>
Selected Nodes: <span *ngFor="let file of selectedFiles">{{file.data.name}} </span>
<p-treeTable [value]="files" [style]="{'margin-top':'30px'}">
<header>Editable Cells with Templating</header>
<p-column field="name" header="Name">
<template let-node="rowData" pTemplate type="body">
<input type="text" [(ngModel)]="node.data.name" style="width:100%;box-sizing:border-box;border-width:0px 0px 1px 0px">
</template>
</p-column>
<p-column field="size" header="Size">
<template let-node="rowData" pTemplate type="body">
<input type="text" [(ngModel)]="node.data.size" style="width:100%;box-sizing:border-box;border-width:0px 0px 1px 0px">
</template>
</p-column>
<p-column field="type" header="Type">
<template let-node="rowData" pTemplate type="body">
<input type="text" [(ngModel)]="node.data.type" style="width:100%;box-sizing:border-box;border-width:0px 0px 1px 0px">
</template>
</p-column>
</p-treeTable>
<p-treeTable [value]="lazyFiles" [style]="{'margin-top':'30px'}"
(onNodeExpand)="nodeExpand($event)">
<header>Lazy Loading</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[];
files: TreeNode[];
lazyFiles: TreeNode[];
selectedFile: TreeNode;
selectedFiles: TreeNode[];
constructor(private nodeService: NodeService) { }
ngOnInit() {
this.nodeService.getFilesystem().then(files => this.files = files);
this.nodeService.getLazyFilesystem().then(files => this.lazyFiles = files);
}
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);
}
}
}