JavaScript Treeview Library for Hierarchical Data – Quercus.js
Named after the botanical genus for oak trees, this library transforms your nested JSON data into expandable treeviews with built-in search, selection controls, and smooth animations.
selectable: false for root nodes or folders that shouldn’t be selected.checkboxSelectionEnabled and cascadeSelectChildren, an admin could check a parent role and automatically grant all the nested permissions below it.onRenderNode callback is perfect for this, as you could add employee photos, titles, or other custom information directly into the node’s HTML.1. Install & download with NPM.
# NPM
$ npm install quercus.js
2. Add references to the treeview.js and treeview.css files in your project.
<link rel="stylesheet" href="path/to/src/treeview.css"> <script src="path/to/src/treeview.js"></script>
3. Create a container element with a unique ID where the tree will be rendered.
<div id="myTreeview"></div>
4. Quercus.js expects an array of objects where each object represents a tree node. Nodes can contain a children array to create nested structures:
const treeData = [
{
id: '1',
name: 'JavaScript',
selectable: false,
children: [
{
id: '1.1',
name: 'React',
children: [
{id: '1.1.1', name: 'React.js'},
{id: '1.1.2', name: 'React Native', selected: true}
]
},
{
id: '1.2',
name: 'Vue',
children: [
{id: '1.2.1', name: 'Vite'},
{id: '1.2.2', name: 'Nuxt'}
]
}
]
},
{
id: '2',
name: 'HTML',
children: [
{id: '2.1', name: 'HTML5'},
{id: '2.2', name: 'XML'}
]
},
{id: '3', name: 'CSS'}
// ... more data here
]; 5. Create a new Treeview instance and pass in configuration options.
containerId: (string) Required. The ID of the HTML div element where the treeview will be rendered.nodeNameKey: (string) The key in your data object to use for the node’s label. Defaults to name.data: (Array<object>) The array of node objects representing your hierarchical data.searchEnabled: (boolean) If true, a search input field will be rendered above the treeview.searchPlaceholder: (string) Placeholder text for the search field. Defaults to Search tree....initiallyExpanded: (boolean) If true, all nodes will be expanded on initial load.multiSelectEnabled: (boolean) If true, users can select multiple nodes. If false, only a single node can be selected at a time.onSelectionChange: (function) A callback function that executes whenever the selection changes. It receives an array of all currently selected node data objects.onRenderNode: (function) A callback for custom node rendering. It receives the node’s data and the HTML element to populate.showSelectAllButton: (boolean) If true, a “Select All” / “Deselect All” button is displayed. Requires multiSelectEnabled, nodeSelectionEnabled, and checkboxSelectionEnabled to be true.showInvertSelectionButton: (boolean) If true, an “Invert Selection” button is displayed.showExpandCollapseAllButtons: (boolean) If true, “Expand All” and “Collapse All” buttons are displayed.nodeSelectionEnabled: (boolean) If true, nodes can be selected. If false, selection is disabled.cascadeSelectChildren: (boolean) If true, selecting a parent node will also select all of its children.checkboxSelectionEnabled: (boolean) If true, a checkbox will be displayed next to each node for selection.const tree = new Treeview({
containerId: 'myTreeview',
data: treeData,
searchEnabled: false,
searchPlaceholder: 'Search tree...',
initiallyExpanded: false,
multiSelectEnabled: false,
onSelectionChange: null,
onRenderNode: null,
showSelectAllButton: false,
showInvertSelectionButton: false,
showExpandCollapseAllButtons: false,
nodeSelectionEnabled: true,
cascadeSelectChildren: false,
checkboxSelectionEnabled: false,
nodeNameKey: 'name'
}); 6. The onRenderNode callback gives you complete control over node content. This callback receives two parameters: the node data object and a DOM element to populate. The expander icon gets added automatically by the library if the node has children.
Here’s an example that adds custom icons and status information:
const tree = new Treeview({
containerId: 'myTreeview',
data: treeData,
onRenderNode: (nodeData, nodeContentWrapper) => {
// Clear existing content for setData calls
nodeContentWrapper.innerHTML = '';
// Add custom icon based on node type
const icon = document.createElement('span');
icon.classList.add('custom-icon');
if (nodeData.type === 'folder') {
icon.textContent = '📁';
} else if (nodeData.type === 'file') {
icon.textContent = '📄';
}
nodeContentWrapper.appendChild(icon);
// Add node name with required class for search
const nameSpan = document.createElement('span');
nameSpan.classList.add('treeview-node-text', 'custom-name');
nameSpan.textContent = nodeData.name;
nodeContentWrapper.appendChild(nameSpan);
// Add status indicator if present
if (nodeData.status) {
const status = document.createElement('span');
status.classList.add('custom-status');
status.textContent = ` [${nodeData.status}]`;
nodeContentWrapper.appendChild(status);
}
}
}); When implementing custom rendering, keep these points in mind: Clear the nodeContentWrapper.innerHTML at the start of your function to prevent duplicate content when using setData. Always include the ‘treeview-node-text’ class on the span containing searchable text to maintain search functionality. The library automatically adds the expander icon, so you don’t need to create it in your custom renderer.
7. You can then interact with the tree programmatically after it’s initialized:
setData(newData): Updates the treeview with a new data array, completely re-rendering it.getSelectedNodes(): Returns an array containing the data objects of all currently selected nodes.getSelectedNodesAndChildrenValues(key): Returns an array of values for a specific key from all selected nodes and their descendants.selectNodeById(id, shouldSelect): Programmatically selects (true) or deselects (false) a specific node by its unique id.search(searchTerm): Programmatically performs a search on the treeview.setData(newData): Updates the treeview with a new data array, completely re-rendering it.getSelectedNodes(): Returns an array containing the data objects of all currently selected nodes.getSelectedNodesAndChildrenValues(key): Returns an array of values for a specific key from all selected nodes and their descendants.selectNodeById(id, shouldSelect): Programmatically selects (true) or deselects (false) a specific node by its unique id.search(searchTerm): Programmatically performs a search on the treeview.Q: Can I use Quercus.js with dynamically loaded data?
A: Yes, the setData method exists specifically for this use case. Call it whenever you receive new data from an API or need to update the tree based on user actions. Keep in mind that setData clears the current selection state, so you’ll need to restore selections programmatically if that’s required for your application.
Q: How do I handle very large trees with thousands of nodes?
A: Quercus.js renders the entire tree into the DOM on initialization, which can impact performance with extremely large datasets. For trees with more than a few hundred nodes, consider implementing server-side filtering or pagination before passing data to the library. Starting with initiallyExpanded set to false helps initial render performance by keeping most nodes collapsed.
Q: How can I persist the expanded and collapsed state across page reloads?
A: The library doesn’t include built-in persistence, but you can implement this by storing expanded node IDs in localStorage or your backend. Track expansion state changes by monitoring click events on expander elements, save the state, and programmatically expand nodes after initialization by traversing the tree and setting the appropriate classes and styles on parent nodes based on your stored state.
Q: Can I disable the expand and collapse animation?
A: The animation behavior is controlled through CSS transitions on the nested ul elements. You can disable animations by overriding the transition property in your custom stylesheet, setting it to ‘none’ on the relevant elements. This gives you control over animation duration or completely removes the animation effect if that better suits your interface requirements.
The post JavaScript Treeview Library for Hierarchical Data – Quercus.js appeared first on CSS Script.
GTA 6 pre-orders were rumored to go live today, May 18, but it looks like…
This website uses cookies.