lara-light-indigo

Tree

Tree is used to display hierarchical data.

Basic
Programmatic Control
Import via Module

import { Tree } from 'primereact/tree';
 
Import via CDN

<script src="https://unpkg.com/primereact/core/core.min.js"></script>
 
Getting Started

Tree component requires an array of TreeNode objects as its value.

TreeNode API
NameTypeDefaultDescription
keyanynullUnique key of the node.
labelstringnullLabel of the node.
dataanynullData represented by the node.
iconstringnullIcon of the node to display next to content.
childrenTreeNode[]nullAn array of treenodes as children.
stylestringnullInline style of the node.
classNamestringnullStyle class of the node.
draggablebooleantrueWhether the node is draggable when dragdrop is enabled.
droppablebooleantrueWhether the node is droppable when dragdrop is enabled.
selectablebooleannullWhether the node is selectable when selection mode is enabled.
leafbooleannullSpecifies if the node has children. Used in lazy loading.

<Tree value={data} />
 

const data: [
    {
        "key": "0",
        "label": "Documents",
        "data": "Documents Folder",
        "icon": "pi pi-fw pi-inbox",
        "children": [{
            "key": "0-0",
            "label": "Work",
            "data": "Work Folder",
            "icon": "pi pi-fw pi-cog",
            "children": [{ "key": "0-0-0", "label": "Expenses.doc", "icon": "pi pi-fw pi-file", "data": "Expenses Document" }, { "key": "0-0-1", "label": "Resume.doc", "icon": "pi pi-fw pi-file", "data": "Resume Document" }]
        },
        {
            "key": "0-1",
            "label": "Home",
            "data": "Home Folder",
            "icon": "pi pi-fw pi-home",
            "children": [{ "key": "0-1-0", "label": "Invoices.txt", "icon": "pi pi-fw pi-file", "data": "Invoices for this month" }]
        }]
    },
    {
        "key": "1",
        "label": "Events",
        "data": "Events Folder",
        "icon": "pi pi-fw pi-calendar",
        "children": [
            { "key": "1-0", "label": "Meeting", "icon": "pi pi-fw pi-calendar-plus", "data": "Meeting" },
            { "key": "1-1", "label": "Product Launch", "icon": "pi pi-fw pi-calendar-plus", "data": "Product Launch" },
            { "key": "1-2", "label": "Report Review", "icon": "pi pi-fw pi-calendar-plus", "data": "Report Review" }]
    },
    {
        "key": "2",
        "label": "Movies",
        "data": "Movies Folder",
        "icon": "pi pi-fw pi-star-fill",
        "children": [{
            "key": "2-0",
            "icon": "pi pi-fw pi-star-fill",
            "label": "Al Pacino",
            "data": "Pacino Movies",
            "children": [{ "key": "2-0-0", "label": "Scarface", "icon": "pi pi-fw pi-video", "data": "Scarface Movie" }, { "key": "2-0-1", "label": "Serpico", "icon": "pi pi-fw pi-video", "data": "Serpico Movie" }]
        },
        {
            "key": "2-1",
            "label": "Robert De Niro",
            "icon": "pi pi-fw pi-star-fill",
            "data": "De Niro Movies",
            "children": [{ "key": "2-1-0", "label": "Goodfellas", "icon": "pi pi-fw pi-video", "data": "Goodfellas Movie" }, { "key": "2-1-1", "label": "Untouchables", "icon": "pi pi-fw pi-video", "data": "Untouchables Movie" }]
        }]
    }
]
 
Controlled vs Uncontrolled

Tree expansion state is managed in two ways, in uncontrolled mode only initial expanded state of a node can be defined using expandedKeys property whereas in controlled mode expandedKeysproperty along with onToggle properties are used for full control over the state. If you need to expand or collapse the state of nodes programmatically then controlled mode should be used. Example below demonstrates both cases;


import React, { Component } from 'react';
import { Tree } from 'primereact/tree';
import { Button } from 'primereact/button';
import { NodeService } from '../service/NodeService';

