Appearance
Virtual Tree API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
loadChildren | Function | null | Async function (node) => Promise<node[]> to load children when a node is expanded |
loadNodeChunk | Function | null | Async function (startIndex, endIndex) => Promise<node[]> to load root nodes in chunks; when provided, tree uses chunked mode |
chunkSize | Number | 500 | Number of root nodes per chunk when loadNodeChunk is used |
draggable | Boolean | false | When true, nodes can be reordered by drag-and-drop and Ctrl+↑/↓ |
Node shape
Each node is expected to have:
id(string): Unique node id.label(string): Display label.expanded(boolean, optional): Whether the node is expanded.hasChildren(boolean, optional): Whether the node has children (if true, chevron is shown and expand loads children).children(array, optional): Pre-loaded children; if not set andhasChildrenis true,loadChildren(node)is called on expand.
Events
| Event | Payload | Description |
|---|---|---|
load-children | { id, label, hasChildren } | Emitted before loading children for a node (for logging or analytics). |
node-click | { id, label, expanded, hasChildren } | Emitted when a node is toggled (expand/collapse) or clicked. |
node-move | { nodeId, label, fromParentId, fromIndex, toParentId, toIndex } | Emitted when a node is moved (draggable mode); persist to your backend here. |
Exposed methods (template ref)
| Method | Description |
|---|---|
expandAll() | Expands all nodes (with loadChildren may be slow on large trees). |
collapseAll() | Collapses all nodes. |
getExpandedNodes() | Returns array of expanded node ids. |
loadChunk(chunkId) | Loads a chunk by id (for chunked mode). |
setNodes(roots) | Sets root nodes (non-chunked mode only). |
moveNode(draggedId, target, emit) | Programmatic move (advanced). |
setSelectedNode(id) | Sets the selected node (draggable mode). |
CSS custom properties
The component uses these CSS variables (on .virtual-tree):
| Variable | Default | Description |
|---|---|---|
--viewport-height | 37.5rem | Height of the scrollable viewport. |
--row-height | 1.75rem | Height of each row. |
--row-gap | 0.5rem | Gap below each row. |
--buffer | 5 | Extra rows rendered above/below viewport for smooth scroll. |
Composable: useVirtualTree
The component is powered by useVirtualTree(props). For advanced usage (e.g. custom tree UI), you can use the composable directly; it returns treeRef, viewportRef, visibleRows, spacerTopPx, spacerBottomPx, toggleNode, expandAll, collapseAll, setNodes, moveNode, etc.
Example usage
vue
<template>
<OVirtualTree
:chunk-size="500"
:load-node-chunk="loadChunk"
:load-children="loadChildren"
draggable
@node-click="onNodeClick"
@load-children="onLoadChildren"
@node-move="onNodeMove"
/>
</template>
<script setup>
const loadChunk = async (startIndex, endIndex) => {
const res = await fetch(`/api/roots?start=${startIndex}&end=${endIndex}`);
return res.json();
};
const loadChildren = async (node) => {
const res = await fetch(`/api/nodes/${node.id}/children`);
return res.json();
};
const onNodeClick = (payload) => console.log('node-click', payload);
const onLoadChildren = (payload) => console.log('load-children', payload);
const onNodeMove = (payload) => console.log('node-move', payload);
</script>