@ticatec/uniface-element 0.3.16 → 0.3.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/TreeNode_README.md +247 -119
- package/dist/lib/TreeNode_README_CN.md +248 -120
- package/dist/lib/TreeNodes.d.ts +339 -85
- package/dist/lib/TreeNodes.js +376 -206
- package/dist/lib/index.d.ts +3 -4
- package/dist/lib/index.js +1 -2
- package/dist/nav-menu/Menus.d.ts +2 -2
- package/dist/nav-menu/Menus.js +6 -4
- package/dist/ticatec-uniface-web.css +29 -5
- package/dist/tree-view/README.md +131 -6
- package/dist/tree-view/TreeNodeView.svelte +13 -11
- package/dist/tree-view/TreeNodeView.svelte.d.ts +5 -5
- package/dist/tree-view/TreeView.svelte +25 -8
- package/dist/tree-view/TreeView.svelte.d.ts +3 -2
- package/dist/tree-view/Types.d.ts +4 -4
- package/dist/tree-view/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -2,52 +2,88 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
`TreeNode` is
|
|
5
|
+
`TreeNode` is a class that represents nodes in a tree structure. It encapsulates the node's data, child nodes, expansion state, and provides convenient methods to manipulate the node itself and its children.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Each node created from `TreeNodes` or `CommonTreeNodes` is an instance of the `TreeNode` class with built-in methods.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## TreeNode Class
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
|
-
|
|
13
|
-
/** The node's data object */
|
|
14
|
-
item: T;
|
|
12
|
+
class TreeNode<T> {
|
|
13
|
+
/** The node's data object (readonly) */
|
|
14
|
+
public readonly item: T;
|
|
15
15
|
|
|
16
16
|
/** Whether the node is expanded (showing children) */
|
|
17
|
-
expand
|
|
17
|
+
public expand: boolean;
|
|
18
18
|
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
```
|
|
19
|
+
/** Whether the node is currently loading (for lazy loading) */
|
|
20
|
+
public loading: boolean;
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
/** Parent node (null for root nodes) */
|
|
23
|
+
public parent: TreeNode<T> | null;
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
/** Child nodes (readonly, use methods to modify) */
|
|
26
|
+
get children(): ReadonlyArray<TreeNode<T>>;
|
|
27
27
|
|
|
28
|
-
```typescript
|
|
29
|
-
interface TreeNodeWithMethods<T> extends TreeNode<T> {
|
|
30
28
|
/** Add a child node to the current node */
|
|
31
|
-
append
|
|
29
|
+
append(childItem: T): void;
|
|
32
30
|
|
|
33
31
|
/** Remove the current node (from its parent) */
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
/** Replace the current node's data */
|
|
37
|
-
replace: (newItem: T) => void;
|
|
32
|
+
detach(): void;
|
|
38
33
|
|
|
39
34
|
/** Move the current node to a different parent */
|
|
40
|
-
moveTo
|
|
35
|
+
moveTo(newParent: TreeNode<T>): void;
|
|
36
|
+
|
|
37
|
+
/** Replace the current node's data */
|
|
38
|
+
replace(newItem: T): void;
|
|
41
39
|
|
|
42
|
-
/** Remove a specific child node */
|
|
43
|
-
removeChild
|
|
40
|
+
/** Remove a specific child node by ID */
|
|
41
|
+
removeChild(childId: any): void;
|
|
44
42
|
|
|
45
43
|
/** Remove all child nodes */
|
|
46
|
-
removeChildren
|
|
44
|
+
removeChildren(): void;
|
|
47
45
|
}
|
|
48
46
|
```
|
|
49
47
|
|
|
50
|
-
##
|
|
48
|
+
## NodeViewOptions Class
|
|
49
|
+
|
|
50
|
+
The `NodeViewOptions` class handles view configuration for tree nodes, separating display concerns from data:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
class NodeViewOptions<T> {
|
|
54
|
+
/** Field name for unique identifier */
|
|
55
|
+
keyField: keyof T;
|
|
56
|
+
|
|
57
|
+
/** Field name or function for display text */
|
|
58
|
+
textField: keyof T | ((data: T) => string);
|
|
59
|
+
|
|
60
|
+
/** Optional: Field name or function for icon */
|
|
61
|
+
iconField?: keyof T | ((data: T) => string);
|
|
62
|
+
|
|
63
|
+
/** Optional: Field name or function for CSS class */
|
|
64
|
+
cssClassField?: keyof T | ((data: T) => string);
|
|
65
|
+
|
|
66
|
+
/** Optional: Field name or function for inline styles */
|
|
67
|
+
styleField?: keyof T | ((data: T) => Record<string, string>);
|
|
68
|
+
|
|
69
|
+
/** Get display text from data */
|
|
70
|
+
getText(data: T): string;
|
|
71
|
+
|
|
72
|
+
/** Get icon from data */
|
|
73
|
+
getIcon(data: T): string | undefined;
|
|
74
|
+
|
|
75
|
+
/** Get CSS class from data */
|
|
76
|
+
getCssClass(data: T): string | undefined;
|
|
77
|
+
|
|
78
|
+
/** Get styles from data */
|
|
79
|
+
getStyle(data: T): Record<string, string> | undefined;
|
|
80
|
+
|
|
81
|
+
/** Get unique key from data */
|
|
82
|
+
getKey(data: T): any;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## TreeNode Methods
|
|
51
87
|
|
|
52
88
|
### 1. append(childItem)
|
|
53
89
|
|
|
@@ -62,33 +98,31 @@ Add a child node to the current node.
|
|
|
62
98
|
parentNode.append({
|
|
63
99
|
id: 123,
|
|
64
100
|
name: "New Child",
|
|
65
|
-
|
|
101
|
+
parentId: parentNode.item.id // Will be set automatically
|
|
66
102
|
});
|
|
67
103
|
```
|
|
68
104
|
|
|
69
105
|
**Notes**:
|
|
70
|
-
-
|
|
71
|
-
- **Manually add child nodes**: You can manually call `append()` to add child nodes
|
|
72
|
-
- If the node is not yet loaded, it will automatically initialize the `children` array
|
|
73
|
-
- The node will transition from leaf to branch, UI will display the branch icon
|
|
106
|
+
- Automatically initializes children array if needed
|
|
74
107
|
- If a sort function is configured, nodes will be automatically sorted
|
|
75
108
|
- The parent's `expand` is automatically set to `true`
|
|
109
|
+
- Triggers version update for reactive updates
|
|
76
110
|
|
|
77
111
|
---
|
|
78
112
|
|
|
79
|
-
### 2.
|
|
113
|
+
### 2. detach()
|
|
80
114
|
|
|
81
|
-
Remove the current node
|
|
115
|
+
Remove the current node from its parent.
|
|
82
116
|
|
|
83
117
|
**Parameter**: None
|
|
84
118
|
|
|
85
119
|
**Example**:
|
|
86
120
|
```typescript
|
|
87
|
-
// Remove the node
|
|
88
|
-
node.
|
|
121
|
+
// Remove the node from its parent
|
|
122
|
+
node.detach();
|
|
89
123
|
|
|
90
124
|
// Clear reference after removal
|
|
91
|
-
activeNode.
|
|
125
|
+
activeNode.detach();
|
|
92
126
|
activeNode = null;
|
|
93
127
|
```
|
|
94
128
|
|
|
@@ -96,10 +130,40 @@ activeNode = null;
|
|
|
96
130
|
- Removes from parent's `children` array
|
|
97
131
|
- Deletes from internal map
|
|
98
132
|
- If it's a root node, removes from root node list
|
|
133
|
+
- Triggers version update for reactive updates
|
|
99
134
|
|
|
100
135
|
---
|
|
101
136
|
|
|
102
|
-
### 3.
|
|
137
|
+
### 3. moveTo(newParent)
|
|
138
|
+
|
|
139
|
+
Move the current node to a different parent node.
|
|
140
|
+
|
|
141
|
+
**Parameter**:
|
|
142
|
+
- `newParent: TreeNode<T>` - The new parent node (not an ID)
|
|
143
|
+
|
|
144
|
+
**Example**:
|
|
145
|
+
```typescript
|
|
146
|
+
// Move to a different parent node
|
|
147
|
+
node.moveTo(newParentNode);
|
|
148
|
+
|
|
149
|
+
// Get parent node first
|
|
150
|
+
const parentNode = treeNodes.nodeMap.get(parentId);
|
|
151
|
+
if (parentNode) {
|
|
152
|
+
node.moveTo(parentNode);
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Notes**:
|
|
157
|
+
- Takes a TreeNode instance, not an ID
|
|
158
|
+
- Automatically updates the node's `parentKeyField` in data
|
|
159
|
+
- Removes from current parent's `children`
|
|
160
|
+
- Adds to new parent's `children`
|
|
161
|
+
- If a sort function is configured, will automatically re-sort
|
|
162
|
+
- Triggers version update for reactive updates
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### 4. replace(newItem)
|
|
103
167
|
|
|
104
168
|
Replace the current node's data.
|
|
105
169
|
|
|
@@ -127,32 +191,7 @@ node.replace({
|
|
|
127
191
|
- Usually need to keep the `id` field unchanged
|
|
128
192
|
- If a sort function is configured and sort field changes, will automatically re-sort
|
|
129
193
|
- Automatically triggers view update
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
### 4. moveTo(newParentId)
|
|
134
|
-
|
|
135
|
-
Move the current node to a different parent.
|
|
136
|
-
|
|
137
|
-
**Parameter**:
|
|
138
|
-
- `newParentId: string | number` - New parent node's ID
|
|
139
|
-
|
|
140
|
-
**Example**:
|
|
141
|
-
```typescript
|
|
142
|
-
// Move to specified parent
|
|
143
|
-
node.moveTo("parent-123");
|
|
144
|
-
|
|
145
|
-
// Use another node's ID
|
|
146
|
-
node.moveTo(anotherNode.item.id);
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
**Notes**:
|
|
150
|
-
- Automatically updates the node's `parent` field
|
|
151
|
-
- Removes from current parent's `children`
|
|
152
|
-
- Adds to new parent's `children`
|
|
153
|
-
- **Lazy node handling**: If the new parent is lazy-loaded and not loaded (`children === null`), it will automatically initialize the `children` array
|
|
154
|
-
- The new parent will transition from leaf to branch, UI will display the branch icon
|
|
155
|
-
- When the user expands the node later, the lazyLoader will load child nodes that merge with manually added nodes
|
|
194
|
+
- Preserves children, expand state, and loading state
|
|
156
195
|
|
|
157
196
|
---
|
|
158
197
|
|
|
@@ -177,6 +216,7 @@ parentNode.removeChild(childId);
|
|
|
177
216
|
- Only removes direct children, not grandchildren recursively
|
|
178
217
|
- Silently ignores if child doesn't exist
|
|
179
218
|
- All descendants of the child node are also removed
|
|
219
|
+
- Triggers version update for reactive updates
|
|
180
220
|
|
|
181
221
|
---
|
|
182
222
|
|
|
@@ -200,37 +240,68 @@ parentNode.append(newChildData);
|
|
|
200
240
|
- Removes all children and their descendants
|
|
201
241
|
- Node's `expand` state remains unchanged
|
|
202
242
|
- Internal map is updated accordingly
|
|
243
|
+
- Triggers version update for reactive updates
|
|
244
|
+
|
|
245
|
+
## CommonTreeNodes Options
|
|
246
|
+
|
|
247
|
+
When creating a tree, you can configure it with these options:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
interface TreeNodeOptions<T> {
|
|
251
|
+
/** Field name for unique identifier (default: 'id') */
|
|
252
|
+
keyField?: keyof T;
|
|
253
|
+
|
|
254
|
+
/** Field name or function for display text (default: 'text') */
|
|
255
|
+
textField?: keyof T | ((data: T) => string);
|
|
256
|
+
|
|
257
|
+
/** Field name for parent reference (default: 'parentId') */
|
|
258
|
+
parentKeyField?: keyof T;
|
|
259
|
+
|
|
260
|
+
/** Function to check if data is a root node */
|
|
261
|
+
checkIsRoot: (data: T) => boolean;
|
|
262
|
+
|
|
263
|
+
/** Optional: Function to check if node is a branch (has children) */
|
|
264
|
+
checkIsDirectory?: (node: TreeNode<T>) => boolean;
|
|
265
|
+
|
|
266
|
+
/** Optional: Comparison function for sorting */
|
|
267
|
+
compareFun?: (o1: T, o2: T) => number | undefined;
|
|
268
|
+
|
|
269
|
+
/** Optional: Expand depth (default: 1) */
|
|
270
|
+
expendDepth?: number;
|
|
271
|
+
}
|
|
272
|
+
```
|
|
203
273
|
|
|
204
274
|
## Complete Usage Example
|
|
205
275
|
|
|
206
276
|
```svelte
|
|
207
277
|
<script>
|
|
208
278
|
import TreeView from "@ticatec/uniface-element/TreeView";
|
|
209
|
-
import
|
|
279
|
+
import { CommonTreeNodes, type TreeNode } from "@ticatec/uniface-element/lib/TreeNodes";
|
|
210
280
|
|
|
211
281
|
// Data type definition
|
|
212
282
|
interface MyData {
|
|
213
283
|
id: number;
|
|
214
284
|
name: string;
|
|
215
|
-
|
|
285
|
+
parentId: number | null;
|
|
216
286
|
}
|
|
217
287
|
|
|
218
|
-
let activeNode:
|
|
288
|
+
let activeNode: TreeNode<MyData> | null = null;
|
|
219
289
|
|
|
220
290
|
// Create tree structure
|
|
221
|
-
const treeNodes = new
|
|
291
|
+
const treeNodes = new CommonTreeNodes<MyData>({
|
|
222
292
|
keyField: 'id',
|
|
223
293
|
textField: 'name',
|
|
224
|
-
parentKeyField: '
|
|
225
|
-
checkIsRoot: (item) => item.
|
|
226
|
-
checkIsDirectory: (node) => node.children
|
|
294
|
+
parentKeyField: 'parentId',
|
|
295
|
+
checkIsRoot: (item) => item.parentId === null,
|
|
296
|
+
checkIsDirectory: (node) => node.children.length > 0,
|
|
297
|
+
expendDepth: 2
|
|
227
298
|
});
|
|
228
299
|
|
|
229
300
|
// Initialize data
|
|
230
301
|
treeNodes.setData([
|
|
231
|
-
{ id: 1, name: "Root",
|
|
232
|
-
{ id: 2, name: "Child 1",
|
|
233
|
-
{ id: 3, name: "Child 2",
|
|
302
|
+
{ id: 1, name: "Root", parentId: null },
|
|
303
|
+
{ id: 2, name: "Child 1", parentId: 1 },
|
|
304
|
+
{ id: 3, name: "Child 2", parentId: 1 }
|
|
234
305
|
]);
|
|
235
306
|
|
|
236
307
|
// Add child node
|
|
@@ -240,14 +311,14 @@ parentNode.append(newChildData);
|
|
|
240
311
|
activeNode.append({
|
|
241
312
|
id: Date.now(),
|
|
242
313
|
name: "New Child",
|
|
243
|
-
|
|
314
|
+
parentId: activeNode.item.id
|
|
244
315
|
});
|
|
245
316
|
}
|
|
246
317
|
|
|
247
318
|
// Delete current node
|
|
248
319
|
function deleteCurrentNode() {
|
|
249
320
|
if (!activeNode) return;
|
|
250
|
-
activeNode.
|
|
321
|
+
activeNode.detach();
|
|
251
322
|
activeNode = null;
|
|
252
323
|
}
|
|
253
324
|
|
|
@@ -275,7 +346,10 @@ parentNode.append(newChildData);
|
|
|
275
346
|
// Move node
|
|
276
347
|
function moveNodeTo(newParentId: number) {
|
|
277
348
|
if (!activeNode) return;
|
|
278
|
-
|
|
349
|
+
const newParent = treeNodes.nodeMap.get(newParentId);
|
|
350
|
+
if (newParent) {
|
|
351
|
+
activeNode.moveTo(newParent);
|
|
352
|
+
}
|
|
279
353
|
}
|
|
280
354
|
</script>
|
|
281
355
|
|
|
@@ -285,7 +359,7 @@ parentNode.append(newChildData);
|
|
|
285
359
|
version={treeNodes.version}
|
|
286
360
|
textField="name"
|
|
287
361
|
bind:activeNode
|
|
288
|
-
checkIsDirectory={(node) => node.children
|
|
362
|
+
checkIsDirectory={(node) => node.children.length > 0}
|
|
289
363
|
/>
|
|
290
364
|
|
|
291
365
|
{#if activeNode}
|
|
@@ -303,30 +377,64 @@ parentNode.append(newChildData);
|
|
|
303
377
|
|
|
304
378
|
## Difference from TreeNodes Class Methods
|
|
305
379
|
|
|
306
|
-
`TreeNode` methods and `TreeNodes` class methods have clear responsibilities:
|
|
380
|
+
`TreeNode` instance methods and `CommonTreeNodes`/`TreeNodes` class methods have clear responsibilities:
|
|
307
381
|
|
|
308
|
-
### TreeNode
|
|
382
|
+
### TreeNode Instance Methods (For Operating on Specific Node Instances)
|
|
309
383
|
|
|
310
384
|
```typescript
|
|
311
|
-
// Operate directly on
|
|
385
|
+
// Operate directly on a node instance
|
|
312
386
|
node.append(childItem); // Add child to this node
|
|
313
|
-
node.
|
|
387
|
+
node.detach(); // Remove this node from its parent
|
|
314
388
|
node.replace(newItem); // Replace this node's data
|
|
315
|
-
node.moveTo(
|
|
389
|
+
node.moveTo(newParentNode); // Move this node to another parent
|
|
316
390
|
node.removeChild(childId); // Remove specific child
|
|
317
391
|
node.removeChildren(); // Remove all children
|
|
318
392
|
```
|
|
319
393
|
|
|
320
|
-
### TreeNodes Class Methods (For
|
|
394
|
+
### CommonTreeNodes/TreeNodes Class Methods (For Tree-Level Operations)
|
|
321
395
|
|
|
322
396
|
```typescript
|
|
323
|
-
//
|
|
397
|
+
// Tree-level operations
|
|
324
398
|
treeNodes.setData(data); // Initialize tree structure
|
|
325
399
|
treeNodes.append(item); // Add new node (auto-find parent)
|
|
326
400
|
treeNodes.nodes; // Get root node list
|
|
327
401
|
treeNodes.version; // Get version number
|
|
328
|
-
treeNodes.getHierarchyList(); // Get expanded node list
|
|
329
|
-
treeNodes.extractDirectories(item); // Extract directory structure
|
|
402
|
+
treeNodes.getHierarchyList(); // Get expanded node list (TreeNodes only)
|
|
403
|
+
treeNodes.extractDirectories(item); // Extract directory structure (TreeNodes only)
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
## Key Properties
|
|
407
|
+
|
|
408
|
+
### item (readonly)
|
|
409
|
+
The data object stored in the node. Cannot be modified directly. Use `replace()` to update data.
|
|
410
|
+
|
|
411
|
+
### children (readonly)
|
|
412
|
+
Returns a read-only array of child nodes. To modify children, use the methods:
|
|
413
|
+
- `append()` - add a child
|
|
414
|
+
- `removeChild()` - remove a specific child
|
|
415
|
+
- `removeChildren()` - remove all children
|
|
416
|
+
|
|
417
|
+
### expand
|
|
418
|
+
Controls whether the node is expanded (showing its children). Can be set directly:
|
|
419
|
+
```typescript
|
|
420
|
+
node.expand = true; // Expand the node
|
|
421
|
+
node.expand = false; // Collapse the node
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### loading
|
|
425
|
+
Indicates if the node is currently loading data (used for lazy loading). Can be set directly:
|
|
426
|
+
```typescript
|
|
427
|
+
node.loading = true; // Show loading state
|
|
428
|
+
node.loading = false; // Hide loading state
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### parent
|
|
432
|
+
Reference to the parent node. Is `null` for root nodes.
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
if (node.parent) {
|
|
436
|
+
console.log("Parent name:", node.parent.item.name);
|
|
437
|
+
}
|
|
330
438
|
```
|
|
331
439
|
|
|
332
440
|
## Reactive Updates
|
|
@@ -359,10 +467,14 @@ const node = treeNodes.nodeMap.get(nodeId);
|
|
|
359
467
|
### Q: How to iterate over child nodes?
|
|
360
468
|
|
|
361
469
|
```typescript
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
470
|
+
// children is readonly, but you can iterate over it
|
|
471
|
+
node.children.forEach(child => {
|
|
472
|
+
console.log(child.item.name);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
// Or use for...of
|
|
476
|
+
for (const child of node.children) {
|
|
477
|
+
console.log(child.item.name);
|
|
366
478
|
}
|
|
367
479
|
```
|
|
368
480
|
|
|
@@ -370,40 +482,24 @@ if (node.children) {
|
|
|
370
482
|
|
|
371
483
|
```typescript
|
|
372
484
|
function findChild(node: TreeNode, childId: number) {
|
|
373
|
-
if (!node.children) return null;
|
|
374
485
|
return node.children.find(child => child.item.id === childId) || null;
|
|
375
486
|
}
|
|
376
487
|
```
|
|
377
488
|
|
|
378
|
-
### Q:
|
|
379
|
-
|
|
380
|
-
For nodes using lazyLoader (`children === null`):
|
|
381
|
-
|
|
382
|
-
```typescript
|
|
383
|
-
// ✅ When a node is selected, TreeView automatically triggers loading
|
|
384
|
-
// When you click a node or set activeNode:
|
|
385
|
-
// - If it's a lazy node and not loaded
|
|
386
|
-
// - Automatically calls lazyLoader.load()
|
|
387
|
-
// - children is set, node transitions to branch
|
|
388
|
-
|
|
389
|
-
// Manually add child nodes
|
|
390
|
-
lazyNode.append(childItem); // Initialize children array and add child node
|
|
391
|
-
// Node transitions to branch, shows branch icon
|
|
392
|
-
|
|
393
|
-
lazyNode.moveTo(parentId); // Moving to this node will initialize children
|
|
489
|
+
### Q: Can I modify the children array directly?
|
|
394
490
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
491
|
+
No. The `children` property is read-only. Use the provided methods instead:
|
|
492
|
+
- `append()` to add
|
|
493
|
+
- `removeChild()` to remove specific child
|
|
494
|
+
- `removeChildren()` to remove all
|
|
399
495
|
|
|
400
496
|
### Q: How to recursively operate on all descendants?
|
|
401
497
|
|
|
402
498
|
```typescript
|
|
403
499
|
function traverse(node: TreeNode, callback: (node: TreeNode) => void) {
|
|
404
500
|
callback(node);
|
|
405
|
-
|
|
406
|
-
|
|
501
|
+
for (const child of node.children) {
|
|
502
|
+
traverse(child, callback);
|
|
407
503
|
}
|
|
408
504
|
}
|
|
409
505
|
|
|
@@ -414,36 +510,68 @@ traverse(rootNode, (node) => {
|
|
|
414
510
|
});
|
|
415
511
|
```
|
|
416
512
|
|
|
513
|
+
### Q: What's the difference between TreeNode and NodeViewOptions?
|
|
514
|
+
|
|
515
|
+
- **TreeNode**: Represents the data structure. Each node is an instance with methods for manipulation.
|
|
516
|
+
- **NodeViewOptions**: Configuration class for how nodes should be displayed (text field, icon, CSS, etc.)
|
|
517
|
+
|
|
518
|
+
This separation allows TreeNode to be used in different contexts (TreeView, TreeDataGrid, etc.) without coupling to view-specific concerns.
|
|
519
|
+
|
|
417
520
|
## Best Practices
|
|
418
521
|
|
|
419
522
|
1. **Prefer node methods**: When you have a node instance, calling node methods directly is more intuitive
|
|
420
523
|
|
|
421
524
|
2. **Keep ID unchanged**: When using `replace()`, ensure the `id` field remains unchanged
|
|
422
525
|
|
|
423
|
-
3. **
|
|
526
|
+
3. **Use moveTo correctly**: The `moveTo()` method takes a TreeNode instance, not an ID:
|
|
527
|
+
```typescript
|
|
528
|
+
// ❌ Wrong
|
|
529
|
+
node.moveTo(123);
|
|
424
530
|
|
|
425
|
-
|
|
531
|
+
// ✅ Correct
|
|
532
|
+
const parentNode = treeNodes.nodeMap.get(123);
|
|
533
|
+
node.moveTo(parentNode);
|
|
534
|
+
```
|
|
426
535
|
|
|
427
|
-
|
|
536
|
+
4. **Version management**: No need to manually manage versions, node methods update automatically
|
|
428
537
|
|
|
429
|
-
|
|
538
|
+
5. **Type safety**: Use TypeScript generics to ensure type safety
|
|
430
539
|
|
|
431
540
|
```typescript
|
|
432
541
|
// ✅ Recommended: Use generics
|
|
433
|
-
const treeNodes = new
|
|
542
|
+
const treeNodes = new CommonTreeNodes<MyData>({ ... });
|
|
434
543
|
|
|
435
544
|
// Node type is automatically inferred
|
|
436
545
|
node.append({ id: 1, name: "..." }); // Type checking
|
|
437
546
|
```
|
|
438
547
|
|
|
548
|
+
6. **Children is readonly**: Don't try to modify the children array directly. Always use the provided methods.
|
|
549
|
+
|
|
439
550
|
## Performance Considerations
|
|
440
551
|
|
|
441
552
|
- All node methods have O(1) or O(n) time complexity, where n is the number of child nodes
|
|
442
553
|
- Delete operations also remove from internal map to maintain consistency
|
|
443
554
|
- For large batch operations, consider using `setData()` to rebuild the tree structure
|
|
444
555
|
|
|
556
|
+
## Architecture
|
|
557
|
+
|
|
558
|
+
### Decoupling from View
|
|
559
|
+
|
|
560
|
+
TreeNode is designed to be independent of any specific view component:
|
|
561
|
+
- No view-specific logic in TreeNode
|
|
562
|
+
- NodeViewOptions handles view configuration separately
|
|
563
|
+
- Can be used in TreeView, TreeDataGrid, or any other tree-based component
|
|
564
|
+
|
|
565
|
+
### Data Immutability
|
|
566
|
+
|
|
567
|
+
The `item` property is readonly to ensure data integrity:
|
|
568
|
+
- Prevents accidental mutations
|
|
569
|
+
- Makes state changes explicit through `replace()` method
|
|
570
|
+
- Helps with debugging and state tracking
|
|
571
|
+
|
|
445
572
|
## Related Components
|
|
446
573
|
|
|
447
|
-
- `
|
|
574
|
+
- `CommonTreeNodes` - Base tree management class
|
|
575
|
+
- `TreeNodes` - Extended tree management with hierarchy features
|
|
448
576
|
- `TreeView` - Tree view component
|
|
449
|
-
- `
|
|
577
|
+
- `NodeViewOptions` - View configuration class
|