export const TreeDemo = () => {

    const [nodes, setNodes] = useState(null);
    const [expandedKeys, setExpandedKeys] = useState({});

    useEffect(() => {
        nodeService = new NodeService();
        nodeService.getTreeNodes().then(data => setNodes(data));
    }, [])

    const toggleMovies = () => {
        let expandedKeys = {...expandedKeys};
        if (expandedKeys['2'])
            delete expandedKeys['2'];
        else
            expandedKeys['2'] = true;

        setExpandedKeys(expandedKeys);
    }

    return (
        <div>
            <h3 className="first">Uncontrolled</h5>
            <Tree value={nodes} />

            <h5>Controlled</h5>
            <Button onClick={toggleMovies} label="Toggle Movies" />
            <Tree value={nodes} expandedKeys={expandedKeys}
                onToggle={e => setExpandedKeys(e.value)} style={{marginTop: '.5em'}} />
        </div>
    )
}
 
Selection

Tree supports single, multiple and checkbox selection modes. Define selectionMode, selectionKeys and onSelectionChange properties to control the selection. In single mode, selectionKeys should be a single value whereas in multiple or checkbox modes an array is required. By default in multiple selection mode, metaKey is necessary to add to existing selections however this can be configured with metaKeySelection property. Note that in touch enabled devices, Tree does not require metaKey.


import React, {Component} from 'react';
import {Tree} from 'primereact/tree';
import {NodeService} from '../service/NodeService';

export const TreeSelectionDemo = () => {

    const [nodes, setNodes] = useState(null);
    const [selectedNodeKey] = useState(null);
    const [selectedNodeKeys1] = useState(null);
    const [selectedNodeKeys2] = useState(null);
    const [selectedNodeKeys3] = useState(null);

    useEffect(() => {
        nodeService = new NodeService();
        nodeService.getTreeNodes().then(data => setNodes(data));
    }, [])

    return (
        <div>
            <h5>Single Selection</h5>
            <Tree value={nodes} selectionMode="single" selectionKeys={selectedNodeKey} onSelectionChange={e => setSelectedNodeKey(e.value)} />

            <h5>Multiple Selection with MetaKey</h5>
            <Tree value={nodes} selectionMode="multiple" selectionKeys={selectedNodeKeys1} onSelectionChange={e => setSelectedNodeKeys1(e.value)} />

            <h5>Multiple Selection without MetaKey</h5>
            <Tree value={nodes} selectionMode="multiple" metaKeySelection={false} selectionKeys={selectedNodeKeys2} onSelectionChange={e => setSelectedNodeKeys2(e.value)} />

            <h5>Checkbox Selection</h5>
            <Tree value={nodes} selectionMode="checkbox" selectionKeys={selectedNodeKeys3} onSelectionChange={e => setSelectedNodeKeys3(e.value)} />
        </div>
    )
}
 
Lazy

Lazy loading is implemented using the onExpand event by adding children to the expanded node. leaf property should be enabled to indicate the node has children but not yet loaded. Here is a in-memory demo that loads generated nodes on expand event to imitate a remote call with a timeout. Notice the usage of loading property as well to give users a feedback about the loading process.


import React, {Component} from 'react';
import {Tree} from 'primereact/tree';
import {NodeService} from '../service/NodeService';

export const TreeLazyDemo = () => {

    const [nodes, setNodes] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        nodeService = new NodeService();
        setTimeout(() => {
            nodeService.getTreeNodes().then(data => {
                setNodes(data);
                setLoading(false);
            });
        }, 2000);
    }, [])

    const loadOnExpand = (event) => {
        if (!event.node.children) {
            setLoading(true)

            setTimeout(() => {
                let node = {...event.node};
                node.children = [];

                for (let i = 0; i < 3; i++) {
                    node.children.push({
                        key: node.key + '-' + i,
                        label: 'Lazy ' + node.label + '-' + i
                    });
                }

                let value = [...nodes];
                value[parseInt(event.node.key, 10)] = node;
                setNodes(value);
                setLoading(false);
            }, 500);
        }
    }

    return (
        <Tree value={nodes} onExpand={loadOnExpand} loading={loading} />
    )
}
 
