0
# Data Trees
1
2
Hierarchical data tree functionality for displaying nested data structures with expandable/collapsible parent-child relationships and custom tree controls.
3
4
## Capabilities
5
6
### Tree Configuration
7
8
Configure hierarchical data display with parent-child relationships and tree controls.
9
10
```javascript { .api }
11
interface DataTreeOptions {
12
dataTree?: boolean;
13
dataTreeFilter?: boolean;
14
dataTreeSort?: boolean;
15
dataTreeElementColumn?: string | false;
16
dataTreeBranchElement?: boolean | string | HTMLElement;
17
dataTreeChildIndent?: number;
18
dataTreeChildField?: string;
19
dataTreeCollapseElement?: string | HTMLElement | false;
20
dataTreeExpandElement?: string | HTMLElement | false;
21
dataTreeStartExpanded?: boolean | Function | boolean[];
22
dataTreeChildColumnCalcs?: boolean;
23
dataTreeSelectPropagate?: boolean;
24
}
25
```
26
27
### Row Tree Methods
28
29
Tree-specific methods added to RowComponent for managing hierarchical relationships.
30
31
```javascript { .api }
32
// Added to RowComponent by DataTree module
33
/**
34
* Collapse this tree row and hide its children
35
*/
36
treeCollapse(): void;
37
38
/**
39
* Expand this tree row and show its children
40
*/
41
treeExpand(): void;
42
43
/**
44
* Toggle expansion state of this tree row
45
*/
46
treeToggle(): void;
47
48
/**
49
* Get the parent row in the tree hierarchy
50
* @returns Parent RowComponent or false if top-level
51
*/
52
getTreeParent(): RowComponent | false;
53
54
/**
55
* Get all direct child rows in the tree
56
* @returns Array of child RowComponent objects
57
*/
58
getTreeChildren(): RowComponent[];
59
60
/**
61
* Add a new child row to this tree row
62
* @param data - Data for the new child row
63
* @param pos - Position to insert (true for top, false for bottom)
64
* @param index - Index to insert before
65
* @returns Promise resolving to new RowComponent
66
*/
67
addTreeChild(data: any, pos?: boolean, index?: any): Promise<RowComponent>;
68
69
/**
70
* Check if this tree row is currently expanded
71
* @returns True if expanded, false if collapsed
72
*/
73
isTreeExpanded(): boolean;
74
```
75
76
**Usage Examples:**
77
78
```javascript
79
import { Tabulator } from "tabulator-tables";
80
81
// Basic tree structure
82
const treeData = [
83
{
84
name: "Engineering",
85
employees: 15,
86
_children: [
87
{
88
name: "Frontend Team",
89
employees: 8,
90
_children: [
91
{ name: "Alice Johnson", role: "Senior Developer", employees: 1 },
92
{ name: "Bob Smith", role: "Developer", employees: 1 },
93
{ name: "Carol White", role: "UI/UX Designer", employees: 1 }
94
]
95
},
96
{
97
name: "Backend Team",
98
employees: 7,
99
_children: [
100
{ name: "David Brown", role: "Tech Lead", employees: 1 },
101
{ name: "Eve Davis", role: "Senior Developer", employees: 1 },
102
{ name: "Frank Wilson", role: "DevOps Engineer", employees: 1 }
103
]
104
}
105
]
106
},
107
{
108
name: "Sales",
109
employees: 12,
110
_children: [
111
{ name: "Grace Miller", role: "Sales Manager", employees: 1 },
112
{ name: "Henry Taylor", role: "Account Executive", employees: 1 },
113
{ name: "Ivy Anderson", role: "Sales Rep", employees: 1 }
114
]
115
}
116
];
117
118
// Table with tree functionality
119
const table = new Tabulator("#tree-table", {
120
data: treeData,
121
columns: [
122
{
123
title: "Name",
124
field: "name",
125
width: 300,
126
formatter: "plaintext"
127
},
128
{
129
title: "Role/Department",
130
field: "role",
131
formatter: function(cell, formatterParams) {
132
return cell.getValue() || cell.getRow().getData().name;
133
}
134
},
135
{
136
title: "Employees",
137
field: "employees",
138
width: 100,
139
align: "right"
140
}
141
],
142
dataTree: true,
143
dataTreeStartExpanded: true,
144
dataTreeChildField: "_children",
145
dataTreeChildIndent: 15,
146
dataTreeElementColumn: "name"
147
});
148
149
// Programmatic tree operations
150
const firstRow = table.getRows()[0];
151
152
// Collapse a tree row
153
firstRow.treeCollapse();
154
155
// Expand a tree row
156
firstRow.treeExpand();
157
158
// Toggle expansion state
159
firstRow.treeToggle();
160
161
// Check expansion state
162
if (firstRow.isTreeExpanded()) {
163
console.log("Row is expanded");
164
}
165
166
// Get tree relationships
167
const children = firstRow.getTreeChildren();
168
console.log(`This row has ${children.length} children`);
169
170
children.forEach(child => {
171
const parent = child.getTreeParent();
172
console.log(`Child row parent: ${parent ? parent.getData().name : 'none'}`);
173
});
174
175
// Add new child
176
firstRow.addTreeChild({
177
name: "Quality Assurance Team",
178
employees: 5,
179
_children: [
180
{ name: "Jack Lee", role: "QA Lead", employees: 1 },
181
{ name: "Kate Green", role: "QA Engineer", employees: 1 }
182
]
183
});
184
```
185
186
## Tree Configuration Options
187
188
### Child Field Configuration
189
190
Specify which field contains child data in your data structure.
191
192
```javascript
193
const table = new Tabulator("#table", {
194
dataTree: true,
195
dataTreeChildField: "_children", // Default field name
196
// ... other options
197
});
198
199
// Alternative field names
200
dataTreeChildField: "children" // Use "children" field
201
dataTreeChildField: "subItems" // Use "subItems" field
202
dataTreeChildField: "nested" // Use "nested" field
203
```
204
205
### Visual Customization
206
207
Customize tree appearance with custom elements and indentation.
208
209
```javascript
210
const table = new Tabulator("#table", {
211
dataTree: true,
212
dataTreeChildIndent: 20, // Indent child rows by 20px
213
dataTreeBranchElement: true, // Show default branch lines
214
dataTreeElementColumn: "name", // Column to show tree controls in
215
216
// Custom collapse/expand buttons
217
dataTreeCollapseElement: "<span>▼</span>",
218
dataTreeExpandElement: "<span>▶</span>",
219
220
// Custom branch element
221
dataTreeBranchElement: "<div class='custom-branch'></div>"
222
});
223
```
224
225
### Expansion State Management
226
227
Control which tree rows start expanded or collapsed.
228
229
```javascript
230
// All rows start expanded
231
const table = new Tabulator("#table", {
232
dataTree: true,
233
dataTreeStartExpanded: true
234
});
235
236
// All rows start collapsed
237
const table2 = new Tabulator("#table2", {
238
dataTree: true,
239
dataTreeStartExpanded: false
240
});
241
242
// Conditional expansion using function
243
const table3 = new Tabulator("#table3", {
244
dataTree: true,
245
dataTreeStartExpanded: function(row, level) {
246
// Expand top-level rows, collapse deeper levels
247
return level < 2;
248
}
249
});
250
251
// Specific expansion levels using array
252
const table4 = new Tabulator("#table4", {
253
dataTree: true,
254
dataTreeStartExpanded: [true, true, false] // Expand levels 0,1 but not 2+
255
});
256
```
257
258
## Advanced Tree Features
259
260
### Tree Filtering and Sorting
261
262
Configure how child rows are handled in filtering and sorting operations.
263
264
```javascript
265
const table = new Tabulator("#table", {
266
dataTree: true,
267
dataTreeFilter: true, // Include child rows in filtering
268
dataTreeSort: true, // Include child rows in sorting
269
270
// Child row calculations
271
dataTreeChildColumnCalcs: true, // Include visible children in calculations
272
273
// Selection propagation
274
dataTreeSelectPropagate: true, // Selecting parent selects children
275
});
276
```
277
278
### Dynamic Tree Operations
279
280
Dynamically modify tree structure after table creation.
281
282
```javascript
283
// Add children to existing rows
284
const parentRow = table.getRow(1);
285
await parentRow.addTreeChild({
286
name: "New Team Member",
287
role: "Junior Developer",
288
employees: 1
289
});
290
291
// Traverse tree programmatically
292
function traverseTree(row, level = 0) {
293
const indent = " ".repeat(level);
294
console.log(`${indent}${row.getData().name}`);
295
296
const children = row.getTreeChildren();
297
children.forEach(child => {
298
traverseTree(child, level + 1);
299
});
300
}
301
302
// Traverse all top-level rows
303
table.getRows().forEach(row => {
304
if (!row.getTreeParent()) {
305
traverseTree(row);
306
}
307
});
308
309
// Batch tree operations
310
const engineeringTeam = table.getRows().find(row =>
311
row.getData().name === "Engineering"
312
);
313
314
if (engineeringTeam) {
315
// Collapse all children
316
engineeringTeam.getTreeChildren().forEach(child => {
317
child.treeCollapse();
318
});
319
320
// Then expand the parent
321
engineeringTeam.treeExpand();
322
}
323
```
324
325
### Tree Events
326
327
Handle tree-specific events for user interactions.
328
329
```javascript
330
// Tree expansion/collapse events
331
table.on("dataTreeRowExpanded", function(row, level) {
332
console.log(`Row expanded: ${row.getData().name} at level ${level}`);
333
});
334
335
table.on("dataTreeRowCollapsed", function(row, level) {
336
console.log(`Row collapsed: ${row.getData().name} at level ${level}`);
337
});
338
339
// Custom tree button handling
340
table.on("rowClick", function(e, row) {
341
// Check if click was on tree control
342
if (e.target.closest('.tabulator-data-tree-control')) {
343
row.treeToggle();
344
}
345
});
346
```
347
348
## Tree Data Structures
349
350
### Nested Object Structure
351
352
Standard hierarchical data with child arrays.
353
354
```javascript
355
const nestedData = [
356
{
357
id: 1,
358
name: "Parent 1",
359
_children: [
360
{
361
id: 2,
362
name: "Child 1.1",
363
_children: [
364
{ id: 3, name: "Grandchild 1.1.1" },
365
{ id: 4, name: "Grandchild 1.1.2" }
366
]
367
},
368
{ id: 5, name: "Child 1.2" }
369
]
370
}
371
];
372
```
373
374
### Flat Data with Parent References
375
376
Transform flat data with parent references into tree structure.
377
378
```javascript
379
const flatData = [
380
{ id: 1, name: "Parent 1", parentId: null },
381
{ id: 2, name: "Child 1.1", parentId: 1 },
382
{ id: 3, name: "Child 1.2", parentId: 1 },
383
{ id: 4, name: "Grandchild 1.1.1", parentId: 2 }
384
];
385
386
// Transform to nested structure
387
function buildTree(flatData) {
388
const tree = [];
389
const lookup = {};
390
391
// Create lookup map
392
flatData.forEach(item => {
393
lookup[item.id] = { ...item, _children: [] };
394
});
395
396
// Build tree structure
397
flatData.forEach(item => {
398
if (item.parentId === null) {
399
tree.push(lookup[item.id]);
400
} else {
401
lookup[item.parentId]._children.push(lookup[item.id]);
402
}
403
});
404
405
return tree;
406
}
407
408
const treeData = buildTree(flatData);
409
```
410
411
## Types
412
413
```javascript { .api }
414
interface TreeRowData {
415
[key: string]: any;
416
_children?: TreeRowData[];
417
}
418
419
interface DataTreeOptions {
420
dataTree?: boolean;
421
dataTreeFilter?: boolean;
422
dataTreeSort?: boolean;
423
dataTreeElementColumn?: string | false;
424
dataTreeBranchElement?: boolean | string | HTMLElement;
425
dataTreeChildIndent?: number;
426
dataTreeChildField?: string;
427
dataTreeCollapseElement?: string | HTMLElement | false;
428
dataTreeExpandElement?: string | HTMLElement | false;
429
dataTreeStartExpanded?: boolean | Function | boolean[];
430
dataTreeChildColumnCalcs?: boolean;
431
dataTreeSelectPropagate?: boolean;
432
}
433
434
interface TreeStartExpandedFunction {
435
(row: RowComponent, level: number): boolean;
436
}
437
```