Data Format
ApexTree renders from a single root NestedNode. Each node declares its id, display name, and an array of children. Children nest recursively to any depth.
NestedNode structure
const data = {
id: 'ceo',
name: 'Alice Johnson',
children: [
{
id: 'cto',
name: 'Bob Smith',
children: [
{ id: 'eng1', name: 'Carol Lee', children: [] },
{ id: 'eng2', name: 'Dan Park', children: [] },
],
},
{
id: 'cfo',
name: 'Eve Torres',
children: [],
},
],
}
const tree = new ApexTree(document.getElementById('chart'), {})
tree.render(data)
Node fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier, stable across renders |
name | string | Yes | Display label rendered inside the node |
children | NestedNode[] | Yes | Child nodes; use [] for a leaf |
data | T | No | Arbitrary payload attached to the node, available in callbacks |
options | object | No | Per-node overrides for font, node, and tooltip options |
Leaf nodes must still declare children: [].
contentKey
By default the node displays the value at the name key. Set contentKey in the chart options to point the label at a different field:
const data = {
id: 'ceo',
label: 'Alice Johnson', // custom field
children: [],
}
const tree = new ApexTree(el, {
contentKey: 'label', // read the label from 'label' instead of 'name'
})
tree.render(data)
contentKey can also point at a nested object — the built-in card template and OrgNodeData (below) rely on this.
Attaching custom data
Use the data field to carry arbitrary information. It is passed through to onNodeClick and is available on the resolved node map:
const data = {
id: 'ceo',
name: 'Alice',
data: { email: 'alice@example.com', department: 'Executive' },
children: [],
}
const tree = new ApexTree(el, {
onNodeClick: (node) => {
console.log(node.data.email)
},
})
tree.render(data)
Per-node option overrides
Any node can override font, node, and tooltip options via its options field. These layer on top of the global chart options for that node only:
const data = {
id: 'ceo',
name: 'Alice',
options: {
nodeBGColor: '#EEF2FF',
borderColor: '#6366F1',
fontWeight: '700',
},
children: [
{
id: 'cto',
name: 'Bob',
options: {
nodeBGColor: '#F0FDF4',
borderColor: '#22C55E',
},
children: [],
},
],
}
Per-node options accept the same keys as the font, node, and tooltip option groups.
Rich org-chart cards with OrgNodeData
For a professional org-chart card (avatar, name, title, subtitle, status chip, accent stripe), point contentKey at a data field holding an OrgNodeData object. The built-in node template understands its shape.
const data = {
id: 'ceo',
name: 'Alice Johnson',
data: {
name: 'Alice Johnson',
title: 'Chief Executive Officer',
subtitle: 'Executive Team',
imageURL: '/avatars/alice.jpg',
accentColor: '#6366F1',
badge: { text: 'Active', color: '#22C55E' },
meta: [
{ icon: 'bi bi-envelope', label: 'alice@example.com' },
{ icon: 'bi bi-geo-alt', label: 'San Francisco' },
],
},
children: [],
}
const tree = new ApexTree(el, {
contentKey: 'data', // read the card fields from the 'data' object
nodeWidth: 240,
nodeHeight: 100,
})
tree.render(data)
OrgNodeData fields
| Field | Type | Description |
|---|---|---|
name | string | Primary display label (line 1) |
title | string | Job title (line 2, medium, lower contrast) |
subtitle | string | Department or team (line 3, smaller) |
imageURL | string | Avatar URL, rendered as a circular image |
accentColor | string | Colored left stripe on the card |
badge | { text, color? } | Status chip in the upper-right corner |
meta | { icon?, label }[] | Extra metadata rows (icon + label lines) |
All fields are optional. Supplying only name renders a simple centered label, so existing simple trees are unaffected. icon is an optional CSS class for an icon font (e.g. Bootstrap Icons 'bi bi-person').
For fully custom rendering beyond OrgNodeData, use a custom node template.
TypeScript
NestedNode is generic over the data payload type:
import type { NestedNode } from 'apextree'
interface EmployeeData {
email: string
department: string
}
const data: NestedNode<EmployeeData> = {
id: 'ceo',
name: 'Alice',
data: { email: 'alice@example.com', department: 'Executive' },
children: [],
}