Custom Node Templates
By default ApexTree renders each node's name inside a simple card. Supply a nodeTemplate function to render arbitrary HTML inside every node instead.
nodeTemplate basics
nodeTemplate receives the node's resolved content (the value at contentKey) and returns an HTML string. The HTML is rendered inside an SVG <foreignObject>.
const tree = new ApexTree(document.getElementById('chart'), {
nodeWidth: 160,
nodeHeight: 60,
nodeTemplate: (content) => `
<div style="display:flex;align-items:center;justify-content:center;
height:100%;font-weight:600;">
${content}
</div>
`,
})
tree.render(data)
The content argument
content is whatever contentKey points at on the node. With the default contentKey: 'name', it is the node's name string. Point contentKey at a data object to pass a richer payload:
const data = {
id: 'ceo',
name: 'Alice',
data: { name: 'Alice Johnson', title: 'CEO', avatar: '/alice.jpg' },
children: [],
}
const tree = new ApexTree(el, {
contentKey: 'data', // content is now the data object
nodeWidth: 220,
nodeHeight: 84,
nodeTemplate: (content) => `
<div style="display:flex;align-items:center;gap:12px;padding:0 12px;height:100%;">
<img src="${content.avatar}" style="width:40px;height:40px;border-radius:50%;" />
<div style="display:flex;flex-direction:column;">
<span style="font-weight:600;">${content.name}</span>
<span style="font-size:12px;color:#64748B;">${content.title}</span>
</div>
</div>
`,
})
tree.render(data)
The context argument
The second argument carries layout-level settings so templates can adapt without reading globals:
| Field | Type | Description |
|---|---|---|
direction | TreeDirection | The tree's growth direction |
cardImagePosition | 'left' | 'top' | Where the built-in card places the avatar |
nodeTemplate: (content, context) => {
const stack = context.cardImagePosition === 'top' ? 'column' : 'row'
return `
<div style="display:flex;flex-direction:${stack};align-items:center;
gap:8px;height:100%;justify-content:center;">
<img src="${content.avatar}" style="width:36px;height:36px;border-radius:50%;" />
<span style="font-weight:600;">${content.name}</span>
</div>
`
}
Safari foreignObject caveats
Because templates render inside a <foreignObject> under a scaled viewBox, certain CSS properties trigger a Safari paint bug where content collapses to the SVG origin. Avoid these on template elements:
position(relative / absolute / fixed / sticky)opacity< 1transformfilterz-indexwill-changemix-blend-modeisolation: isolate
Use flex/grid layout with DOM order and color-based dimming instead. ApexTree logs a one-time console.warn if a template trips this.
// Avoid: <div style="position:relative;opacity:0.8;transform:scale(1.1)">
// Prefer: <div style="display:flex;color:#94A3B8">
Built-in org card (OrgNodeData)
Before writing a custom template, consider the built-in card. Point contentKey at an OrgNodeData object and ApexTree renders a professional card (avatar, name, title, subtitle, status chip, accent stripe) with no template code. See Data Format.
cardImagePosition controls where the built-in card places the avatar:
const tree = new ApexTree(el, {
contentKey: 'data',
cardImagePosition: 'top', // avatar above the text ('left' by default)
nodeWidth: 200,
nodeHeight: 120,
})
Per-node templates via node options
A custom nodeTemplate set globally applies to every node. To vary a single node, override font, node, and tooltip options through that node's options field (see Data Format). For entirely different markup per node, branch inside the global template on the content.
React example
import { ApexTreeChart } from 'react-apextree'
const options = {
contentKey: 'data',
nodeWidth: 220,
nodeHeight: 84,
nodeTemplate: (content: any) => `
<div style="display:flex;align-items:center;gap:12px;padding:0 12px;height:100%">
<img src="${content.avatar}" style="width:40px;height:40px;border-radius:50%" />
<div style="display:flex;flex-direction:column">
<span style="font-weight:600">${content.name}</span>
<span style="font-size:12px;color:#64748B">${content.title}</span>
</div>
</div>
`,
}
export default function TemplatedTree() {
return <ApexTreeChart data={data} options={options} />
}