Templating

label property of a node is used to display as the content by default. Templating is supported as well with the nodeTemplate callback that gets the node instance and returns JSX. For custom filter support define a filterTemplate function that gets the option instance as a parameter and returns the content for the filter element. Example below is a sample tree based navigation of React docs.


import React, { Component, useState, useRef } from 'react';
import { Tree } from 'primereact/tree';

export const TreeTemplatingDemo = () => {

    const [nodes, setNodes] = useState(createNavigation());
    const [filterValue, setFilterValue] = useState('');
    const filterInputRef = useRef();

    const createNavigation = () => {
        return [
            {
                label: 'Insallation',
                children: [
                    {label: 'Getting Started', url:'https://reactjs.org/docs/getting-started.html'},
                    {label: 'Add React', url: 'https://reactjs.org/docs/add-react-to-a-website.html'},
                    {label: 'Create an App', url:'https://reactjs.org/docs/create-a-new-react-app.html'},
                    {label: 'CDN Links', url: 'https://reactjs.org/docs/cdn-links.html'}
                ]
            },
            {
                label: 'Main Concepts',
                children: [
                    {label: 'Hello World', url: 'https://reactjs.org/docs/hello-world.html'},
                    {label: 'Introducing JSX', url: 'https://reactjs.org/docs/introducing-jsx.html'},
                    {label: 'Rendering Elements', url: 'https://reactjs.org/docs/rendering-elements.html'},
                    {label: 'Components and Props', url: 'https://reactjs.org/docs/components-and-props.html'},
                    {label: 'State and LifeCycle', url: 'https://reactjs.org/docs/state-and-lifecycle.html'},
                    {label: 'Handling Events', url: 'https://reactjs.org/docs/handling-events.html'}
                ]
            }
        ];
    }

    const nodeTemplate = (node, options) => {
        let label = <b>{node.label}</b>;

        if (node.url) {
            label = <a href={node.url}>{node.label}</a>;
        }

        return (
            <span className={options.className}>
                {label}
            </span>
        )
    }

    const filterTemplate = (options) => {
        let {filterOptions} = options;
    
        return (
            <div className="flex gap-2">
                <InputText value={filterValue} ref={filterInputRef} onChange={(e) => myFilterFunction(e, filterOptions)} />
                <Button label="Reset" onClick={() => myResetFunction(filterOptions)} />
            </div>
        )
    }
    
    const myResetFunction = (options) => {
        setFilterValue('');
        options.reset();
        filterInputRef && filterInputRef.current.focus()
    }
    
    const myFilterFunction = (event, options) => {
        let _filterValue = event.target.value;
        setFilterValue(_filterValue);
        options.filter(event);
    }

    return (
        <Tree value={nodes} nodeTemplate={nodeTemplate} filter filterTemplate={filterTemplate}/>
    )
}
 
DragDrop

Tree nodes can be reordered using dragdrop by setting dragdropScope property to a unique variable and updating the new value at onDragDrop callback. The value of the dragdropScope must be unique to provide intervention from other draggable elements on the page.


import React, {Component} from 'react';
import {Tree} from 'primereact/tree';
import {NodeService} from '../service/NodeService';

export const TreeDragDropDemo = () => {

    const [nodes, setNodes] = useState(null);

    useEffect(() => {
        nodeService = new NodeService();
        nodeService.getTreeNodes().then(data => setNodes(data));
    }, [])

    return (
        <div>
            <Tree value={nodes} dragdropScope="demo" onDragDrop={event => setNodes(event.value)} />
        </div>
    )
}
 
Filtering

Filtering is enabled by setting the filter property to true, by default label property of a node is used to compare against the value in the text field, in order to customize which field(s) should be used during search define filterBy property.

