Methods
An ApexTree instance is created with new ApexTree(element, options) and drawn with render(data). The render() call returns the internal Graph instance, which exposes the runtime API for layout, expand/collapse, selection, search, and export.
import { ApexTree } from 'apextree'
const tree = new ApexTree(document.getElementById('chart'), {
direction: 'top',
nodeWidth: 120,
nodeHeight: 40,
})
const graph = tree.render(data) // returns the Graph instance
Instance methods
render(data)
Builds the tree from a NestedNode root and returns the Graph instance. See Data Format for the node structure.
const graph = tree.render({
id: 'ceo',
name: 'Alice',
children: [
{ id: 'vp1', name: 'Bob', children: [] },
{ id: 'vp2', name: 'Carol', children: [] },
],
})
Throws if the container element is not found. To redraw with new data, call tree.render(newData) again.
destroy()
Destroys the chart instance and cleans up its DOM resources. Call before removing the container, or in a framework unmount hook.
tree.destroy()
getInstanceId()
Returns the unique identifier for this chart instance.
ApexTree.setLicense(key)
Static method. Sets the global ApexCharts license key. Call once at app startup, before creating any instance. Without a valid license the chart renders with a watermark.
ApexTree.setLicense('YOUR_LICENSE_KEY')
See Setting the License for framework patterns.
Graph methods
All of the following are called on the Graph object returned by render() (also reachable as tree.graph).
Layout and navigation
| Method | Description |
|---|---|
expand(nodeId) | Expand a collapsed node to reveal its children |
collapse(nodeId) | Collapse a node, hiding its descendants |
changeLayout(direction?) | Re-lay out the tree in a new direction: 'top', 'bottom', 'left', 'right', 'radial' |
fitScreen() | Fit the entire tree within the viewport |
zoom(zoomFactor) | Zoom by a numeric factor (e.g. 1.2 to zoom in, 0.8 to zoom out) |
centerOnNode(nodeId) | Center the camera on a node, keeping the current zoom level |
construct(data) | Rebuild the internal graph from new data (pair with render({ mode })) |
render({ mode }) | Re-draw. mode: 'initial', 'expand', 'collapse', or 'data-update' |
zoom() re-bases on the live viewBox before stepping, so a step is always multiplicative on the real scale: zoom(1.2) is 20% in, whatever programmatic camera moves happened first.
const graph = tree.render(data)
graph.expand('vp1')
graph.collapse('vp2')
graph.changeLayout('left')
graph.fitScreen()
graph.zoom(1.2)
graph.centerOnNode('vp1')
Live data updates
| Method | Description |
|---|---|
updateData(data) | Diff a new dataset against the live tree and spring to it |
Nodes present in both datasets keep their DOM wrapper and travel from where they are to where the new layout puts them; nodes only in the new data enter from their parent; nodes only in the old data retract and exit. Because the wrappers survive, so does everything the browser hangs off them (keyboard focus, hover, text selection) along with collapse state, selection, focus and expanded cards.
const graph = tree.render(data)
socket.on('org:changed', (next) => graph.updateData(next))
Use tree.render(data) only for the first render, since it also builds the toolbar and other chrome. updateData falls back to a full rebuild when animation is disabled or before the first render has settled, so the end state is identical either way. See Live Data Updates.
Batch expand and collapse
Each of these runs as a single reflow, so the whole set springs together in one wave rather than one render per node.
| Method | Description |
|---|---|
expandAll() | Expand every node at once. No-op if nothing is collapsed |
collapseAll() | Collapse every node, leaving only the root visible |
expandToDepth(depth) | Show the tree down to depth (root = 0); nodes at or below it collapse |
expandSubtree(nodeId) | Expand a node and every one of its descendants |
collapseSubtree(nodeId) | Collapse a node and every one of its descendants |
graph.expandToDepth(1) // root plus its direct children
graph.expandSubtree('eng')
graph.collapseAll()
collapseAll() leaves each level's own collapsed state intact, so a later expand reveals one level at a time.
Focus mode and the active path
See Focus Mode and the Active Path.
| Method | Description |
|---|---|
focus(nodeId) | Spotlight a node's lineage and subtree, dim the rest, spring the camera to frame it. Returns false when the node is unknown or not currently rendered |
clearFocus() | Remove the spotlight and spring the camera back to the whole tree |
getFocusedNodeId() | Id of the spotlighted node, or null when focus mode is inactive |
setActivePath(nodeIds) | Flow a marching dash along the lineage from the root to each given node. Accepts one id or a list; an empty list clears |
clearActivePath() | Clear the flow, restoring edges to their normal styling |
getActivePath() | The node ids whose lineage is currently flowing, or [] |
graph.focus('eng')
graph.setActivePath('ada') // root → ada
graph.setActivePath(['ada', 'kai']) // both lineages
graph.clearActivePath()
graph.clearFocus()
Focus survives collapse, expand and layout changes as long as the node stays rendered. The active path is re-asserted after every render, so it survives collapse and expand too.
Expandable cards
A card expanding in place is distinct from expanding a node's children. See Node Sizing and Expandable Cards.
| Method | Description |
|---|---|
expandCard(nodeId) | Expand a node's card to reveal its detail section |
collapseCard(nodeId) | Collapse a node's expanded card |
toggleCard(nodeId) | Toggle a node's expanded card |
setExpandedCards(nodeIds) | Replace the set of expanded cards wholesale and reflow once |
getExpandedCards() | Ids of every currently expanded card, or [] |
graph.toggleCard('alice')
graph.setExpandedCards(['alice', 'bob'])
These work whether or not cardExpansion.clickToExpand is set. Expanding only grows the card when its height can change, so pair it with autoNodeHeight.
Selection
Requires enableSelection to be 'single' or 'multi'. See the Selection guide.
| Method | Description |
|---|---|
getSelection() | Return the selected node ids in insertion order (empty when none/disabled) |
setSelection(ids) | Replace the selection. In 'single' mode only the first id applies |
clearSelection() | Clear the current selection |
onSelectionChange(listener) | Register a listener called with the new id array on every change; pass null to unregister |
graph.onSelectionChange((ids) => {
console.log('Selected:', ids)
})
graph.setSelection(['vp1'])
const selected = graph.getSelection()
graph.clearSelection()
Search and traversal
See the Search and Breadcrumbs guide.
| Method | Description |
|---|---|
findNodesByQuery(query) | Return every node id whose resolved label contains query (case-insensitive) |
setSearchHighlight(matchIds) | Highlight matches and their lineage to root; pass [] to clear |
getNodeLabel(nodeId) | Resolve the display label for a node |
getNodeMap() | Return the resolved node map for external traversal |
getRootNodeId() | Return the root node id of the current tree |
const matches = graph.findNodesByQuery('bob')
graph.setSearchHighlight(matches)
if (matches.length) graph.centerOnNode(matches[0])
Breadcrumb
| Method | Description |
|---|---|
setBreadcrumbHandler(handler) | Register a callback invoked with the node id on every node click; pass null to clear |
graph.setBreadcrumbHandler((nodeId) => {
console.log('Clicked:', nodeId)
})
Localization
| Method | Description |
|---|---|
getMessages() | Return the resolved, localized strings for this chart (English defaults merged with locale.messages) |
getIsRtl() | Return whether the current locale.direction resolves to right-to-left |
const messages = graph.getMessages()
const rtl = graph.getIsRtl()
Export
| Method | Description |
|---|---|
exportToSvg() | Export the current tree as an SVG file (triggers a download) |
See the Zoom, Pan and Export guide.
Full example
import { ApexTree } from 'apextree'
const tree = new ApexTree(document.getElementById('chart'), {
direction: 'top',
nodeWidth: 140,
nodeHeight: 50,
enableSelection: 'multi',
enableToolbar: true,
})
const graph = tree.render(data)
// wire external controls
document.getElementById('expand-all').onclick = () => graph.expand(graph.getRootNodeId())
document.getElementById('fit').onclick = () => graph.fitScreen()
document.getElementById('export').onclick = () => graph.exportToSvg()
graph.onSelectionChange((ids) => updatePanel(ids))
React
The React wrapper exposes a subset of the Graph API through a ref, plus getGraph() for the full instance:
import { useRef } from 'react'
import { ApexTreeChart } from 'react-apextree'
import type { ApexTreeRef } from 'react-apextree'
export default function OrgChart() {
const ref = useRef<ApexTreeRef>(null)
return (
<div>
<button onClick={() => ref.current?.changeLayout('left')}>Left</button>
<button onClick={() => ref.current?.fitScreen()}>Fit</button>
<button onClick={() => ref.current?.getGraph()?.exportToSvg()}>Export</button>
<ApexTreeChart ref={ref} data={data} options={{ direction: 'top' }} />
</div>
)
}
The ApexTreeRef handle exposes changeLayout(), collapse(), expand(), fitScreen(), and getGraph() (which returns the full Graph instance for zoom, exportToSvg, selection, and search).