In addition filterMode specifies the filtering strategy. In lenient mode when the query matches a node, children of the node are not searched further as all descendants of the node are included. On the other hand, in strict mode when the query matches a node, filtering continues on all descendants.


<Tree value={nodes} filter />

<Tree value={nodes} filter filterBy="data.name,data.age" />

<Tree value={nodes} filter filterMode="strict" />
 
ContextMenu

One or more ContextMenu instances can be attached to nodes. Similar to selection, separate contextMenuSelectionKey and onContextMenuSelectionChange properties are necesary to manage the selected node with right click. In addition, a context menu can either be displayed at onContextMenu event. Since this event also passes the node instance, you may choose to display a different context menu for a particular node.


import React, { Component } from 'react';
import {Tree} from 'primereact/tree'
import {ContextMenu} from 'primereact/contextmenu';
import {Toast} from 'primereact/toast';
import {NodeService} from '../service/NodeService';

export const TreeContextMenuDemo = () => {

    const [nodes, setNodes] = useState(null);
    const [expandedKeys, setExpandedKeys] = useState({});
    const [selectedNodeKey, setSelectedNodeKey] = useState(null);
    const toast = useRef(null);
    const cm = useRef(null);
    const menu = [
        {
            label: 'View Key',
            icon: 'pi pi-search',
            command: () => {
                toast.current.show({severity: 'success', summary: 'Node Key', detail: selectedNodeKey});
            }
        },
        {
            label: 'Toggle',
            icon: 'pi pi-cog',
            command: () => {
                let expandedKeys = {...expandedKeys};
                if (expandedKeys[selectedNodeKey])
                    delete expandedKeys[selectedNodeKey];
                else
                    expandedKeys[selectedNodeKey] = true;
                setExpandedKeys(expandedKeys);
            }
        }
    ];

    useEffect(() => {
        nodeService = new NodeService();
        nodeService.getTreeNodes().then(data => setNodes(data));
    }, [])

    return (
        <div>
            <Toast ref={toast} />

            <ContextMenu model={menu} ref={cm} />

            <Tree value={nodes} expandedKeys={expandedKeys} onToggle={e => setExpandedkeys(e.value)}
                onContextMenuSelectionChange={event => setSelectedNodeKey(event.value)}
                onContextMenu={event => cm.current.show(event.originalEvent)} />
        </div>
    )
}
 
Properties
NameTypeDefaultDescription
idstringnullUnique identifier of the element.
valuearraynullAn array of treenodes.
selectionModestringnullDefines the selection mode, valid values "single", "multiple", and "checkbox".
selectionKeysanynullA single or an array of keys to control the selection state.
contextMenuSelectionKeyanynullA single key to control the selection with the context menu.
expandedKeysarraynullAn array of keys to represent the state of the tree expansion state in controlled mode.
styleobjectnullInline style of the component.
classNamestringnullStyle class of the component.
contentStyleobjectnullInline style of the tree content.
contentClassNamestringnullStyle class of the tree content.
metaKeySelectionbooleantrueDefines 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.
propagateSelectionUpbooleantrueWhether checkbox selections propagate to ancestor nodes.
propagateSelectionDownbooleantrueWhether checkbox selections propagate to descendant nodes.
loadingbooleanfalseWhether to display loading indicator.
loadingIconstringpi pi-spinIcon to display when tree is loading.
dragdropScopestringfalseUnique key to enable dragdrop functionality.
headeranynullThe template of header.
footeranynullThe template of footer.
ariaLabelstringfalseUsed to define a string that labels the component.
ariaLabelledBystringnullContains the element IDs of labels.
nodeTemplateanyfalseTemplate of node element.
filterTemplateanynullTemplate of filter element.
togglerTemplateanynullTemplate of toggler element.
filterTemplateanynullTemplate of filter element.
showHeaderbooleantrueWhether to show the header or not.
filterbooleanfalseWhen specified, displays an input field to filter the items.
filterValuestringnullWhen filtering is enabled, the value of input field.
filterBystringlabelWhen filtering is enabled, filterBy decides which field or fields (comma separated) to search against.
filterModestringlenientMode for filtering valid values are "lenient" and "strict". Default is lenient.
filterPlaceholderstringnullPlaceholder text to show when filter input is empty.
filterLocalestringundefinedLocale to use in filtering. The default locale is the host environment's current locale.
disabledbooleanfalseWhen present, it specifies that the component should be disabled.
Events
NameParametersDescription
onSelectevent.originalEvent: browser event
event.node: Selected node instance.
Callback to invoke when a node is selected.
onUnselectevent.originalEvent: browser event
event.node: Unselected node instance.
Callback to invoke when a node is unselected.
onExpandevent.originalEvent: browser event
event.node: Expanded node instance.
Callback to invoke when a node is expanded.
onCollapseevent.originalEvent: browser event
event.node: Collapsed node instance.
Callback to invoke when a node is collapsed.
onSelectionChangeevent.originalEvent: browser event
event.value: Selected node key(s).
Callback to invoke when selection changes.
onContextMenuSelectionChangeevent.originalEvent: browser event
event.value: Selected node key.
Callback to invoke when selection changes with a context menu.
onToggleevent.originalEvent: browser event
event.node: Toggled node instance.
Callback to invoke when a node is toggled.
onDragDropevent.originalEvent: browser event
event.value: New value after the dragdrop.
Callback to invoke when a node is selected.
onContextMenuevent.originalEvent: browser event
event.node: Selected node instance.
Callback to invoke when a node is selected with a context menu.
onFilterValueChangeevent.originalEvent: Browser event
event.value: the filtered value
Callback to invoke when filter value changes.
onNodeClickevent.originalEvent: Browser event
event.node: the current node
Callback to invoke when the node is clicked.
onNodeDoubleClickevent.originalEvent: Browser event
event.node: the current node
Callback to invoke when the node is double-clicked.
Methods
NameParametersDescription
filtervalue: the filter valueFilters the data.
Styling

Following is the list of structural style classes

NameElement
p-treeMain container element
p-tree-horizontalMain container element in horizontal mode
p-tree-containerContainer of nodes
p-treenodeA treenode element
p-treenode-contentContent of a treenode
p-treenode-togglerToggle element
p-treenode-toggler-iconToggle icon
p-treenode-iconIcon of a treenode
p-treenode-labelLabel of a treenode
p-treenode-childrenContainer element for node children
Accessibility

This section is under development. After the necessary tests and improvements are made, it will be shared with the users as soon as possible.

Dependencies

None.

Component Scale

Input Style

Ripple Effect

Free Themes

Built-in component themes created by the PrimeReact Theme Designer.

Bootstrap
Blue
Purple
Blue
Purple
Material Design
Indigo
Deep Purple
Indigo
Deep Purple
Material Design Compact
Indigo
Deep Purple
Indigo
Deep Purple
Tailwind
Tailwind Light
Fluent UI
Blue
PrimeOne Design - 2022 NEW
Lara Indigo
Lara Blue
Lara Purple
Lara Teal
Lara Indigo
Lara Blue
Lara Purple
Lara Teal
PrimeOne Design - 2021
Saga Blue
Saga Green
Saga Orange
Saga Purple
Vela Blue
Vela Green
Vela Orange
Vela Purple
Arya Blue
Arya Green
Arya Orange
Arya Purple
Premium Themes

Premium themes are only available exclusively for PrimeReact Theme Designer subscribers and therefore not included in PrimeReact core.

Soho Light
Soho Dark
Viva Light
Viva Dark
Mira
Nano

Legacy Free Themes

Nova
Nova Alt
Nova Accent
Luna Blue
Luna Green
Luna Amber
Luna Pink
Rhea

Premium Create-React-App Templates

Beautifully crafted premium create-react-app application templates by the PrimeTek design team.

Sakai
Atlantis
Freya
Ultima
Diamond
Sapphire
Serenity
Babylon
Avalon
Apollo
Roma