@primevue/mcp 4.5.5 → 5.0.0-rc.2

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.
Files changed (173) hide show
  1. package/LICENSE.md +45 -21
  2. package/README.md +48 -250
  3. package/data/components.json +47269 -0
  4. package/data/llms/components/accordion.md +629 -0
  5. package/data/llms/components/animateonscroll.md +165 -0
  6. package/data/llms/components/autocomplete.md +995 -0
  7. package/data/llms/components/avatar.md +264 -0
  8. package/data/llms/components/badge.md +200 -0
  9. package/data/llms/components/blockui.md +99 -0
  10. package/data/llms/components/breadcrumb.md +269 -0
  11. package/data/llms/components/button.md +902 -0
  12. package/data/llms/components/card.md +209 -0
  13. package/data/llms/components/carousel.md +506 -0
  14. package/data/llms/components/cascadeselect.md +1207 -0
  15. package/data/llms/components/chart.md +1022 -0
  16. package/data/llms/components/checkbox.md +401 -0
  17. package/data/llms/components/chip.md +206 -0
  18. package/data/llms/components/colorpicker.md +213 -0
  19. package/data/llms/components/commandmenu.md +660 -0
  20. package/data/llms/components/compare.md +407 -0
  21. package/data/llms/components/confirmdialog.md +343 -0
  22. package/data/llms/components/confirmpopup.md +252 -0
  23. package/data/llms/components/contextmenu.md +522 -0
  24. package/data/llms/components/datatable.md +5266 -0
  25. package/data/llms/components/dataview.md +569 -0
  26. package/data/llms/components/datepicker.md +964 -0
  27. package/data/llms/components/deferredcontent.md +96 -0
  28. package/data/llms/components/dialog.md +702 -0
  29. package/data/llms/components/divider.md +152 -0
  30. package/data/llms/components/dock.md +488 -0
  31. package/data/llms/components/drawer.md +469 -0
  32. package/data/llms/components/dynamicdialog.md +214 -0
  33. package/data/llms/components/editor.md +205 -0
  34. package/data/llms/components/fieldset.md +253 -0
  35. package/data/llms/components/fileupload.md +459 -0
  36. package/data/llms/components/floatlabel.md +144 -0
  37. package/data/llms/components/fluid.md +104 -0
  38. package/data/llms/components/focustrap.md +59 -0
  39. package/data/llms/components/forms.md +344 -0
  40. package/data/llms/components/galleria.md +1119 -0
  41. package/data/llms/components/gallery.md +1003 -0
  42. package/data/llms/components/iconfield.md +283 -0
  43. package/data/llms/components/iftalabel.md +96 -0
  44. package/data/llms/components/image.md +179 -0
  45. package/data/llms/components/imagecompare.md +108 -0
  46. package/data/llms/components/inplace.md +183 -0
  47. package/data/llms/components/inputcolor.md +869 -0
  48. package/data/llms/components/inputgroup.md +419 -0
  49. package/data/llms/components/inputmask.md +345 -0
  50. package/data/llms/components/inputnumber.md +551 -0
  51. package/data/llms/components/inputotp.md +345 -0
  52. package/data/llms/components/inputpassword.md +738 -0
  53. package/data/llms/components/inputtags.md +432 -0
  54. package/data/llms/components/inputtext.md +569 -0
  55. package/data/llms/components/installation.md +1 -0
  56. package/data/llms/components/keyfilter.md +116 -0
  57. package/data/llms/components/knob.md +318 -0
  58. package/data/llms/components/label.md +151 -0
  59. package/data/llms/components/laravel.md +53 -0
  60. package/data/llms/components/listbox.md +636 -0
  61. package/data/llms/components/mask.md +203 -0
  62. package/data/llms/components/mcp.md +39 -0
  63. package/data/llms/components/megamenu.md +563 -0
  64. package/data/llms/components/menu.md +651 -0
  65. package/data/llms/components/menubar.md +446 -0
  66. package/data/llms/components/message.md +497 -0
  67. package/data/llms/components/metergroup.md +281 -0
  68. package/data/llms/components/multiselect.md +752 -0
  69. package/data/llms/components/orderlist.md +224 -0
  70. package/data/llms/components/organizationchart.md +418 -0
  71. package/data/llms/components/paginator.md +221 -0
  72. package/data/llms/components/panel.md +321 -0
  73. package/data/llms/components/panelmenu.md +703 -0
  74. package/data/llms/components/password.md +657 -0
  75. package/data/llms/components/picklist.md +286 -0
  76. package/data/llms/components/popover.md +145 -0
  77. package/data/llms/components/progressbar.md +242 -0
  78. package/data/llms/components/progressspinner.md +104 -0
  79. package/data/llms/components/radiobutton.md +427 -0
  80. package/data/llms/components/rating.md +312 -0
  81. package/data/llms/components/ripple.md +91 -0
  82. package/data/llms/components/scrollarea.md +700 -0
  83. package/data/llms/components/scrollpanel.md +131 -0
  84. package/data/llms/components/scrolltop.md +87 -0
  85. package/data/llms/components/select.md +1251 -0
  86. package/data/llms/components/selectbutton.md +268 -0
  87. package/data/llms/components/sidebar.md +2232 -0
  88. package/data/llms/components/skeleton.md +302 -0
  89. package/data/llms/components/slider.md +416 -0
  90. package/data/llms/components/speeddial.md +402 -0
  91. package/data/llms/components/splitbutton.md +840 -0
  92. package/data/llms/components/splitter.md +447 -0
  93. package/data/llms/components/stepper.md +551 -0
  94. package/data/llms/components/styleclass.md +226 -0
  95. package/data/llms/components/tabs.md +609 -0
  96. package/data/llms/components/tag.md +178 -0
  97. package/data/llms/components/terminal.md +123 -0
  98. package/data/llms/components/textarea.md +519 -0
  99. package/data/llms/components/tieredmenu.md +578 -0
  100. package/data/llms/components/timeline.md +494 -0
  101. package/data/llms/components/toast.md +472 -0
  102. package/data/llms/components/togglebutton.md +276 -0
  103. package/data/llms/components/toggleswitch.md +271 -0
  104. package/data/llms/components/toolbar.md +140 -0
  105. package/data/llms/components/tooltip.md +160 -0
  106. package/data/llms/components/tree.md +1076 -0
  107. package/data/llms/components/treeselect.md +660 -0
  108. package/data/llms/components/treetable.md +2493 -0
  109. package/data/llms/components/virtualscroller.md +265 -0
  110. package/data/llms/guides/autoimport.md +28 -0
  111. package/data/llms/guides/cdn.md +72 -0
  112. package/data/llms/guides/configuration.md +158 -0
  113. package/data/llms/guides/customicons.md +67 -0
  114. package/data/llms/guides/guides/accessibility.md +27 -0
  115. package/data/llms/guides/guides/animations.md +119 -0
  116. package/data/llms/guides/guides/rtl.md +7 -0
  117. package/data/llms/guides/icons.md +136 -0
  118. package/data/llms/guides/installation.md +3 -0
  119. package/data/llms/guides/laravel.md +66 -0
  120. package/data/llms/guides/llms.md +15 -0
  121. package/data/llms/guides/mcp.md +104 -0
  122. package/data/llms/guides/migration/v4.md +15 -0
  123. package/data/llms/guides/migration/v5.md +15 -0
  124. package/data/llms/guides/nuxt.md +141 -0
  125. package/data/llms/guides/passthrough.md +137 -0
  126. package/data/llms/guides/primeclt.md +43 -0
  127. package/data/llms/guides/tailwind.md +151 -0
  128. package/data/llms/guides/theming/styled.md +497 -0
  129. package/data/llms/guides/theming/unstyled.md +57 -0
  130. package/data/llms/guides/uikit.md +3 -0
  131. package/data/llms/guides/vite.md +90 -0
  132. package/data/llms/llms-full.txt +54465 -0
  133. package/data/llms/llms.txt +132 -0
  134. package/data/llms/pages/accessibility.md +27 -0
  135. package/data/llms/pages/animations.md +119 -0
  136. package/data/llms/pages/autoimport.md +28 -0
  137. package/data/llms/pages/cdn.md +72 -0
  138. package/data/llms/pages/configuration.md +158 -0
  139. package/data/llms/pages/contribution.md +31 -0
  140. package/data/llms/pages/customicons.md +67 -0
  141. package/data/llms/pages/designer.md +79 -0
  142. package/data/llms/pages/dynamicimports.md +7 -0
  143. package/data/llms/pages/forms.md +63 -0
  144. package/data/llms/pages/guides/accessibility.md +27 -0
  145. package/data/llms/pages/guides/animations.md +119 -0
  146. package/data/llms/pages/guides/rtl.md +7 -0
  147. package/data/llms/pages/icons.md +136 -0
  148. package/data/llms/pages/installation.md +3 -0
  149. package/data/llms/pages/introduction.md +23 -0
  150. package/data/llms/pages/laravel.md +66 -0
  151. package/data/llms/pages/llms.md +15 -0
  152. package/data/llms/pages/mcp.md +104 -0
  153. package/data/llms/pages/migration/v4.md +15 -0
  154. package/data/llms/pages/migration/v5.md +15 -0
  155. package/data/llms/pages/nuxt.md +141 -0
  156. package/data/llms/pages/passthrough.md +137 -0
  157. package/data/llms/pages/primeclt.md +43 -0
  158. package/data/llms/pages/rtl.md +7 -0
  159. package/data/llms/pages/setup.md +3 -0
  160. package/data/llms/pages/styled.md +497 -0
  161. package/data/llms/pages/tailwind.md +151 -0
  162. package/data/llms/pages/theming/styled.md +497 -0
  163. package/data/llms/pages/theming/unstyled.md +57 -0
  164. package/data/llms/pages/uikit.md +3 -0
  165. package/data/llms/pages/unstyled.md +57 -0
  166. package/data/llms/pages/v4.md +15 -0
  167. package/data/llms/pages/v5.md +15 -0
  168. package/data/llms/pages/vite.md +90 -0
  169. package/data/manifest.json +11117 -0
  170. package/data/mcp-data.json +55940 -0
  171. package/dist/index.d.ts +17 -1
  172. package/dist/index.js +66066 -72541
  173. package/package.json +10 -12
@@ -0,0 +1,2493 @@
1
+ # TreeTable
2
+
3
+ TreeTable is used to display hierarchical data in tabular format.
4
+
5
+ ## Basic
6
+
7
+ TreeTable requires a collection of TreeNode instances as a value and Column components as children for the representation. The column with the element to toggle a node should have expander enabled.
8
+
9
+ ```vue
10
+ <template>
11
+ <div>
12
+ <TreeTable :value="nodes" tableStyle="min-width: 50rem">
13
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
14
+ <Column field="size" header="Size" style="width: 33%"></Column>
15
+ <Column field="type" header="Type" style="width: 33%"></Column>
16
+ </TreeTable>
17
+ </div>
18
+ </template>
19
+
20
+ <script setup>
21
+ import { ref, onMounted } from 'vue';
22
+ import { NodeService } from '@/service/NodeService';
23
+
24
+ onMounted(() => {
25
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
26
+ });
27
+
28
+ const nodes = ref();
29
+ <\/script>
30
+ ```
31
+
32
+ ## Size
33
+
34
+ In addition to a regular table, alternatives with alternative sizes are available.
35
+
36
+ ```vue
37
+ <template>
38
+ <div>
39
+ <div class="flex mb-6">
40
+ <SelectButton v-model="size" :options="sizeOptions" optionLabel="label" dataKey="label" />
41
+ </div>
42
+ <TreeTable :value="nodes" :size="size.value" tableStyle="min-width: 50rem">
43
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
44
+ <Column field="size" header="Size" style="width: 33%"></Column>
45
+ <Column field="type" header="Type" style="width: 33%">
46
+ <template #body="{ node }">
47
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
48
+ </template>
49
+ </Column>
50
+ </TreeTable>
51
+ </div>
52
+ </template>
53
+
54
+ <script setup>
55
+ import { ref, onMounted } from 'vue';
56
+ import { NodeService } from '@/service/NodeService';
57
+
58
+ onMounted(() => {
59
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
60
+ });
61
+
62
+ const nodes = ref();
63
+ const size = ref({ label: 'Normal', value: 'normal' });
64
+ const sizeOptions = ref([
65
+ { label: 'Small', value: 'small', class: 'sm' },
66
+ { label: 'Normal', value: 'normal' },
67
+ { label: 'Large', value: 'large', class: 'lg' }
68
+ ]);
69
+
70
+ const getSeverity = (type) => {
71
+ switch (type) {
72
+ case 'Folder':
73
+ return 'warn';
74
+ case 'Document':
75
+ return 'info';
76
+ case 'Picture':
77
+ return 'success';
78
+ case 'Video':
79
+ return 'success';
80
+ case 'Text':
81
+ return 'secondary';
82
+ default:
83
+ return 'secondary';
84
+ }
85
+ };
86
+ <\/script>
87
+ ```
88
+
89
+ ## Grid Lines
90
+
91
+ Enabling showGridlines displays grid lines.
92
+
93
+ ```vue
94
+ <template>
95
+ <div>
96
+ <TreeTable :value="nodes" showGridlines tableStyle="min-width: 50rem">
97
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
98
+ <Column field="size" header="Size" style="width: 33%"></Column>
99
+ <Column field="type" header="Type" style="width: 33%">
100
+ <template #body="{ node }">
101
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
102
+ </template>
103
+ </Column>
104
+ </TreeTable>
105
+ </div>
106
+ </template>
107
+
108
+ <script setup>
109
+ import { ref, onMounted } from 'vue';
110
+ import { NodeService } from '@/service/NodeService';
111
+
112
+ onMounted(() => {
113
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
114
+ });
115
+
116
+ const nodes = ref();
117
+
118
+ const getSeverity = (type) => {
119
+ switch (type) {
120
+ case 'Folder':
121
+ return 'warn';
122
+ case 'Document':
123
+ return 'info';
124
+ case 'Picture':
125
+ return 'success';
126
+ case 'Video':
127
+ return 'success';
128
+ case 'Text':
129
+ return 'secondary';
130
+ default:
131
+ return 'secondary';
132
+ }
133
+ };
134
+ <\/script>
135
+ ```
136
+
137
+ ## Single
138
+
139
+ Single node selection is configured by setting selectionMode as single along with selectionKeys property to manage the selection value binding. By default, metaKey press (e.g. ⌘ ) is necessary to unselect a node however this can be configured with disabling the metaKeySelection property. In touch enabled devices this option has no effect and behavior is same as setting it to false.
140
+
141
+ ```vue
142
+ <template>
143
+ <div>
144
+ <div class="flex justify-center items-center mb-6 gap-2">
145
+ <ToggleSwitch v-model="metaKey" inputId="input-metakey" />
146
+ <label for="input-metakey">MetaKey</label>
147
+ </div>
148
+ <TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="single" :metaKeySelection="metaKey" tableStyle="min-width: 50rem">
149
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
150
+ <Column field="size" header="Size" style="width: 33%"></Column>
151
+ <Column field="type" header="Type" style="width: 33%">
152
+ <template #body="{ node }">
153
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
154
+ </template>
155
+ </Column>
156
+ </TreeTable>
157
+ </div>
158
+ </template>
159
+
160
+ <script setup>
161
+ import { ref, onMounted } from 'vue';
162
+ import { NodeService } from '@/service/NodeService';
163
+
164
+ onMounted(() => {
165
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
166
+ });
167
+
168
+ const nodes = ref();
169
+ const selectedKey = ref();
170
+ const metaKey = ref(true);
171
+
172
+ const getSeverity = (type) => {
173
+ switch (type) {
174
+ case 'Folder':
175
+ return 'warn';
176
+ case 'Document':
177
+ return 'info';
178
+ case 'Picture':
179
+ return 'success';
180
+ case 'Video':
181
+ return 'success';
182
+ case 'Text':
183
+ return 'secondary';
184
+ default:
185
+ return 'secondary';
186
+ }
187
+ };
188
+ <\/script>
189
+ ```
190
+
191
+ ## Multiple
192
+
193
+ More than one node is selectable by setting selectionMode to multiple . By default in multiple selection mode, metaKey press (e.g. ⌘ ) is not necessary to add to existing selections. When the optional metaKeySelection is present, behavior is changed in a way that selecting a new node requires meta key to be present. Note that in touch enabled devices, TreeTable always ignores metaKey. In multiple selection mode, value binding should be a key-value pair where key is the node key and value is a boolean to indicate selection.
194
+
195
+ ```vue
196
+ <template>
197
+ <div>
198
+ <div class="flex justify-center items-center mb-6 gap-2">
199
+ <ToggleSwitch v-model="metaKey" inputId="input-metakey" />
200
+ <label for="input-metakey">MetaKey</label>
201
+ </div>
202
+ <TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="multiple" :metaKeySelection="metaKey" tableStyle="min-width: 50rem">
203
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
204
+ <Column field="size" header="Size" style="width: 33%"></Column>
205
+ <Column field="type" header="Type" style="width: 33%">
206
+ <template #body="{ node }">
207
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
208
+ </template>
209
+ </Column>
210
+ </TreeTable>
211
+ </div>
212
+ </template>
213
+
214
+ <script setup>
215
+ import { ref, onMounted } from 'vue';
216
+ import { NodeService } from '@/service/NodeService';
217
+
218
+ onMounted(() => {
219
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
220
+ });
221
+
222
+ const nodes = ref();
223
+ const selectedKey = ref();
224
+ const metaKey = ref(true);
225
+
226
+ const getSeverity = (type) => {
227
+ switch (type) {
228
+ case 'Folder':
229
+ return 'warn';
230
+ case 'Document':
231
+ return 'info';
232
+ case 'Picture':
233
+ return 'success';
234
+ case 'Video':
235
+ return 'success';
236
+ case 'Text':
237
+ return 'secondary';
238
+ default:
239
+ return 'secondary';
240
+ }
241
+ };
242
+ <\/script>
243
+ ```
244
+
245
+ ## Checkbox
246
+
247
+ Selection of multiple nodes via checkboxes is enabled by configuring selectionMode as checkbox . In checkbox selection mode, value binding should be a key-value pair where key (or the dataKey) is the node key and value is an object that has checked and partialChecked properties to represent the checked state of a node.
248
+
249
+ ```vue
250
+ <template>
251
+ <div>
252
+ <TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="checkbox" tableStyle="min-width: 50rem">
253
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
254
+ <Column field="size" header="Size" style="width: 33%"></Column>
255
+ <Column field="type" header="Type" style="width: 33%">
256
+ <template #body="{ node }">
257
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
258
+ </template>
259
+ </Column>
260
+ </TreeTable>
261
+ </div>
262
+ </template>
263
+
264
+ <script setup>
265
+ import { ref, onMounted } from 'vue';
266
+ import { NodeService } from '@/service/NodeService';
267
+
268
+ onMounted(() => {
269
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
270
+ });
271
+
272
+ const nodes = ref();
273
+ const selectedKey = ref();
274
+
275
+ const getSeverity = (type) => {
276
+ switch (type) {
277
+ case 'Folder':
278
+ return 'warn';
279
+ case 'Document':
280
+ return 'info';
281
+ case 'Picture':
282
+ return 'success';
283
+ case 'Video':
284
+ return 'success';
285
+ case 'Text':
286
+ return 'secondary';
287
+ default:
288
+ return 'secondary';
289
+ }
290
+ };
291
+ <\/script>
292
+ ```
293
+
294
+ ## Keyboard
295
+
296
+ TreeTable has full keyboard support. Arrow Up and Down move focus between rows, Arrow Right and Left expand and collapse a node, Space or Enter toggles the selection of the focused row and Shift with Arrow keys extends the range. Pair selectionMode multiple with metaKeySelection for a fully keyboard-driven flow.
297
+
298
+ ```vue
299
+ <template>
300
+ <div>
301
+ <TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="multiple" metaKeySelection tableStyle="min-width: 50rem">
302
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
303
+ <Column field="size" header="Size" style="width: 33%"></Column>
304
+ <Column field="type" header="Type" style="width: 33%">
305
+ <template #body="{ node }">
306
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
307
+ </template>
308
+ </Column>
309
+ </TreeTable>
310
+ </div>
311
+ </template>
312
+
313
+ <script setup>
314
+ import { ref, onMounted } from 'vue';
315
+ import { NodeService } from '@/service/NodeService';
316
+
317
+ onMounted(() => {
318
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
319
+ });
320
+
321
+ const nodes = ref();
322
+ const selectedKey = ref();
323
+
324
+ const getSeverity = (type) => {
325
+ switch (type) {
326
+ case 'Folder':
327
+ return 'warn';
328
+ case 'Document':
329
+ return 'info';
330
+ case 'Picture':
331
+ return 'success';
332
+ case 'Video':
333
+ return 'success';
334
+ case 'Text':
335
+ return 'secondary';
336
+ default:
337
+ return 'secondary';
338
+ }
339
+ };
340
+ <\/script>
341
+ ```
342
+
343
+ ## Events
344
+
345
+ TreeTable provides nodeSelect and nodeUnselect events to listen selection events.
346
+
347
+ ```vue
348
+ <template>
349
+ <div>
350
+ <TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="single" @nodeSelect="onNodeSelect" @nodeUnselect="onNodeUnselect" :metaKeySelection="false" tableStyle="min-width: 50rem">
351
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
352
+ <Column field="size" header="Size" style="width: 33%"></Column>
353
+ <Column field="type" header="Type" style="width: 33%">
354
+ <template #body="{ node }">
355
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
356
+ </template>
357
+ </Column>
358
+ </TreeTable>
359
+ <Toast />
360
+ </div>
361
+ </template>
362
+
363
+ <script setup>
364
+ import { ref, onMounted } from 'vue';
365
+ import { useToast } from 'primevue/usetoast'
366
+ import { NodeService } from '@/service/NodeService';
367
+
368
+ onMounted(() => {
369
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
370
+ });
371
+
372
+ const nodes = ref();
373
+ const selectedKey = ref();
374
+ const toast = useToast();
375
+ const onNodeSelect = (node) => {
376
+ toast.add({ severity: 'success', summary: 'Node Selected', detail: node.data.name, life: 3000 });
377
+ };
378
+ const onNodeUnselect = (node) => {
379
+ toast.add({ severity: 'warn', summary: 'Node Unselected', detail: node.data.name, life: 3000 });
380
+ };
381
+
382
+ const getSeverity = (type) => {
383
+ switch (type) {
384
+ case 'Folder':
385
+ return 'warn';
386
+ case 'Document':
387
+ return 'info';
388
+ case 'Picture':
389
+ return 'success';
390
+ case 'Video':
391
+ return 'success';
392
+ case 'Text':
393
+ return 'secondary';
394
+ default:
395
+ return 'secondary';
396
+ }
397
+ };
398
+ <\/script>
399
+ ```
400
+
401
+ ## Single Column
402
+
403
+ Sorting on a column is enabled by adding the sortable property.
404
+
405
+ ```vue
406
+ <template>
407
+ <div>
408
+ <TreeTable :value="nodes" tableStyle="min-width: 50rem">
409
+ <Column field="name" header="Name" sortable expander style="width: 34%"></Column>
410
+ <Column field="size" header="Size" sortable style="width: 33%"></Column>
411
+ <Column field="type" header="Type" sortable style="width: 33%">
412
+ <template #body="{ node }">
413
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
414
+ </template>
415
+ </Column>
416
+ </TreeTable>
417
+ </div>
418
+ </template>
419
+
420
+ <script setup>
421
+ import { ref, onMounted } from 'vue';
422
+ import { NodeService } from '@/service/NodeService';
423
+
424
+ onMounted(() => {
425
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
426
+ });
427
+
428
+ const nodes = ref();
429
+
430
+ const getSeverity = (type) => {
431
+ switch (type) {
432
+ case 'Folder':
433
+ return 'warn';
434
+ case 'Document':
435
+ return 'info';
436
+ case 'Picture':
437
+ return 'success';
438
+ case 'Video':
439
+ return 'success';
440
+ case 'Text':
441
+ return 'secondary';
442
+ default:
443
+ return 'secondary';
444
+ }
445
+ };
446
+ <\/script>
447
+ ```
448
+
449
+ ## Multiple Columns
450
+
451
+ Multiple columns can be sorted by defining sortMode as multiple . This mode requires metaKey (e.g. ⌘ ) to be pressed when clicking a header.
452
+
453
+ ```vue
454
+ <template>
455
+ <div>
456
+ <TreeTable :value="nodes" sortMode="multiple" tableStyle="min-width: 50rem">
457
+ <Column field="name" header="Name" sortable expander style="width: 34%"></Column>
458
+ <Column field="size" header="Size" sortable style="width: 33%"></Column>
459
+ <Column field="type" header="Type" sortable style="width: 33%">
460
+ <template #body="{ node }">
461
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
462
+ </template>
463
+ </Column>
464
+ </TreeTable>
465
+ </div>
466
+ </template>
467
+
468
+ <script setup>
469
+ import { ref, onMounted } from 'vue';
470
+ import { NodeService } from '@/service/NodeService';
471
+
472
+ onMounted(() => {
473
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
474
+ });
475
+
476
+ const nodes = ref();
477
+
478
+ const getSeverity = (type) => {
479
+ switch (type) {
480
+ case 'Folder':
481
+ return 'warn';
482
+ case 'Document':
483
+ return 'info';
484
+ case 'Picture':
485
+ return 'success';
486
+ case 'Video':
487
+ return 'success';
488
+ case 'Text':
489
+ return 'secondary';
490
+ default:
491
+ return 'secondary';
492
+ }
493
+ };
494
+ <\/script>
495
+ ```
496
+
497
+ ## Presort
498
+
499
+ Apply an initial sort on mount using sortField and sortOrder . Headers stay interactive afterwards.
500
+
501
+ ```vue
502
+ <template>
503
+ <div>
504
+ <TreeTable :value="nodes" sortField="size" :sortOrder="-1" removableSort tableStyle="min-width: 50rem">
505
+ <Column field="name" header="Name" sortable expander style="width: 34%"></Column>
506
+ <Column field="size" header="Size" sortable style="width: 33%"></Column>
507
+ <Column field="type" header="Type" sortable style="width: 33%">
508
+ <template #body="{ node }">
509
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
510
+ </template>
511
+ </Column>
512
+ </TreeTable>
513
+ </div>
514
+ </template>
515
+
516
+ <script setup>
517
+ import { ref, onMounted } from 'vue';
518
+ import { NodeService } from '@/service/NodeService';
519
+
520
+ onMounted(() => {
521
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
522
+ });
523
+
524
+ const nodes = ref();
525
+
526
+ const getSeverity = (type) => {
527
+ switch (type) {
528
+ case 'Folder':
529
+ return 'warn';
530
+ case 'Document':
531
+ return 'info';
532
+ case 'Picture':
533
+ return 'success';
534
+ case 'Video':
535
+ return 'success';
536
+ case 'Text':
537
+ return 'secondary';
538
+ default:
539
+ return 'secondary';
540
+ }
541
+ };
542
+ <\/script>
543
+ ```
544
+
545
+ ## Multiple Presort
546
+
547
+ Apply an initial multi-column sort on mount by setting sortMode to multiple together with multiSortMeta . Each header keeps a badge with its sort order and stays interactive afterwards.
548
+
549
+ ```vue
550
+ <template>
551
+ <div>
552
+ <TreeTable :value="nodes" sortMode="multiple" :multiSortMeta="multiSortMeta" removableSort tableStyle="min-width: 50rem">
553
+ <Column field="name" header="Name" sortable expander style="width: 34%"></Column>
554
+ <Column field="size" header="Size" sortable style="width: 33%"></Column>
555
+ <Column field="type" header="Type" sortable style="width: 33%">
556
+ <template #body="{ node }">
557
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
558
+ </template>
559
+ </Column>
560
+ </TreeTable>
561
+ </div>
562
+ </template>
563
+
564
+ <script setup>
565
+ import { ref, onMounted } from 'vue';
566
+ import { NodeService } from '@/service/NodeService';
567
+
568
+ onMounted(() => {
569
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
570
+ });
571
+
572
+ const nodes = ref();
573
+ const multiSortMeta = ref([
574
+ { field: 'type', order: 1 },
575
+ { field: 'name', order: 1 }
576
+ ]);
577
+
578
+ const getSeverity = (type) => {
579
+ switch (type) {
580
+ case 'Folder':
581
+ return 'warn';
582
+ case 'Document':
583
+ return 'info';
584
+ case 'Picture':
585
+ return 'success';
586
+ case 'Video':
587
+ return 'success';
588
+ case 'Text':
589
+ return 'secondary';
590
+ default:
591
+ return 'secondary';
592
+ }
593
+ };
594
+ <\/script>
595
+ ```
596
+
597
+ ## Removable Sort
598
+
599
+ When removableSort is present, the third click removes the sorting from the column.
600
+
601
+ ```vue
602
+ <template>
603
+ <div>
604
+ <TreeTable :value="nodes" sortMode="multiple" removableSort tableStyle="min-width: 50rem">
605
+ <Column field="name" header="Name" sortable expander style="width: 34%"></Column>
606
+ <Column field="size" header="Size" sortable style="width: 33%"></Column>
607
+ <Column field="type" header="Type" sortable style="width: 33%">
608
+ <template #body="{ node }">
609
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
610
+ </template>
611
+ </Column>
612
+ </TreeTable>
613
+ </div>
614
+ </template>
615
+
616
+ <script setup>
617
+ import { ref, onMounted } from 'vue';
618
+ import { NodeService } from '@/service/NodeService';
619
+
620
+ onMounted(() => {
621
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
622
+ });
623
+
624
+ const nodes = ref();
625
+
626
+ const getSeverity = (type) => {
627
+ switch (type) {
628
+ case 'Folder':
629
+ return 'warn';
630
+ case 'Document':
631
+ return 'info';
632
+ case 'Picture':
633
+ return 'success';
634
+ case 'Video':
635
+ return 'success';
636
+ case 'Text':
637
+ return 'secondary';
638
+ default:
639
+ return 'secondary';
640
+ }
641
+ };
642
+ <\/script>
643
+ ```
644
+
645
+ ## Basic
646
+
647
+ Pagination is enabled by adding paginator property and defining rows per page.
648
+
649
+ ```vue
650
+ <template>
651
+ <div>
652
+ <TreeTable :value="nodes" :paginator="true" :rows="5" :rowsPerPageOptions="[5, 10, 25]" tableStyle="min-width: 50rem">
653
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
654
+ <Column field="size" header="Size" style="width: 33%"></Column>
655
+ <Column field="type" header="Type" style="width: 33%">
656
+ <template #body="{ node }">
657
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
658
+ </template>
659
+ </Column>
660
+ </TreeTable>
661
+ </div>
662
+ </template>
663
+
664
+ <script setup>
665
+ import { ref } from 'vue';
666
+
667
+ const nodes = ref();
668
+
669
+ let files = [];
670
+ for (let i = 0; i < 50; i++) {
671
+ let node = {
672
+ key: i,
673
+ data: {
674
+ name: 'Item ' + i,
675
+ size: Math.floor(Math.random() * 1000) + 1 + 'kb',
676
+ type: 'Type ' + i
677
+ },
678
+ children: [
679
+ {
680
+ key: i + ' - 0',
681
+ data: {
682
+ name: 'Item ' + i + ' - 0',
683
+ size: Math.floor(Math.random() * 1000) + 1 + 'kb',
684
+ type: 'Type ' + i
685
+ }
686
+ }
687
+ ]
688
+ };
689
+
690
+ files.push(node);
691
+ }
692
+
693
+ nodes.value = files;
694
+
695
+ const getSeverity = (type) => {
696
+ switch (type) {
697
+ case 'Folder':
698
+ return 'warn';
699
+ case 'Document':
700
+ return 'info';
701
+ case 'Picture':
702
+ return 'success';
703
+ case 'Video':
704
+ return 'success';
705
+ case 'Text':
706
+ return 'secondary';
707
+ default:
708
+ return 'secondary';
709
+ }
710
+ };
711
+ <\/script>
712
+ ```
713
+
714
+ ## Template
715
+
716
+ Paginator UI is customized using the paginatorTemplate property. Each element can also be customized further with your own UI to replace the default one, refer to the Paginator component for more information about the advanced customization options.
717
+
718
+ ```vue
719
+ <template>
720
+ <div>
721
+ <TreeTable
722
+ :value="nodes"
723
+ :paginator="true"
724
+ :rows="5"
725
+ :rowsPerPageOptions="[5, 10, 25, 50]"
726
+ paginatorTemplate="RowsPerPageDropdown FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"
727
+ currentPageReportTemplate="{first} to {last} of {totalRecords}"
728
+ tableStyle="min-width: 50rem"
729
+ >
730
+ <template #paginatorstart>
731
+ <Button type="button" iconOnly text>
732
+ <Refresh />
733
+ </Button>
734
+ </template>
735
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
736
+ <Column field="size" header="Size" style="width: 33%"></Column>
737
+ <Column field="type" header="Type" style="width: 33%">
738
+ <template #body="{ node }">
739
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
740
+ </template>
741
+ </Column>
742
+ <template #paginatorend>
743
+ <Button type="button" iconOnly text>
744
+ <Download />
745
+ </Button>
746
+ </template>
747
+ </TreeTable>
748
+ </div>
749
+ </template>
750
+
751
+ <script setup>
752
+ import Download from '@primeicons/vue/download';
753
+ import Refresh from '@primeicons/vue/refresh';
754
+ import { ref } from 'vue';
755
+
756
+ const nodes = ref();
757
+
758
+ let files = [];
759
+ for (let i = 0; i < 50; i++) {
760
+ let node = {
761
+ key: i,
762
+ data: {
763
+ name: 'Item ' + i,
764
+ size: Math.floor(Math.random() * 1000) + 1 + 'kb',
765
+ type: 'Type ' + i
766
+ },
767
+ children: [
768
+ {
769
+ key: i + ' - 0',
770
+ data: {
771
+ name: 'Item ' + i + ' - 0',
772
+ size: Math.floor(Math.random() * 1000) + 1 + 'kb',
773
+ type: 'Type ' + i
774
+ }
775
+ }
776
+ ]
777
+ };
778
+
779
+ files.push(node);
780
+ }
781
+
782
+ nodes.value = files;
783
+
784
+ const getSeverity = (type) => {
785
+ switch (type) {
786
+ case 'Folder':
787
+ return 'warn';
788
+ case 'Document':
789
+ return 'info';
790
+ case 'Picture':
791
+ return 'success';
792
+ case 'Video':
793
+ return 'success';
794
+ case 'Text':
795
+ return 'secondary';
796
+ default:
797
+ return 'secondary';
798
+ }
799
+ };
800
+ <\/script>
801
+ ```
802
+
803
+ ## Headless
804
+
805
+ Pagination is enabled by adding paginator property and defining rows per page.
806
+
807
+ ```vue
808
+ <template>
809
+ <div>
810
+ <TreeTable :value="nodes" :paginator="true" :rows="5" :rowsPerPageOptions="[5, 10, 25]" tableStyle="min-width: 50rem">
811
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
812
+ <Column field="size" header="Size" style="width: 33%"></Column>
813
+ <Column field="type" header="Type" style="width: 33%">
814
+ <template #body="{ node }">
815
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
816
+ </template>
817
+ </Column>
818
+ <template #paginatorcontainer="{ first, last, page, pageCount, prevPageCallback, nextPageCallback, totalRecords }">
819
+ <div class="flex items-center gap-4 border border-primary bg-transparent rounded-full w-full py-1 px-2 justify-between">
820
+ <Button iconOnly rounded text @click="prevPageCallback" :disabled="page === 0">
821
+ <ChevronLeft />
822
+ </Button>
823
+ <div class="text-color font-medium">
824
+ <span class="hidden sm:block">Showing {{ first }} to {{ last }} of {{ totalRecords }}</span>
825
+ <span class="block sm:hidden">Page {{ page + 1 }} of {{ pageCount }}</span>
826
+ </div>
827
+ <Button iconOnly rounded text @click="nextPageCallback" :disabled="page === pageCount - 1">
828
+ <ChevronRight />
829
+ </Button>
830
+ </div>
831
+ </template>
832
+ </TreeTable>
833
+ </div>
834
+ </template>
835
+
836
+ <script setup>
837
+ import ChevronLeft from '@primeicons/vue/chevron-left';
838
+ import ChevronRight from '@primeicons/vue/chevron-right';
839
+ import { ref } from 'vue';
840
+
841
+ const nodes = ref();
842
+
843
+ let files = [];
844
+ for (let i = 0; i < 50; i++) {
845
+ let node = {
846
+ key: i,
847
+ data: {
848
+ name: 'Item ' + i,
849
+ size: Math.floor(Math.random() * 1000) + 1 + 'kb',
850
+ type: 'Type ' + i
851
+ },
852
+ children: [
853
+ {
854
+ key: i + ' - 0',
855
+ data: {
856
+ name: 'Item ' + i + ' - 0',
857
+ size: Math.floor(Math.random() * 1000) + 1 + 'kb',
858
+ type: 'Type ' + i
859
+ }
860
+ }
861
+ ]
862
+ };
863
+
864
+ files.push(node);
865
+ }
866
+
867
+ nodes.value = files;
868
+
869
+ const getSeverity = (type) => {
870
+ switch (type) {
871
+ case 'Folder':
872
+ return 'warn';
873
+ case 'Document':
874
+ return 'info';
875
+ case 'Picture':
876
+ return 'success';
877
+ case 'Video':
878
+ return 'success';
879
+ case 'Text':
880
+ return 'secondary';
881
+ default:
882
+ return 'secondary';
883
+ }
884
+ };
885
+ <\/script>
886
+ ```
887
+
888
+ ## Vertical
889
+
890
+ Adding scrollable property along with a scrollHeight for the data viewport enables vertical scrolling with fixed headers.
891
+
892
+ ```vue
893
+ <template>
894
+ <div>
895
+ <TreeTable v-model:expandedKeys="expandedKeys" :value="nodes" scrollable scrollHeight="400px" tableStyle="min-width: 50rem">
896
+ <Column field="name" header="Name" expander style="width: 50%">
897
+ <template #body="{ node }">
898
+ <span class="inline-flex items-center gap-2">
899
+ <ImageIcon v-if="node.data.type === 'Picture'" />
900
+ <VideoIcon v-else-if="node.data.type === 'Video'" />
901
+ <Folder v-else-if="node.data.type === 'Folder'" />
902
+ <File v-else />
903
+ <span :class="{ 'font-medium': node.data.type === 'Folder' }">{{ node.data.name }}</span>
904
+ </span>
905
+ </template>
906
+ </Column>
907
+ <Column field="size" header="Size" style="width: 25%">
908
+ <template #body="{ node }">
909
+ <span class="text-sm text-surface-500 dark:text-surface-400">{{ node.data.size }}</span>
910
+ </template>
911
+ </Column>
912
+ <Column field="type" header="Type" style="width: 25%">
913
+ <template #body="{ node }">
914
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
915
+ </template>
916
+ </Column>
917
+ <template #empty>
918
+ <div class="flex flex-col items-center justify-center gap-3 py-24 text-center">
919
+ <div class="relative">
920
+ <div class="w-16 h-16 rounded-full bg-surface-100 dark:bg-surface-800 flex items-center justify-center">
921
+ <Database class="w-8 h-8 text-surface-400 dark:text-surface-500" />
922
+ </div>
923
+ <span class="absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-full border-2 border-surface-0 dark:border-surface-900 bg-primary animate-pulse" />
924
+ </div>
925
+ <div>
926
+ <p class="m-0 font-semibold text-surface-900 dark:text-surface-0">Loading tree</p>
927
+ <p class="mt-1 text-sm text-surface-500 dark:text-surface-400">Hang tight, the data is on its way.</p>
928
+ </div>
929
+ </div>
930
+ </template>
931
+ </TreeTable>
932
+ </div>
933
+ </template>
934
+
935
+ <script setup>
936
+ import { ref } from 'vue';
937
+ import Database from '@primeicons/vue/database';
938
+ import File from '@primeicons/vue/file';
939
+ import Folder from '@primeicons/vue/folder';
940
+ import ImageIcon from '@primeicons/vue/image';
941
+ import VideoIcon from '@primeicons/vue/video';
942
+
943
+ const types = ['Document', 'Text', 'Picture', 'Video'];
944
+
945
+ const nodes = ref(
946
+ Array.from({ length: 20 }, (_, i) => ({
947
+ key: String(i),
948
+ data: { name: \`Folder \${i + 1}\`, size: '—', type: 'Folder' },
949
+ children: Array.from({ length: 6 }, (_, j) => {
950
+ const type = types[j % types.length];
951
+ const size = ((i * 37 + j * 113) % 1950) + 50;
952
+
953
+ return {
954
+ key: \`\${i}-\${j}\`,
955
+ data: { name: \`\${type} \${i + 1}.\${j + 1}\`, size: \`\${size}kb\`, type }
956
+ };
957
+ })
958
+ }))
959
+ );
960
+ const expandedKeys = ref({ 0: true, 1: true });
961
+
962
+ const getSeverity = (type) => {
963
+ switch (type) {
964
+ case 'Folder':
965
+ return 'warn';
966
+ case 'Document':
967
+ return 'info';
968
+ case 'Picture':
969
+ return 'success';
970
+ case 'Video':
971
+ return 'success';
972
+ case 'Text':
973
+ return 'secondary';
974
+ default:
975
+ return 'secondary';
976
+ }
977
+ };
978
+ <\/script>
979
+ ```
980
+
981
+ ## Horizontal
982
+
983
+ Horizontal scrollbar is displayed when table width exceeds the parent width.
984
+
985
+ ```vue
986
+ <template>
987
+ <div>
988
+ <TreeTable v-model:expandedKeys="expandedKeys" :value="nodes" scrollable scrollHeight="400px">
989
+ <Column field="name" header="Name" expander style="min-width: 20rem">
990
+ <template #body="{ node }">
991
+ <span class="inline-flex items-center gap-2">
992
+ <ImageIcon v-if="node.data.type === 'Picture'" />
993
+ <VideoIcon v-else-if="node.data.type === 'Video'" />
994
+ <Folder v-else-if="node.data.type === 'Folder'" />
995
+ <File v-else />
996
+ <span :class="{ 'font-medium': node.data.type === 'Folder' }">{{ node.data.name }}</span>
997
+ </span>
998
+ </template>
999
+ </Column>
1000
+ <Column field="size" header="Size" style="min-width: 10rem">
1001
+ <template #body="{ node }">
1002
+ <span class="text-sm text-surface-500 dark:text-surface-400">{{ node.data.size }}</span>
1003
+ </template>
1004
+ </Column>
1005
+ <Column field="type" header="Type" style="min-width: 12rem">
1006
+ <template #body="{ node }">
1007
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
1008
+ </template>
1009
+ </Column>
1010
+ <Column header="Key" style="min-width: 14rem">
1011
+ <template #body="{ node }">
1012
+ <code class="text-xs text-surface-500 dark:text-surface-400">{{ node.key }}</code>
1013
+ </template>
1014
+ </Column>
1015
+ <Column header="Level" style="min-width: 12rem">
1016
+ <template #body="{ node }">{{ getLevel(node) }}</template>
1017
+ </Column>
1018
+ <Column header="Has Children" style="min-width: 12rem">
1019
+ <template #body="{ node }">{{ node.children && node.children.length ? 'Yes' : 'No' }}</template>
1020
+ </Column>
1021
+ <template #empty>
1022
+ <div class="flex flex-col items-center justify-center gap-3 py-24 text-center">
1023
+ <div class="relative">
1024
+ <div class="w-16 h-16 rounded-full bg-surface-100 dark:bg-surface-800 flex items-center justify-center">
1025
+ <Database class="w-8 h-8 text-surface-400 dark:text-surface-500" />
1026
+ </div>
1027
+ <span class="absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-full border-2 border-surface-0 dark:border-surface-900 bg-primary animate-pulse" />
1028
+ </div>
1029
+ <div>
1030
+ <p class="m-0 font-semibold text-surface-900 dark:text-surface-0">Loading tree</p>
1031
+ <p class="mt-1 text-sm text-surface-500 dark:text-surface-400">Hang tight, the data is on its way.</p>
1032
+ </div>
1033
+ </div>
1034
+ </template>
1035
+ </TreeTable>
1036
+ </div>
1037
+ </template>
1038
+
1039
+ <script setup>
1040
+ import { ref, onMounted } from 'vue';
1041
+ import { NodeService } from '@/service/NodeService';
1042
+ import Database from '@primeicons/vue/database';
1043
+ import File from '@primeicons/vue/file';
1044
+ import Folder from '@primeicons/vue/folder';
1045
+ import ImageIcon from '@primeicons/vue/image';
1046
+ import VideoIcon from '@primeicons/vue/video';
1047
+
1048
+ const nodes = ref();
1049
+ const expandedKeys = ref({ 0: true });
1050
+
1051
+ onMounted(() => {
1052
+ NodeService.getTreeTableNodes().then((data) => (nodes.value = data));
1053
+ });
1054
+
1055
+ const getLevel = (node) => String(node.key).split('-').length - 1;
1056
+
1057
+ const getSeverity = (type) => {
1058
+ switch (type) {
1059
+ case 'Folder':
1060
+ return 'warn';
1061
+ case 'Document':
1062
+ return 'info';
1063
+ case 'Resume':
1064
+ return 'info';
1065
+ case 'Application':
1066
+ return 'info';
1067
+ case 'PDF':
1068
+ return 'info';
1069
+ case 'Picture':
1070
+ return 'success';
1071
+ case 'Video':
1072
+ return 'success';
1073
+ case 'Text':
1074
+ return 'secondary';
1075
+ case 'Zip':
1076
+ return 'secondary';
1077
+ case 'Link':
1078
+ return 'secondary';
1079
+ default:
1080
+ return 'secondary';
1081
+ }
1082
+ };
1083
+ <\/script>
1084
+ ```
1085
+
1086
+ ## Flexible
1087
+
1088
+ Flex scroll feature makes the scrollable viewport section dynamic instead of a fixed value so that it can grow or shrink relative to the parent size of the table. Click the button below to display a maximizable Dialog where data viewport adjusts itself according to the size changes.
1089
+
1090
+ ```vue
1091
+ <template>
1092
+ <div class="flex justify-center">
1093
+ <Button @click="dialogVisible = true">
1094
+ <ExternalLink />
1095
+ Show
1096
+ </Button>
1097
+ <Dialog v-model:visible="dialogVisible" header="Flex Scroll" :style="{ width: '75vw' }" maximizable modal :contentStyle="{ height: '300px' }">
1098
+ <TreeTable :value="nodes" :scrollable="true" scrollHeight="flex" tableStyle="min-width: 50rem">
1099
+ <Column field="name" header="Name" :expander="true" style="min-width: 200px"></Column>
1100
+ <Column field="size" header="Size" style="min-width: 200px"></Column>
1101
+ <Column field="type" header="Type" style="min-width: 200px">
1102
+ <template #body="{ node }">
1103
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
1104
+ </template>
1105
+ </Column>
1106
+ </TreeTable>
1107
+ <template #footer>
1108
+ <Button @click="dialogVisible = false">
1109
+ <Check />
1110
+ Ok
1111
+ </Button>
1112
+ </template>
1113
+ </Dialog>
1114
+ </div>
1115
+ </template>
1116
+
1117
+ <script setup>
1118
+ import Check from '@primeicons/vue/check';
1119
+ import ExternalLink from '@primeicons/vue/external-link';
1120
+ import { ref, onMounted } from 'vue';
1121
+ import { NodeService } from '@/service/NodeService';
1122
+
1123
+ onMounted(() => {
1124
+ NodeService.getTreeTableNodesSmall().then((data) => (this.nodes = data));
1125
+ });
1126
+
1127
+ const nodes = ref();
1128
+ const dialogVisible = ref(false);
1129
+
1130
+ const getSeverity = (type) => {
1131
+ switch (type) {
1132
+ case 'Folder':
1133
+ return 'warn';
1134
+ case 'Document':
1135
+ return 'info';
1136
+ case 'Picture':
1137
+ return 'success';
1138
+ case 'Video':
1139
+ return 'success';
1140
+ case 'Text':
1141
+ return 'secondary';
1142
+ default:
1143
+ return 'secondary';
1144
+ }
1145
+ };
1146
+ <\/script>
1147
+ ```
1148
+
1149
+ ## Frozen Columns
1150
+
1151
+ A column can be fixed during horizontal scrolling by enabling the frozen property on a Column. The location is defined with the alignFrozen that can be left or right .
1152
+
1153
+ ```vue
1154
+ <template>
1155
+ <div>
1156
+ <TreeTable v-model:expandedKeys="expandedKeys" :value="nodes" scrollable scrollHeight="400px">
1157
+ <Column field="name" header="Name" expander frozen style="min-width: 300px">
1158
+ <template #body="{ node }">
1159
+ <span class="inline-flex items-center gap-2">
1160
+ <ImageIcon v-if="node.data.type === 'Picture'" />
1161
+ <VideoIcon v-else-if="node.data.type === 'Video'" />
1162
+ <Folder v-else-if="node.data.type === 'Folder'" />
1163
+ <File v-else />
1164
+ <span :class="{ 'font-semibold': node.data.type === 'Folder' }">{{ node.data.name }}</span>
1165
+ </span>
1166
+ </template>
1167
+ </Column>
1168
+ <Column field="size" header="Size" style="min-width: 160px">
1169
+ <template #body="{ node }">
1170
+ <span class="text-sm text-surface-500 dark:text-surface-400">{{ node.data.size }}</span>
1171
+ </template>
1172
+ </Column>
1173
+ <Column field="type" header="Type" style="min-width: 160px">
1174
+ <template #body="{ node }">
1175
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
1176
+ </template>
1177
+ </Column>
1178
+ <Column field="owner" header="Owner" style="min-width: 200px"></Column>
1179
+ <Column field="modified" header="Modified" style="min-width: 160px"></Column>
1180
+ <Column header="Actions" alignFrozen="right" frozen style="min-width: 140px">
1181
+ <template #body>
1182
+ <span class="text-xs text-surface-500 dark:text-surface-400">Open · Share</span>
1183
+ </template>
1184
+ </Column>
1185
+ <template #empty>
1186
+ <div class="flex flex-col items-center justify-center gap-3 py-24 text-center">
1187
+ <div class="relative">
1188
+ <div class="w-16 h-16 rounded-full bg-surface-100 dark:bg-surface-800 flex items-center justify-center">
1189
+ <Database class="w-8 h-8 text-surface-400 dark:text-surface-500" />
1190
+ </div>
1191
+ <span class="absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-full border-2 border-surface-0 dark:border-surface-900 bg-primary animate-pulse" />
1192
+ </div>
1193
+ <div>
1194
+ <p class="m-0 font-semibold text-surface-900 dark:text-surface-0">Loading tree</p>
1195
+ <p class="mt-1 text-sm text-surface-500 dark:text-surface-400">Hang tight, the data is on its way.</p>
1196
+ </div>
1197
+ </div>
1198
+ </template>
1199
+ </TreeTable>
1200
+ </div>
1201
+ </template>
1202
+
1203
+ <script setup>
1204
+ import { ref } from 'vue';
1205
+ import Database from '@primeicons/vue/database';
1206
+ import File from '@primeicons/vue/file';
1207
+ import Folder from '@primeicons/vue/folder';
1208
+ import ImageIcon from '@primeicons/vue/image';
1209
+ import VideoIcon from '@primeicons/vue/video';
1210
+
1211
+ const owners = ['Amy Elsner', 'Anna Fali', 'Bernardo Dominic', 'Ioni Bowcher', 'Stephen Shaw'];
1212
+ const types = ['Document', 'Text', 'Picture', 'Video'];
1213
+
1214
+ const nodes = ref(
1215
+ Array.from({ length: 10 }, (_, i) => ({
1216
+ key: String(i),
1217
+ data: {
1218
+ name: \`Folder \${i + 1}\`,
1219
+ size: '—',
1220
+ type: 'Folder',
1221
+ owner: owners[i % owners.length],
1222
+ modified: \`2026-0\${(i % 9) + 1}-15\`
1223
+ },
1224
+ children: Array.from({ length: 5 }, (_, j) => {
1225
+ const type = types[j % types.length];
1226
+ const size = ((i * 37 + j * 113) % 1950) + 50;
1227
+
1228
+ return {
1229
+ key: \`\${i}-\${j}\`,
1230
+ data: {
1231
+ name: \`\${type} \${i + 1}.\${j + 1}\`,
1232
+ size: \`\${size}kb\`,
1233
+ type,
1234
+ owner: owners[(i + j) % owners.length],
1235
+ modified: \`2026-0\${((i + j) % 9) + 1}-20\`
1236
+ }
1237
+ };
1238
+ })
1239
+ }))
1240
+ );
1241
+ const expandedKeys = ref({ 0: true, 1: true });
1242
+
1243
+ const getSeverity = (type) => {
1244
+ switch (type) {
1245
+ case 'Folder':
1246
+ return 'warn';
1247
+ case 'Document':
1248
+ return 'info';
1249
+ case 'Picture':
1250
+ return 'success';
1251
+ case 'Video':
1252
+ return 'success';
1253
+ case 'Text':
1254
+ return 'secondary';
1255
+ default:
1256
+ return 'secondary';
1257
+ }
1258
+ };
1259
+ <\/script>
1260
+ ```
1261
+
1262
+ ## Fit Mode
1263
+
1264
+ Columns can be resized with drag and drop when resizableColumns is enabled. Default resize mode is fit that does not change the overall table width.
1265
+
1266
+ ```vue
1267
+ <template>
1268
+ <div>
1269
+ <TreeTable :value="nodes" :resizableColumns="true" showGridlines tableStyle="min-width: 50rem">
1270
+ <Column field="name" header="Name" expander></Column>
1271
+ <Column field="size" header="Size"></Column>
1272
+ <Column field="type" header="Type">
1273
+ <template #body="{ node }">
1274
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
1275
+ </template>
1276
+ </Column>
1277
+ </TreeTable>
1278
+ </div>
1279
+ </template>
1280
+
1281
+ <script setup>
1282
+ import { ref, onMounted } from 'vue';
1283
+ import { NodeService } from '@/service/NodeService';
1284
+
1285
+ onMounted(() => {
1286
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
1287
+ });
1288
+
1289
+ const nodes = ref();
1290
+
1291
+ const getSeverity = (type) => {
1292
+ switch (type) {
1293
+ case 'Folder':
1294
+ return 'warn';
1295
+ case 'Document':
1296
+ return 'info';
1297
+ case 'Picture':
1298
+ return 'success';
1299
+ case 'Video':
1300
+ return 'success';
1301
+ case 'Text':
1302
+ return 'secondary';
1303
+ default:
1304
+ return 'secondary';
1305
+ }
1306
+ };
1307
+ <\/script>
1308
+ ```
1309
+
1310
+ ## Expand Mode
1311
+
1312
+ Setting columnResizeMode as expand changes the table width as well.
1313
+
1314
+ ```vue
1315
+ <template>
1316
+ <div>
1317
+ <TreeTable :value="nodes" :resizableColumns="true" columnResizeMode="expand" showGridlines tableStyle="min-width: 50rem">
1318
+ <Column field="name" header="Name" expander></Column>
1319
+ <Column field="size" header="Size"></Column>
1320
+ <Column field="type" header="Type">
1321
+ <template #body="{ node }">
1322
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
1323
+ </template>
1324
+ </Column>
1325
+ </TreeTable>
1326
+ </div>
1327
+ </template>
1328
+
1329
+ <script setup>
1330
+ import { ref, onMounted } from 'vue';
1331
+ import { NodeService } from '@/service/NodeService';
1332
+
1333
+ onMounted(() => {
1334
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
1335
+ });
1336
+
1337
+ const nodes = ref();
1338
+
1339
+ const getSeverity = (type) => {
1340
+ switch (type) {
1341
+ case 'Folder':
1342
+ return 'warn';
1343
+ case 'Document':
1344
+ return 'info';
1345
+ case 'Picture':
1346
+ return 'success';
1347
+ case 'Video':
1348
+ return 'success';
1349
+ case 'Text':
1350
+ return 'secondary';
1351
+ default:
1352
+ return 'secondary';
1353
+ }
1354
+ };
1355
+ <\/script>
1356
+ ```
1357
+
1358
+ ## Column Toggle
1359
+
1360
+ Columns can be shown, hidden and reordered through a popover that holds a draggable, checkable list of the available columns.
1361
+
1362
+ ```vue
1363
+ <template>
1364
+ <div>
1365
+ <div class="mb-3 flex items-center justify-end">
1366
+ <Button variant="outlined" severity="secondary" size="small" @click="toggleColumns">
1367
+ <Cog />
1368
+ Columns
1369
+ </Button>
1370
+ <Popover ref="columnsPopover" :pt="{ content: { class: 'p-0!' } }">
1371
+ <div class="w-72">
1372
+ <div class="flex items-center justify-between gap-2 px-4 py-3 border-b border-surface-200 dark:border-surface-700">
1373
+ <span class="text-sm font-semibold">Columns</span>
1374
+ <Button variant="text" size="small" severity="secondary" @click="resetOptions">
1375
+ <Refresh />
1376
+ Reset
1377
+ </Button>
1378
+ </div>
1379
+ <div class="py-2 max-h-80 overflow-auto">
1380
+ <div
1381
+ v-for="(col, idx) in columns"
1382
+ :key="col.field"
1383
+ draggable="true"
1384
+ :class="[
1385
+ 'flex items-center gap-2 px-3 py-1.5 mx-1 rounded-md cursor-move select-none transition',
1386
+ draggedIndex === idx ? 'opacity-40' : '',
1387
+ dragOverIndex === idx && draggedIndex !== idx ? 'bg-primary-50 dark:bg-primary-900/30 ring-1 ring-primary-400' : 'hover:bg-surface-100 dark:hover:bg-surface-800'
1388
+ ]"
1389
+ @dragstart="onDragStart($event, idx)"
1390
+ @dragover.prevent="onDragOver(idx)"
1391
+ @drop="onDrop(idx)"
1392
+ @dragend="onDragEnd"
1393
+ >
1394
+ <Bars class="w-3.5 h-3.5 text-surface-400 dark:text-surface-500" />
1395
+ <label class="flex-1 flex items-center gap-2 cursor-pointer" @click.stop>
1396
+ <Checkbox :modelValue="visibleFields.includes(col.field)" binary @update:modelValue="toggleVisible(col.field)" />
1397
+ <span class="text-sm">{{ col.header }}</span>
1398
+ </label>
1399
+ </div>
1400
+ </div>
1401
+ </div>
1402
+ </Popover>
1403
+ </div>
1404
+ <TreeTable v-model:expandedKeys="expandedKeys" :value="nodes" tableStyle="min-width: 40rem">
1405
+ <Column v-for="col in visibleColumns" :key="col.field" :field="col.field" :header="col.header" :expander="col.field === 'name'">
1406
+ <template #body="{ node }">
1407
+ <span v-if="col.field === 'name'" class="inline-flex items-center gap-2">
1408
+ <ImageIcon v-if="node.data.type === 'Picture'" />
1409
+ <VideoIcon v-else-if="node.data.type === 'Video'" />
1410
+ <Folder v-else-if="node.data.type === 'Folder'" />
1411
+ <File v-else />
1412
+ <span :class="{ 'font-medium': node.data.type === 'Folder' }">{{ node.data.name }}</span>
1413
+ </span>
1414
+ <span v-else-if="col.field === 'size'" class="text-sm text-surface-500 dark:text-surface-400">{{ node.data.size }}</span>
1415
+ <Tag v-else-if="col.field === 'type'" :value="node.data.type" :severity="getSeverity(node.data.type)" />
1416
+ <code v-else-if="col.field === 'key'" class="text-xs text-surface-500 dark:text-surface-400">{{ node.key }}</code>
1417
+ <template v-else-if="col.field === 'level'">{{ getLevel(node) }}</template>
1418
+ <template v-else-if="col.field === 'hasChildren'">{{ node.children && node.children.length ? 'Yes' : 'No' }}</template>
1419
+ </template>
1420
+ </Column>
1421
+ <template #empty>
1422
+ <div class="flex flex-col items-center justify-center gap-3 py-24 text-center">
1423
+ <div class="relative">
1424
+ <div class="w-16 h-16 rounded-full bg-surface-100 dark:bg-surface-800 flex items-center justify-center">
1425
+ <Database class="w-8 h-8 text-surface-400 dark:text-surface-500" />
1426
+ </div>
1427
+ <span class="absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-full border-2 border-surface-0 dark:border-surface-900 bg-primary animate-pulse" />
1428
+ </div>
1429
+ <div>
1430
+ <p class="m-0 font-semibold text-surface-900 dark:text-surface-0">Loading tree</p>
1431
+ <p class="mt-1 text-sm text-surface-500 dark:text-surface-400">Hang tight, the data is on its way.</p>
1432
+ </div>
1433
+ </div>
1434
+ </template>
1435
+ </TreeTable>
1436
+ </div>
1437
+ </template>
1438
+
1439
+ <script setup>
1440
+ import { ref, computed } from 'vue';
1441
+ import { NodeService } from '@/service/NodeService';
1442
+ import Bars from '@primeicons/vue/bars';
1443
+ import Cog from '@primeicons/vue/cog';
1444
+ import Database from '@primeicons/vue/database';
1445
+ import File from '@primeicons/vue/file';
1446
+ import Folder from '@primeicons/vue/folder';
1447
+ import ImageIcon from '@primeicons/vue/image';
1448
+ import Refresh from '@primeicons/vue/refresh';
1449
+ import VideoIcon from '@primeicons/vue/video';
1450
+
1451
+ const INITIAL_COLUMNS = [
1452
+ { field: 'name', header: 'Name' },
1453
+ { field: 'size', header: 'Size' },
1454
+ { field: 'type', header: 'Type' },
1455
+ { field: 'key', header: 'Key' },
1456
+ { field: 'level', header: 'Level' },
1457
+ { field: 'hasChildren', header: 'Has Children' }
1458
+ ];
1459
+ const DEFAULT_VISIBLE_FIELDS = ['name', 'size', 'type'];
1460
+
1461
+ const nodes = ref(null);
1462
+ const expandedKeys = ref({ 0: true });
1463
+ const columns = ref(INITIAL_COLUMNS.map((col) => ({ ...col })));
1464
+ const visibleFields = ref([...DEFAULT_VISIBLE_FIELDS]);
1465
+ const draggedIndex = ref(null);
1466
+ const dragOverIndex = ref(null);
1467
+ const columnsPopover = ref();
1468
+
1469
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data.slice(0, 5)));
1470
+
1471
+ const visibleColumns = computed(() => columns.value.filter((col) => visibleFields.value.includes(col.field)));
1472
+
1473
+ const toggleColumns = (event) => columnsPopover.value.toggle(event);
1474
+
1475
+ const toggleVisible = (field) => {
1476
+ visibleFields.value = visibleFields.value.includes(field) ? visibleFields.value.filter((f) => f !== field) : [...visibleFields.value, field];
1477
+ };
1478
+
1479
+ const resetOptions = () => {
1480
+ columns.value = INITIAL_COLUMNS.map((col) => ({ ...col }));
1481
+ visibleFields.value = [...DEFAULT_VISIBLE_FIELDS];
1482
+ };
1483
+
1484
+ const resetDrag = () => {
1485
+ draggedIndex.value = null;
1486
+ dragOverIndex.value = null;
1487
+ };
1488
+
1489
+ const onDragStart = (event, index) => {
1490
+ draggedIndex.value = index;
1491
+ event.dataTransfer.effectAllowed = 'move';
1492
+ };
1493
+
1494
+ const onDragOver = (index) => (dragOverIndex.value = index);
1495
+
1496
+ const onDrop = (index) => {
1497
+ if (draggedIndex.value === null || draggedIndex.value === index) return resetDrag();
1498
+
1499
+ const next = [...columns.value];
1500
+ const [moved] = next.splice(draggedIndex.value, 1);
1501
+
1502
+ next.splice(index, 0, moved);
1503
+ columns.value = next;
1504
+ resetDrag();
1505
+ };
1506
+
1507
+ const onDragEnd = () => resetDrag();
1508
+
1509
+ const getLevel = (node) => String(node.key).split('-').length - 1;
1510
+
1511
+ const getSeverity = (type) => {
1512
+ switch (type) {
1513
+ case 'Folder':
1514
+ return 'warn';
1515
+ case 'Document':
1516
+ return 'info';
1517
+ case 'Resume':
1518
+ return 'info';
1519
+ case 'Application':
1520
+ return 'info';
1521
+ case 'PDF':
1522
+ return 'info';
1523
+ case 'Picture':
1524
+ return 'success';
1525
+ case 'Video':
1526
+ return 'success';
1527
+ case 'Text':
1528
+ return 'secondary';
1529
+ case 'Zip':
1530
+ return 'secondary';
1531
+ case 'Link':
1532
+ return 'secondary';
1533
+ default:
1534
+ return 'secondary';
1535
+ }
1536
+ };
1537
+ <\/script>
1538
+ ```
1539
+
1540
+ ## Filter
1541
+
1542
+ Filtering is enabled by adding a filter template to a Column along with the filters property. The match strategy of a column is configured with filterMatchMode , and a global entry in filters searches across all columns at once. The filterMode defaults to lenient so when a node matches, its descendants are kept without further filtering.
1543
+
1544
+ ```vue
1545
+ <template>
1546
+ <div>
1547
+ <div class="mb-3 flex justify-end">
1548
+ <IconField class="w-full sm:max-w-xs">
1549
+ <InputIcon><Search /></InputIcon>
1550
+ <InputText v-model="filters['global']" type="search" placeholder="Keyword search" class="w-full" />
1551
+ </IconField>
1552
+ </div>
1553
+ <TreeTable :value="nodes" :filters="filters" tableStyle="min-width: 40rem">
1554
+ <Column field="name" header="Name" expander filterMatchMode="contains" style="width: 50%">
1555
+ <template #body="{ node }">
1556
+ <span class="inline-flex items-center gap-2">
1557
+ <ImageIcon v-if="node.data.type === 'Picture'" />
1558
+ <VideoIcon v-else-if="node.data.type === 'Video'" />
1559
+ <Folder v-else-if="node.data.type === 'Folder'" />
1560
+ <File v-else />
1561
+ <span :class="{ 'font-medium': node.data.type === 'Folder' }">{{ node.data.name }}</span>
1562
+ </span>
1563
+ </template>
1564
+ <template #filter>
1565
+ <InputText v-model="filters['name']" type="text" placeholder="Search name..." size="small" fluid />
1566
+ </template>
1567
+ </Column>
1568
+ <Column field="size" header="Size" style="width: 20%">
1569
+ <template #body="{ node }">
1570
+ <span class="text-sm text-surface-500 dark:text-surface-400">{{ node.data.size }}</span>
1571
+ </template>
1572
+ </Column>
1573
+ <Column field="type" header="Type" filterMatchMode="equals" style="width: 30%">
1574
+ <template #body="{ node }">
1575
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
1576
+ </template>
1577
+ <template #filter>
1578
+ <Select v-model="filters['type']" :options="typeOptions" optionLabel="label" optionValue="value" placeholder="Any" size="small" fluid />
1579
+ </template>
1580
+ </Column>
1581
+ <template #empty>
1582
+ <div class="flex flex-col items-center justify-center gap-3 py-24 text-center">
1583
+ <div class="relative">
1584
+ <div class="w-16 h-16 rounded-full bg-surface-100 dark:bg-surface-800 flex items-center justify-center">
1585
+ <Database class="w-8 h-8 text-surface-400 dark:text-surface-500" />
1586
+ </div>
1587
+ <span class="absolute -bottom-0.5 -right-0.5 w-4 h-4 rounded-full border-2 border-surface-0 dark:border-surface-900 bg-primary animate-pulse" />
1588
+ </div>
1589
+ <div>
1590
+ <p class="m-0 font-semibold text-surface-900 dark:text-surface-0">Loading tree</p>
1591
+ <p class="mt-1 text-sm text-surface-500 dark:text-surface-400">Hang tight, the data is on its way.</p>
1592
+ </div>
1593
+ </div>
1594
+ </template>
1595
+ </TreeTable>
1596
+ </div>
1597
+ </template>
1598
+
1599
+ <script setup>
1600
+ import { ref, onMounted } from 'vue';
1601
+ import { NodeService } from '@/service/NodeService';
1602
+ import Database from '@primeicons/vue/database';
1603
+ import File from '@primeicons/vue/file';
1604
+ import Folder from '@primeicons/vue/folder';
1605
+ import ImageIcon from '@primeicons/vue/image';
1606
+ import Search from '@primeicons/vue/search';
1607
+ import VideoIcon from '@primeicons/vue/video';
1608
+
1609
+ const nodes = ref();
1610
+ const filters = ref({});
1611
+ const typeOptions = ref([
1612
+ { label: 'Any', value: '' },
1613
+ { label: 'Folder', value: 'Folder' },
1614
+ { label: 'Document', value: 'Document' },
1615
+ { label: 'Text', value: 'Text' },
1616
+ { label: 'Picture', value: 'Picture' },
1617
+ { label: 'Video', value: 'Video' }
1618
+ ]);
1619
+
1620
+ onMounted(() => {
1621
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
1622
+ });
1623
+
1624
+ const getSeverity = (type) => {
1625
+ switch (type) {
1626
+ case 'Folder':
1627
+ return 'warn';
1628
+ case 'Document':
1629
+ case 'Resume':
1630
+ case 'Application':
1631
+ case 'PDF':
1632
+ return 'info';
1633
+ case 'Picture':
1634
+ case 'Video':
1635
+ return 'success';
1636
+ case 'Text':
1637
+ case 'Zip':
1638
+ case 'Link':
1639
+ return 'secondary';
1640
+ default:
1641
+ return 'secondary';
1642
+ }
1643
+ };
1644
+ <\/script>
1645
+ ```
1646
+
1647
+ ## Lazy Load
1648
+
1649
+ Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking corresponding callbacks everytime paging , sorting and filtering occurs. Sample below imitates lazy loading data from a remote datasource using an in-memory list and timeouts to mimic network connection. Enabling the lazy property and assigning the logical number of rows to totalRecords by doing a projection query are the key elements of the implementation so that paginator displays the UI assuming there are actually records of totalRecords size although in reality they are not present on page, only the records that are displayed on the current page exist. In addition, only the root elements should be loaded, children can be loaded on demand using nodeExpand callback.
1650
+
1651
+ ```vue
1652
+ <template>
1653
+ <div>
1654
+ <TreeTable :value="nodes" :lazy="true" :paginator="true" :rows="rows" :loading="loading"
1655
+ @nodeExpand="onExpand" @page="onPage" :totalRecords="totalRecords" tableStyle="min-width: 50rem">
1656
+ <Column field="name" header="Name" :expander="true"></Column>
1657
+ <Column field="size" header="Size"></Column>
1658
+ <Column field="type" header="Type">
1659
+ <template #body="{ node }">
1660
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
1661
+ </template>
1662
+ </Column>
1663
+ </TreeTable>
1664
+ </div>
1665
+ </template>
1666
+
1667
+ <script setup>
1668
+ import { ref, onMounted } from 'vue';
1669
+
1670
+ onMounted(() => {
1671
+ loading.value = true;
1672
+
1673
+ setTimeout(() => {
1674
+ loading.value = false;
1675
+ nodes.value = loadNodes(0, rows.value);
1676
+ totalRecords.value = 1000;
1677
+ }, 1000);
1678
+ });
1679
+
1680
+ const nodes = ref();
1681
+ const rows = ref(10);
1682
+ const loading = ref(false);
1683
+ const totalRecords = ref(0);
1684
+ const onExpand = (node) => {
1685
+ if (!node.children) {
1686
+ loading.value = true;
1687
+
1688
+ setTimeout(() => {
1689
+ let lazyNode = {...node};
1690
+
1691
+ lazyNode.children = [
1692
+ {
1693
+ data: {
1694
+ name: lazyNode.data.name + ' - 0',
1695
+ size: Math.floor(Math.random() * 1000) + 1 + 'kb',
1696
+ type: 'File'
1697
+ },
1698
+ },
1699
+ {
1700
+ data: {
1701
+ name: lazyNode.data.name + ' - 1',
1702
+ size: Math.floor(Math.random() * 1000) + 1 + 'kb',
1703
+ type: 'File'
1704
+ }
1705
+ }
1706
+ ];
1707
+
1708
+ let newNodes = nodes.value.map(n => {
1709
+ if (n.key === node.key) {
1710
+ n = lazyNode;
1711
+ }
1712
+
1713
+ return n;
1714
+ });
1715
+
1716
+ loading.value = false;
1717
+ nodes.value = newNodes;
1718
+ }, 250);
1719
+ }
1720
+ };
1721
+ const onPage = (event) => {
1722
+ loading.value = true;
1723
+
1724
+ //imitate delay of a backend call
1725
+ setTimeout(() => {
1726
+ loading.value = false;
1727
+ nodes.value = loadNodes(event.first, rows.value);
1728
+ }, 1000);
1729
+ };
1730
+ const loadNodes = (first, rows) => {
1731
+ let nodes = [];
1732
+
1733
+ for(let i = 0; i < rows; i++) {
1734
+ let node = {
1735
+ key: (first + i),
1736
+ data: {
1737
+ name: 'Item ' + (first + i),
1738
+ size: Math.floor(Math.random() * 1000) + 1 + 'kb',
1739
+ type: 'Type ' + (first + i)
1740
+ },
1741
+ leaf: false
1742
+ };
1743
+
1744
+ nodes.push(node);
1745
+ }
1746
+
1747
+ return nodes;
1748
+ };
1749
+ const getSeverity = (type) => {
1750
+ switch (type) {
1751
+ case 'Folder':
1752
+ return 'warn';
1753
+ case 'Document':
1754
+ return 'info';
1755
+ case 'Picture':
1756
+ return 'success';
1757
+ case 'Video':
1758
+ return 'success';
1759
+ case 'Text':
1760
+ return 'secondary';
1761
+ default:
1762
+ return 'secondary';
1763
+ }
1764
+ };
1765
+ <\/script>
1766
+ ```
1767
+
1768
+ ## Overlay
1769
+
1770
+ The loading property displays a mask overlay with a spinner while data is being fetched. Use the loadingicon slot to customize the overlay content.
1771
+
1772
+ ```vue
1773
+ <template>
1774
+ <div>
1775
+ <div class="mb-3 flex items-center justify-between gap-3">
1776
+ <span class="text-sm text-surface-500 dark:text-surface-400">Click refresh to simulate a network fetch.</span>
1777
+ <Button size="small" :disabled="loading" @click="refresh">
1778
+ <Refresh />
1779
+ Refresh
1780
+ </Button>
1781
+ </div>
1782
+ <TreeTable v-model:expandedKeys="expandedKeys" :value="nodes" :loading="loading" tableStyle="min-width: 40rem">
1783
+ <Column field="name" header="Name" expander style="width: 50%">
1784
+ <template #body="{ node }">
1785
+ <span class="inline-flex items-center gap-2">
1786
+ <ImageIcon v-if="node.data.type === 'Picture'" />
1787
+ <VideoIcon v-else-if="node.data.type === 'Video'" />
1788
+ <Folder v-else-if="node.data.type === 'Folder'" />
1789
+ <File v-else />
1790
+ <span :class="{ 'font-medium': node.data.type === 'Folder' }">{{ node.data.name }}</span>
1791
+ </span>
1792
+ </template>
1793
+ </Column>
1794
+ <Column field="size" header="Size" style="width: 20%">
1795
+ <template #body="{ node }">
1796
+ <span class="text-sm text-surface-500 dark:text-surface-400">{{ node.data.size }}</span>
1797
+ </template>
1798
+ </Column>
1799
+ <Column field="type" header="Type" style="width: 30%">
1800
+ <template #body="{ node }">
1801
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
1802
+ </template>
1803
+ </Column>
1804
+ <template #loadingicon>
1805
+ <div class="flex flex-col items-center gap-2">
1806
+ <Spinner :size="40" class="animate-spin text-primary" />
1807
+ <span class="text-sm text-surface-600 dark:text-surface-300">Loading nodes…</span>
1808
+ </div>
1809
+ </template>
1810
+ </TreeTable>
1811
+ </div>
1812
+ </template>
1813
+
1814
+ <script setup>
1815
+ import { ref, onMounted } from 'vue';
1816
+ import { NodeService } from '@/service/NodeService';
1817
+ import File from '@primeicons/vue/file';
1818
+ import Folder from '@primeicons/vue/folder';
1819
+ import ImageIcon from '@primeicons/vue/image';
1820
+ import Refresh from '@primeicons/vue/refresh';
1821
+ import Spinner from '@primeicons/vue/spinner';
1822
+ import VideoIcon from '@primeicons/vue/video';
1823
+
1824
+ const nodes = ref();
1825
+ const loading = ref(false);
1826
+ const expandedKeys = ref({ 0: true });
1827
+
1828
+ onMounted(() => {
1829
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
1830
+ });
1831
+
1832
+ const refresh = () => {
1833
+ loading.value = true;
1834
+ setTimeout(() => {
1835
+ NodeService.getTreeTableNodesSmall().then((data) => {
1836
+ nodes.value = data;
1837
+ loading.value = false;
1838
+ });
1839
+ }, 1500);
1840
+ };
1841
+
1842
+ const getSeverity = (type) => {
1843
+ switch (type) {
1844
+ case 'Folder':
1845
+ return 'warn';
1846
+ case 'Document':
1847
+ case 'Resume':
1848
+ case 'Application':
1849
+ case 'PDF':
1850
+ return 'info';
1851
+ case 'Picture':
1852
+ case 'Video':
1853
+ return 'success';
1854
+ case 'Text':
1855
+ case 'Zip':
1856
+ case 'Link':
1857
+ return 'secondary';
1858
+ default:
1859
+ return 'secondary';
1860
+ }
1861
+ };
1862
+ <\/script>
1863
+ ```
1864
+
1865
+ ## Skeleton
1866
+
1867
+ Skeleton component can be used as a placeholder during the loading process.
1868
+
1869
+ ```vue
1870
+ <template>
1871
+ <div>
1872
+ <TreeTable :value="nodes" tableStyle="min-width: 50rem">
1873
+ <Column field="name" header="Name" style="width: 34%">
1874
+ <template #body>
1875
+ <Skeleton />
1876
+ </template>
1877
+ </Column>
1878
+ <Column field="size" header="Size" style="width: 33%">
1879
+ <template #body>
1880
+ <Skeleton />
1881
+ </template>
1882
+ </Column>
1883
+ <Column field="type" header="Type" style="width: 33%">
1884
+ <template #body>
1885
+ <Skeleton />
1886
+ </template>
1887
+ </Column>
1888
+ </TreeTable>
1889
+ </div>
1890
+ </template>
1891
+
1892
+ <script setup>
1893
+ import { ref, onMounted } from 'vue';
1894
+
1895
+ onMounted(() => {
1896
+ nodes.value = Array.from({ length: 10 }).map((_, i) => ({id: i.toString()}));
1897
+ });
1898
+
1899
+ const nodes = ref();
1900
+
1901
+ <\/script>
1902
+ ```
1903
+
1904
+ ## Empty State
1905
+
1906
+ A custom empty state is displayed through the empty slot when the value is an empty array.
1907
+
1908
+ ```vue
1909
+ <template>
1910
+ <div>
1911
+ <TreeTable :value="[]" tableStyle="min-width: 40rem">
1912
+ <template #empty>
1913
+ <div class="flex flex-col items-center justify-center gap-3 py-10 text-center">
1914
+ <div class="w-14 h-14 rounded-full bg-surface-100 dark:bg-surface-800 flex items-center justify-center">
1915
+ <Folder class="w-7 h-7 text-surface-400 dark:text-surface-500" />
1916
+ </div>
1917
+ <div>
1918
+ <p class="m-0 font-semibold text-surface-900 dark:text-surface-0">No folders yet</p>
1919
+ <p class="mt-1 text-sm text-surface-500 dark:text-surface-400">Create your first folder to start building a tree.</p>
1920
+ </div>
1921
+ <Button size="small">
1922
+ <Plus />
1923
+ New Folder
1924
+ </Button>
1925
+ </div>
1926
+ </template>
1927
+ <Column field="name" header="Name" expander style="width: 50%"></Column>
1928
+ <Column field="size" header="Size" style="width: 20%"></Column>
1929
+ <Column field="type" header="Type" style="width: 30%"></Column>
1930
+ </TreeTable>
1931
+ </div>
1932
+ </template>
1933
+
1934
+ <script setup>
1935
+ import Folder from '@primeicons/vue/folder';
1936
+ import Plus from '@primeicons/vue/plus';
1937
+ <\/script>
1938
+ ```
1939
+
1940
+ ## Dynamic Columns
1941
+
1942
+ Columns can be created programmatically.
1943
+
1944
+ ```vue
1945
+ <template>
1946
+ <div>
1947
+ <TreeTable :value="nodes" tableStyle="min-width: 50rem">
1948
+ <Column v-for="col of columns" :key="col.field" :field="col.field" :header="col.header" :expander="col.expander"></Column>
1949
+ </TreeTable>
1950
+ </div>
1951
+ </template>
1952
+
1953
+ <script setup>
1954
+ import { ref, onMounted } from 'vue';
1955
+ import { NodeService } from '@/service/NodeService';
1956
+
1957
+ onMounted(() => {
1958
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
1959
+ });
1960
+
1961
+ const nodes = ref();
1962
+ const columns = ref([
1963
+ { field: 'name', header: 'Name', expander: true },
1964
+ { field: 'size', header: 'Size' },
1965
+ { field: 'type', header: 'Type' }
1966
+ ]);
1967
+ <\/script>
1968
+ ```
1969
+
1970
+ ## Template
1971
+
1972
+ Custom content at header and footer slots are supported via templating.
1973
+
1974
+ ```vue
1975
+ <template>
1976
+ <div>
1977
+ <TreeTable :value="nodes" tableStyle="min-width: 50rem">
1978
+ <template #header>
1979
+ <div class="text-xl font-bold">File Viewer</div>
1980
+ </template>
1981
+ <Column field="name" header="Name" expander style="width: 250px"></Column>
1982
+ <Column field="size" header="Size" style="width: 150px"></Column>
1983
+ <Column field="type" header="Type" style="width: 150px">
1984
+ <template #body="{ node }">
1985
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
1986
+ </template>
1987
+ </Column>
1988
+ <Column style="width: 10rem">
1989
+ <template #body>
1990
+ <div class="flex flex-wrap gap-2">
1991
+ <Button type="button" iconOnly rounded>
1992
+ <Search />
1993
+ </Button>
1994
+ <Button type="button" iconOnly rounded severity="success">
1995
+ <Pencil />
1996
+ </Button>
1997
+ </div>
1998
+ </template>
1999
+ </Column>
2000
+ <template #footer>
2001
+ <div class="flex justify-start">
2002
+ <Button severity="warn">
2003
+ <Refresh />
2004
+ Reload
2005
+ </Button>
2006
+ </div>
2007
+ </template>
2008
+ </TreeTable>
2009
+ </div>
2010
+ </template>
2011
+
2012
+ <script setup>
2013
+ import Pencil from '@primeicons/vue/pencil';
2014
+ import Refresh from '@primeicons/vue/refresh';
2015
+ import Search from '@primeicons/vue/search';
2016
+ import { ref, onMounted } from 'vue';
2017
+ import { NodeService } from '@/service/NodeService';
2018
+
2019
+ onMounted(() => {
2020
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
2021
+ });
2022
+
2023
+ const nodes = ref();
2024
+ const getSeverity = (type) => {
2025
+ switch (type) {
2026
+ case 'Folder':
2027
+ return 'warn';
2028
+ case 'Document':
2029
+ return 'info';
2030
+ case 'Picture':
2031
+ return 'success';
2032
+ case 'Video':
2033
+ return 'success';
2034
+ case 'Text':
2035
+ return 'secondary';
2036
+ default:
2037
+ return 'secondary';
2038
+ }
2039
+ };
2040
+ <\/script>
2041
+ ```
2042
+
2043
+ ## Controlled
2044
+
2045
+ Expansion state is controlled with expandedKeys property. The expandedKeys should be an object whose keys refer to the node key and values represent the expanded state e.g. &#123;'0-0': true&#125; .
2046
+
2047
+ ```vue
2048
+ <template>
2049
+ <div>
2050
+ <Button @click="toggleApplications">Toggle Applications</Button>
2051
+ <TreeTable v-model:expandedKeys="expandedKeys" :value="nodes" class="mt-6" tableStyle="min-width: 50rem">
2052
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
2053
+ <Column field="size" header="Size" style="width: 33%"></Column>
2054
+ <Column field="type" header="Type" style="width: 33%">
2055
+ <template #body="{ node }">
2056
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
2057
+ </template>
2058
+ </Column>
2059
+ </TreeTable>
2060
+ </div>
2061
+ </template>
2062
+
2063
+ <script setup>
2064
+ import { ref, onMounted } from 'vue';
2065
+ import { NodeService } from '@/service/NodeService';
2066
+
2067
+ onMounted(() => {
2068
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
2069
+ });
2070
+
2071
+ const nodes = ref();
2072
+ const expandedKeys = ref({});
2073
+ const toggleApplications = () => {
2074
+ let _expandedKeys = { ...expandedKeys.value };
2075
+
2076
+ if (_expandedKeys['0']) delete _expandedKeys['0'];
2077
+ else _expandedKeys['0'] = true;
2078
+
2079
+ expandedKeys.value = _expandedKeys;
2080
+ }
2081
+ const getSeverity = (type) => {
2082
+ switch (type) {
2083
+ case 'Folder':
2084
+ return 'warn';
2085
+ case 'Document':
2086
+ return 'info';
2087
+ case 'Picture':
2088
+ return 'success';
2089
+ case 'Video':
2090
+ return 'success';
2091
+ case 'Text':
2092
+ return 'secondary';
2093
+ default:
2094
+ return 'secondary';
2095
+ }
2096
+ };
2097
+ <\/script>
2098
+ ```
2099
+
2100
+ ## ContextMenu
2101
+
2102
+ TreeTable has exclusive integration with ContextMenu using the contextMenu event to open a menu on right click along with contextMenuSelection property and row-contextmenu event to control the selection via the menu.
2103
+
2104
+ ```vue
2105
+ <template>
2106
+ <div>
2107
+ <ContextMenu ref="cm" :model="menuModel" @hide="selectedNode = null" />
2108
+ <TreeTable v-model:contextMenuSelection="selectedNode" :value="nodes" contextMenu @row-contextmenu="onRowContextMenu" tableStyle="min-width: 50rem">
2109
+ <Column field="name" header="Name" expander style="width: 34%"></Column>
2110
+ <Column field="size" header="Size" style="width: 33%"></Column>
2111
+ <Column field="type" header="Type" style="width: 33%">
2112
+ <template #body="{ node }">
2113
+ <Tag :value="node.data.type" :severity="getSeverity(node.data.type)" />
2114
+ </template>
2115
+ </Column>
2116
+ </TreeTable>
2117
+ <Toast />
2118
+ </div>
2119
+ </template>
2120
+
2121
+ <script setup>
2122
+ import Search from '@primeicons/vue/search';
2123
+ import Times from '@primeicons/vue/times';
2124
+ import { ref, onMounted } from 'vue';
2125
+ import { useToast } from 'primevue/usetoast';
2126
+ import { NodeService } from '@/service/NodeService';
2127
+
2128
+ onMounted(() => {
2129
+ NodeService.getTreeTableNodesSmall().then((data) => (nodes.value = data));
2130
+ });
2131
+
2132
+ const cm = ref();
2133
+ const toast = useToast();
2134
+ const nodes = ref();
2135
+ const selectedNode = ref();
2136
+ const menuModel = ref(
2137
+ [
2138
+ { label: 'View', icon: Search, command: () => this.viewNode(this.selectedNode) },
2139
+ { label: 'Delete', icon: Times, command: () => this.deleteNode(this.selectedNode) }
2140
+ ]
2141
+ );
2142
+
2143
+ const onRowContextMenu = (event) => {
2144
+ cm.value.show(event.originalEvent);
2145
+ };
2146
+
2147
+ const viewNode = (product) => {
2148
+ toast.add({severity: 'info', summary: 'Node Selected', detail: node.data.name, life: 3000});
2149
+ };
2150
+
2151
+ const deleteProduct = (node) => {
2152
+ nodes.value = filterNodes(nodes.value, node.key);
2153
+ toast.add({severity: 'error', summary: 'Node Deleted', detail: node.data.name, life: 3000});
2154
+ selectedProduct.value = null;
2155
+ };
2156
+
2157
+ const filterNodes = (nodeList, keyToRemove) => {
2158
+ return nodes
2159
+ .map((node) => {
2160
+ if (node.key === keyToRemove) {
2161
+ return null;
2162
+ }
2163
+
2164
+ if (node.children) {
2165
+ const filteredChildren = filterNodes(node.children, keyToRemove);
2166
+
2167
+ return { ...node, children: filteredChildren };
2168
+ }
2169
+
2170
+ return node;
2171
+ })
2172
+ .filter((node) => node !== null);
2173
+ }
2174
+
2175
+ const getSeverity = (type) => {
2176
+ switch (type) {
2177
+ case 'Folder':
2178
+ return 'warn';
2179
+ case 'Document':
2180
+ return 'info';
2181
+ case 'Picture':
2182
+ return 'success';
2183
+ case 'Video':
2184
+ return 'success';
2185
+ case 'Text':
2186
+ return 'secondary';
2187
+ default:
2188
+ return 'secondary';
2189
+ }
2190
+ };
2191
+ <\/script>
2192
+ ```
2193
+
2194
+ ## Accessibility
2195
+
2196
+ Screen Reader DataTable uses a treegrid element whose attributes can be extended with the tableProps option. This property allows passing aria roles and attributes like aria-label and aria-describedby to define the table for readers. Default role of the table is table . Header, body and footer elements use rowgroup , rows use row role, header cells have columnheader and body cells use cell roles. Sortable headers utilizer aria-sort attribute either set to "ascending" or "descending". Row elements manage aria-expanded for state along with aria-posinset , aria-setsize and aria-level attribute to define the hierachy. When selection is enabled, aria-selected is set to true on a row. In checkbox mode, TreeTable component uses a hidden native checkbox element. Editable cells use custom templating so you need to manage aria roles and attributes manually if required. Paginator is a standalone component used inside the DataTable, refer to the paginator for more information about the accessibility features. Sortable Headers Keyboard Support Key Function tab Moves through the headers. enter Sorts the column. space Sorts the column. Keyboard Support Key Function tab Moves focus to the first selected node when focus enters the component, if there is none then first element receives the focus. If focus is already inside the component, moves focus to the next focusable element in the page tab sequence. shift + tab Moves focus to the last selected node when focus enters the component, if there is none then first element receives the focus. If focus is already inside the component, moves focus to the previous focusable element in the page tab sequence. enter Selects the focused treenode. space Selects the focused treenode. down arrow Moves focus to the next treenode. up arrow Moves focus to the previous treenode. right arrow If node is closed, opens the node otherwise moves focus to the first child node. left arrow If node is open, closes the node otherwise moves focus to the parent node. home Moves focus to the first same-level node. end Moves focus to the last same-level node.
2197
+
2198
+ ## Tree Table API
2199
+
2200
+ ### Props
2201
+
2202
+ | Name |Type |Default |Description |
2203
+ | --- | --- | --- | --- |
2204
+ | value | TreeNode[] | - | An array of treenodes. |
2205
+ | dataKey | string \| Function | "key" | Name of the field that uniquely identifies the a record in the data. |
2206
+ | expandedKeys | TreeTableExpandedKeys | - | A map of keys to represent the state of the tree expansion state in controlled mode. |
2207
+ | selectionKeys | TreeTableSelectionKeys | - | A map of keys to control the selection state. |
2208
+ | selectionMode | HintedString<"single" \| "multiple" \| "checkbox"> | - | Defines the selection mode. |
2209
+ | metaKeySelection | boolean | false | Defines how multiple items can be selected, when true metaKey needs to be pressed to select or unselect an item and when set to false selection of each item can be toggled individually. On touch enabled devices, metaKeySelection is turned off automatically. |
2210
+ | contextMenu | boolean | false | Enables context menu integration. |
2211
+ | contextMenuSelection | any | - | Selected row instance with the ContextMenu. |
2212
+ | rows | number | - | Number of rows to display per page. |
2213
+ | first | number | 0 | Index of the first row to be displayed. |
2214
+ | totalRecords | number | - | Number of total records, defaults to length of value when not defined. |
2215
+ | paginator | boolean | false | When specified as true, enables the pagination. |
2216
+ | paginatorPosition | HintedString<"top" \| "bottom" \| "both"> | bottom | Position of the paginator, options are 'top','bottom' or 'both'. |
2217
+ | alwaysShowPaginator | boolean | true | Whether to show it even there is only one page. |
2218
+ | paginatorTemplate | string | FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown | Template of the paginator. It can be customized using the template property using the predefined keys. Here are the available elements that can be placed inside a paginator in any order. - FirstPageLink - PrevPageLink - PageLinks - NextPageLink - LastPageLink - RowsPerPageDropdown - JumpToPageDropdown - JumpToPageInput - CurrentPageReport |
2219
+ | pageLinkSize | number | 5 | Number of page links to display. |
2220
+ | rowsPerPageOptions | number[] | - | Array of integer values to display inside rows per page dropdown. |
2221
+ | currentPageReportTemplate | string | '({currentPage} of {totalPages})' | Template of the current page report element. It displays information about the pagination state. - {currentPage} - {totalPages} - {rows} - {first} - {last} - {totalRecords} |
2222
+ | lazy | boolean | false | Defines if data is loaded and interacted with in lazy manner. |
2223
+ | loading | boolean | false | Displays a loader to indicate data load is in progress. |
2224
+ | loadingIcon | string | - | The icon to show while indicating data load is in progress. |
2225
+ | loadingMode | HintedString<"icon" \| "mask"> | mask | Loading mode display. |
2226
+ | rowHover | boolean | false | When enabled, background of the rows change on hover. |
2227
+ | autoLayout | boolean | false | Whether the cell widths scale according to their content or not. |
2228
+ | sortField | string \| Function | - | Property name or a getter function of a row data used for sorting by default. |
2229
+ | sortOrder | number | - | Order to sort the data by default. |
2230
+ | defaultSortOrder | number | 1 | Default sort order of an unsorted column. |
2231
+ | multiSortMeta | null \| TreeTableSortMeta[] | - | An array of SortMeta objects to sort the data by default in multiple sort mode. |
2232
+ | sortMode | HintedString<"single" \| "multiple"> | single | Defines whether sorting works on single column or on multiple columns. |
2233
+ | removableSort | boolean | false | When enabled, columns can have an un-sorted state. |
2234
+ | filters | TreeTableFilterMeta | - | Filters object with key-value pairs to define the filters. |
2235
+ | filterMode | HintedString<"lenient" \| "strict"> | lenient | Mode for filtering. |
2236
+ | filterLocale | string | - | Locale to use in filtering. The default locale is the host environment's current locale. |
2237
+ | resizableColumns | boolean | false | When enabled, columns can be resized using drag and drop. |
2238
+ | columnResizeMode | HintedString<"fit" \| "expand"> | fit | Defines whether the overall table width should change on column resize. |
2239
+ | indentation | number | 1 | Indentation factor as rem value for children nodes. |
2240
+ | showGridlines | boolean | false | Whether to show grid lines between cells. |
2241
+ | scrollable | boolean | false | When specified, enables horizontal and/or vertical scrolling. |
2242
+ | scrollHeight | HintedString<"flex"> | - | Height of the scroll viewport in fixed pixels or the 'flex' keyword for a dynamic size. |
2243
+ | size | HintedString<"small" \| "large"> | - | Defines the size of the table. |
2244
+ | tableStyle | string \| object | - | Inline style of the table element. |
2245
+ | tableClass | string \| object | - | Style class of the table element. |
2246
+ | tableProps | any | - | Props to pass to the table element. |
2247
+ | dt | any | - | It generates scoped CSS variables using design tokens for the component. |
2248
+ | pt | PassThrough<TreeTablePassThroughOptions> | - | Used to pass attributes to DOM elements inside the component. |
2249
+ | ptOptions | any | - | Used to configure passthrough(pt) options of the component. |
2250
+ | unstyled | boolean | false | When enabled, it removes component related styles in the core. |
2251
+
2252
+ ### Pass Through Options
2253
+
2254
+ | Name |Type |Description |
2255
+ | --- | --- | --- |
2256
+ | root | TreeTablePassThroughOptionType | Used to pass attributes to the root's DOM element. |
2257
+ | loading | TreeTablePassThroughOptionType | Used to pass attributes to the loading wrapper's DOM element. |
2258
+ | mask | TreeTablePassThroughOptionType | Used to pass attributes to the mask's DOM element. |
2259
+ | loadingIcon | TreeTablePassThroughOptionType | Used to pass attributes to the loading icon's DOM element. |
2260
+ | header | TreeTablePassThroughOptionType | Used to pass attributes to the header's DOM element. |
2261
+ | pcPaginator | any | Used to pass attributes to the Paginator component. |
2262
+ | tableContainer | TreeTablePassThroughOptionType | Used to pass attributes to the table container's DOM element. |
2263
+ | table | TreeTablePassThroughOptionType | Used to pass attributes to the table's DOM element. |
2264
+ | thead | TreeTablePassThroughOptionType | Used to pass attributes to the thead's DOM element. |
2265
+ | headerRow | TreeTablePassThroughOptionType | Used to pass attributes to the header row's DOM element. |
2266
+ | tbody | TreeTablePassThroughOptionType | Used to pass attributes to the tbody's DOM element. |
2267
+ | row | TreeTablePassThroughOptionType | Used to pass attributes to the row's DOM element. |
2268
+ | emptyMessage | TreeTablePassThroughOptionType | Used to pass attributes to the empty message's DOM element. |
2269
+ | emptyMessageCell | TreeTablePassThroughOptionType | Used to pass attributes to the empty message cell's DOM element. |
2270
+ | tfoot | TreeTablePassThroughOptionType | Used to pass attributes to the tfoot's DOM element. |
2271
+ | footerRow | TreeTablePassThroughOptionType | Used to pass attributes to the footer row's DOM element. |
2272
+ | footer | TreeTablePassThroughOptionType | Used to pass attributes to the footer's DOM element. |
2273
+ | columnResizeIndicator | TreeTablePassThroughOptionType | Used to pass attributes to the column resize indicator's DOM element. |
2274
+ | column | any | Used to pass attributes to the Column helper components. |
2275
+ | hooks | any | Used to manage all lifecycle hooks. |
2276
+
2277
+ ### Theming
2278
+
2279
+ ### CSS Classes
2280
+
2281
+ | Class |Description |
2282
+ | --- | --- |
2283
+ | p-treetable | Class name of the root element |
2284
+ | p-treetable-loading | Class name of the loading element |
2285
+ | p-treetable-mask | Class name of the mask element |
2286
+ | p-treetable-loading-icon | Class name of the loading icon element |
2287
+ | p-treetable-header | Class name of the header element |
2288
+ | p-treetable-paginator-[position] | Class name of the paginator element |
2289
+ | p-treetable-table-container | Class name of the table container element |
2290
+ | p-treetable-table | Class name of the table element |
2291
+ | p-treetable-thead | Class name of the thead element |
2292
+ | p-treetable-column-resizer | Class name of the column resizer element |
2293
+ | p-treetable-column-title | Class name of the column title element |
2294
+ | p-treetable-sort-icon | Class name of the sort icon element |
2295
+ | p-treetable-sort-badge | Class name of the sort badge element |
2296
+ | p-treetable-tbody | Class name of the tbody element |
2297
+ | p-treetable-node-toggle-button | Class name of the node toggle button element |
2298
+ | p-treetable-node-toggle-icon | Class name of the node toggle icon element |
2299
+ | p-treetable-node-checkbox | Class name of the node checkbox element |
2300
+ | p-treetable-empty-message | Class name of the empty message element |
2301
+ | p-treetable-tfoot | Class name of the tfoot element |
2302
+ | p-treetable-footer | Class name of the footer element |
2303
+ | p-treetable-column-resize-indicator | Class name of the column resize indicator element |
2304
+
2305
+ ### Design Tokens
2306
+
2307
+ | Token |CSS Variable |Description |
2308
+ | --- | --- | --- |
2309
+ | treetable.transition.duration | --p-treetable-transition-duration | Transition duration of root |
2310
+ | treetable.border.color | --p-treetable-border-color | Border color of root |
2311
+ | treetable.header.background | --p-treetable-header-background | Background of header |
2312
+ | treetable.header.border.color | --p-treetable-header-border-color | Border color of header |
2313
+ | treetable.header.color | --p-treetable-header-color | Color of header |
2314
+ | treetable.header.border.width | --p-treetable-header-border-width | Border width of header |
2315
+ | treetable.header.padding | --p-treetable-header-padding | Padding of header |
2316
+ | treetable.header.cell.background | --p-treetable-header-cell-background | Background of header cell |
2317
+ | treetable.header.cell.hover.background | --p-treetable-header-cell-hover-background | Hover background of header cell |
2318
+ | treetable.header.cell.selected.background | --p-treetable-header-cell-selected-background | Selected background of header cell |
2319
+ | treetable.header.cell.border.color | --p-treetable-header-cell-border-color | Border color of header cell |
2320
+ | treetable.header.cell.color | --p-treetable-header-cell-color | Color of header cell |
2321
+ | treetable.header.cell.hover.color | --p-treetable-header-cell-hover-color | Hover color of header cell |
2322
+ | treetable.header.cell.selected.color | --p-treetable-header-cell-selected-color | Selected color of header cell |
2323
+ | treetable.header.cell.gap | --p-treetable-header-cell-gap | Gap of header cell |
2324
+ | treetable.header.cell.padding | --p-treetable-header-cell-padding | Padding of header cell |
2325
+ | treetable.header.cell.focus.ring.width | --p-treetable-header-cell-focus-ring-width | Focus ring width of header cell |
2326
+ | treetable.header.cell.focus.ring.style | --p-treetable-header-cell-focus-ring-style | Focus ring style of header cell |
2327
+ | treetable.header.cell.focus.ring.color | --p-treetable-header-cell-focus-ring-color | Focus ring color of header cell |
2328
+ | treetable.header.cell.focus.ring.offset | --p-treetable-header-cell-focus-ring-offset | Focus ring offset of header cell |
2329
+ | treetable.header.cell.focus.ring.shadow | --p-treetable-header-cell-focus-ring-shadow | Focus ring shadow of header cell |
2330
+ | treetable.column.title.font.weight | --p-treetable-column-title-font-weight | Font weight of column title |
2331
+ | treetable.column.title.font.size | --p-treetable-column-title-font-size | Font size of column title |
2332
+ | treetable.row.background | --p-treetable-row-background | Background of row |
2333
+ | treetable.row.hover.background | --p-treetable-row-hover-background | Hover background of row |
2334
+ | treetable.row.selected.background | --p-treetable-row-selected-background | Selected background of row |
2335
+ | treetable.row.color | --p-treetable-row-color | Color of row |
2336
+ | treetable.row.hover.color | --p-treetable-row-hover-color | Hover color of row |
2337
+ | treetable.row.selected.color | --p-treetable-row-selected-color | Selected color of row |
2338
+ | treetable.row.focus.ring.width | --p-treetable-row-focus-ring-width | Focus ring width of row |
2339
+ | treetable.row.focus.ring.style | --p-treetable-row-focus-ring-style | Focus ring style of row |
2340
+ | treetable.row.focus.ring.color | --p-treetable-row-focus-ring-color | Focus ring color of row |
2341
+ | treetable.row.focus.ring.offset | --p-treetable-row-focus-ring-offset | Focus ring offset of row |
2342
+ | treetable.row.focus.ring.shadow | --p-treetable-row-focus-ring-shadow | Focus ring shadow of row |
2343
+ | treetable.body.cell.border.color | --p-treetable-body-cell-border-color | Border color of body cell |
2344
+ | treetable.body.cell.padding | --p-treetable-body-cell-padding | Padding of body cell |
2345
+ | treetable.body.cell.gap | --p-treetable-body-cell-gap | Gap of body cell |
2346
+ | treetable.body.cell.selected.border.color | --p-treetable-body-cell-selected-border-color | Selected border color of body cell |
2347
+ | treetable.body.cell.font.weight | --p-treetable-body-cell-font-weight | Font weight of body cell |
2348
+ | treetable.body.cell.font.size | --p-treetable-body-cell-font-size | Font size of body cell |
2349
+ | treetable.footer.cell.background | --p-treetable-footer-cell-background | Background of footer cell |
2350
+ | treetable.footer.cell.border.color | --p-treetable-footer-cell-border-color | Border color of footer cell |
2351
+ | treetable.footer.cell.color | --p-treetable-footer-cell-color | Color of footer cell |
2352
+ | treetable.footer.cell.padding | --p-treetable-footer-cell-padding | Padding of footer cell |
2353
+ | treetable.column.footer.font.weight | --p-treetable-column-footer-font-weight | Font weight of column footer |
2354
+ | treetable.column.footer.font.size | --p-treetable-column-footer-font-size | Font size of column footer |
2355
+ | treetable.footer.background | --p-treetable-footer-background | Background of footer |
2356
+ | treetable.footer.border.color | --p-treetable-footer-border-color | Border color of footer |
2357
+ | treetable.footer.color | --p-treetable-footer-color | Color of footer |
2358
+ | treetable.footer.border.width | --p-treetable-footer-border-width | Border width of footer |
2359
+ | treetable.footer.padding | --p-treetable-footer-padding | Padding of footer |
2360
+ | treetable.column.resizer.width | --p-treetable-column-resizer-width | Width of column resizer |
2361
+ | treetable.resize.indicator.width | --p-treetable-resize-indicator-width | Width of resize indicator |
2362
+ | treetable.resize.indicator.color | --p-treetable-resize-indicator-color | Color of resize indicator |
2363
+ | treetable.sort.icon.color | --p-treetable-sort-icon-color | Color of sort icon |
2364
+ | treetable.sort.icon.hover.color | --p-treetable-sort-icon-hover-color | Hover color of sort icon |
2365
+ | treetable.sort.icon.size | --p-treetable-sort-icon-size | Size of sort icon |
2366
+ | treetable.loading.icon.size | --p-treetable-loading-icon-size | Size of loading icon |
2367
+ | treetable.node.toggle.button.hover.background | --p-treetable-node-toggle-button-hover-background | Hover background of node toggle button |
2368
+ | treetable.node.toggle.button.selected.hover.background | --p-treetable-node-toggle-button-selected-hover-background | Selected hover background of node toggle button |
2369
+ | treetable.node.toggle.button.color | --p-treetable-node-toggle-button-color | Color of node toggle button |
2370
+ | treetable.node.toggle.button.hover.color | --p-treetable-node-toggle-button-hover-color | Hover color of node toggle button |
2371
+ | treetable.node.toggle.button.selected.hover.color | --p-treetable-node-toggle-button-selected-hover-color | Selected hover color of node toggle button |
2372
+ | treetable.node.toggle.button.size | --p-treetable-node-toggle-button-size | Size of node toggle button |
2373
+ | treetable.node.toggle.button.border.radius | --p-treetable-node-toggle-button-border-radius | Border radius of node toggle button |
2374
+ | treetable.node.toggle.button.focus.ring.width | --p-treetable-node-toggle-button-focus-ring-width | Focus ring width of node toggle button |
2375
+ | treetable.node.toggle.button.focus.ring.style | --p-treetable-node-toggle-button-focus-ring-style | Focus ring style of node toggle button |
2376
+ | treetable.node.toggle.button.focus.ring.color | --p-treetable-node-toggle-button-focus-ring-color | Focus ring color of node toggle button |
2377
+ | treetable.node.toggle.button.focus.ring.offset | --p-treetable-node-toggle-button-focus-ring-offset | Focus ring offset of node toggle button |
2378
+ | treetable.node.toggle.button.focus.ring.shadow | --p-treetable-node-toggle-button-focus-ring-shadow | Focus ring shadow of node toggle button |
2379
+ | treetable.paginator.top.border.color | --p-treetable-paginator-top-border-color | Border color of paginator top |
2380
+ | treetable.paginator.top.border.width | --p-treetable-paginator-top-border-width | Border width of paginator top |
2381
+ | treetable.paginator.bottom.border.color | --p-treetable-paginator-bottom-border-color | Border color of paginator bottom |
2382
+ | treetable.paginator.bottom.border.width | --p-treetable-paginator-bottom-border-width | Border width of paginator bottom |
2383
+
2384
+ ## Column API
2385
+
2386
+ ### Props
2387
+
2388
+ | Name |Type |Default |Description |
2389
+ | --- | --- | --- | --- |
2390
+ | columnKey | string | - | Identifier of a column if field property is not defined. |
2391
+ | field | string \| Function | - | Property represented by the column. |
2392
+ | sortField | string \| Function | - | Property name to use in sorting, defaults to field. |
2393
+ | filterField | string \| Function | - | Property name to use in filtering, defaults to field. |
2394
+ | dataType | string | - | Type of data. It's value is related to PrimeVue.filterMatchModeOptions config. |
2395
+ | sortable | boolean | false | Defines if a column is sortable. |
2396
+ | header | string | - | Header content of the column. |
2397
+ | footer | string | - | Footer content of the column. |
2398
+ | style | any | - | Inline style of header, body and footer cells. |
2399
+ | class | any | - | Style class of header, body and footer cells. |
2400
+ | headerStyle | any | - | Inline style of the column header. |
2401
+ | headerClass | any | - | Style class of the column header. |
2402
+ | bodyStyle | any | - | Inline style of the column body. |
2403
+ | bodyClass | any | - | Style class of the column body. |
2404
+ | footerStyle | any | - | Inline style of the column footer. |
2405
+ | footerClass | any | - | Style class of the column footer. |
2406
+ | showFilterMenu | boolean | true | Whether to display the filter overlay. |
2407
+ | showFilterOperator | boolean | true | When enabled, match all and match any operator selector is displayed. |
2408
+ | showClearButton | boolean | false | Displays a button to clear the column filtering. |
2409
+ | showApplyButton | boolean | true | Displays a button to apply the column filtering. |
2410
+ | showFilterMatchModes | boolean | true | Whether to show the match modes selector. |
2411
+ | showAddButton | boolean | true | When enabled, a button is displayed to add more rules. |
2412
+ | filterMatchModeOptions | ColumnFilterMatchModeOptions[] | - | An array of label-value pairs to override the global match mode options. |
2413
+ | maxConstraints | number | 2 | Maximum number of constraints for a column filter. |
2414
+ | excludeGlobalFilter | boolean | false | Whether to exclude from global filtering or not. |
2415
+ | filterHeaderStyle | any | - | Inline style of the column filter header in row filter display. |
2416
+ | filterHeaderClass | any | - | Style class of the column filter header in row filter display. |
2417
+ | filterMenuStyle | any | - | Inline style of the column filter overlay. |
2418
+ | filterMenuClass | any | - | Style class of the column filter overlay. |
2419
+ | selectionMode | HintedString<"single" \| "multiple"> | - | Defines column based selection mode. |
2420
+ | expander | boolean | false | Displays an icon to toggle row expansion. |
2421
+ | colspan | number | - | Number of columns to span for grouping. |
2422
+ | rowspan | number | - | Number of rows to span for grouping. |
2423
+ | rowReorder | boolean | false | Whether this column displays an icon to reorder the rows. |
2424
+ | rowReorderIcon | string | - | Icon of the drag handle to reorder rows. |
2425
+ | reorderableColumn | boolean | false | Defines if the column itself can be reordered with dragging. |
2426
+ | rowEditor | boolean | false | When enabled, column displays row editor controls. |
2427
+ | frozen | boolean | false | Whether the column is fixed in horizontal scrolling. |
2428
+ | alignFrozen | HintedString<"left" \| "right"> | left | Position of a frozen column, valid values are left and right. |
2429
+ | exportable | boolean | false | Whether the column is included in data export. |
2430
+ | exportHeader | string | - | Custom export header of the column to be exported as CSV. |
2431
+ | exportFooter | string | - | Custom export footer of the column to be exported as CSV. |
2432
+ | filterMatchMode | string | - | Defines the filtering algorithm to use when searching the options. |
2433
+ | hidden | boolean | false | Whether the column is rendered. |
2434
+ | dt | any | - | It generates scoped CSS variables using design tokens for the component. |
2435
+ | pt | PassThrough<ColumnPassThroughOptions> | - | Used to pass attributes to DOM elements inside the component. |
2436
+ | ptOptions | any | - | Used to configure passthrough(pt) options of the component. |
2437
+ | unstyled | boolean | false | When enabled, it removes component related styles in the core. |
2438
+
2439
+ ### Pass Through Options
2440
+
2441
+ | Name |Type |Description |
2442
+ | --- | --- | --- |
2443
+ | root | ColumnPassThroughOptionType | Used to pass attributes to the root's DOM element. |
2444
+ | headerCell | ColumnPassThroughOptionType | Used to pass attributes to the header cell's DOM element. |
2445
+ | columnResizer | ColumnPassThroughOptionType | Used to pass attributes to the column resizer's DOM element. |
2446
+ | columnHeaderContent | ColumnPassThroughOptionType | Used to pass attributes to the column header content's DOM element. |
2447
+ | columnTitle | ColumnPassThroughOptionType | Used to pass attributes to the header title's DOM element. |
2448
+ | sort | ColumnPassThroughOptionType | Used to pass attributes to the sort's DOM element. |
2449
+ | sortIcon | ColumnPassThroughOptionType | Used to pass attributes to the sort icon's DOM element. |
2450
+ | pcSortBadge | any | Used to pass attributes to the Badge component. |
2451
+ | pcHeaderCheckbox | any | Used to pass attributes to the Checkbox component. |
2452
+ | filter | ColumnPassThroughOptionType | Used to pass attributes to the column filter's DOM element. |
2453
+ | filterElementContainer | ColumnPassThroughOptionType | Used to pass attributes to the filter element container's DOM element. |
2454
+ | pcColumnFilterButton | ColumnPassThroughOptionType | Used to pass attributes to the column filter button's DOM element. |
2455
+ | filterMenuIcon | ColumnPassThroughOptionType | Used to pass attributes to the filter menu icon's DOM element. |
2456
+ | pcColumnFilterClearButton | ColumnPassThroughOptionType | Used to pass attributes to the column filter clear button's DOM element. |
2457
+ | filterClearIcon | ColumnPassThroughOptionType | Used to pass attributes to the filter clear icon's DOM element. |
2458
+ | filterOverlay | ColumnPassThroughOptionType | Used to pass attributes to the filter overlay's DOM element. |
2459
+ | filterConstraintList | ColumnPassThroughOptionType | Used to pass attributes to the filter constraint list's DOM element. |
2460
+ | filterConstraint | ColumnPassThroughOptionType | Used to pass attributes to the filter constraint's DOM element. |
2461
+ | filterConstraintSeparator | ColumnPassThroughOptionType | Used to pass attributes to the filter constraint separator's DOM element. |
2462
+ | filterOperator | ColumnPassThroughOptionType | Used to pass attributes to the filter operator's DOM element. |
2463
+ | pcFilterOperatorDropdown | any | Used to pass attributes to the Select component. |
2464
+ | filterRuleList | ColumnPassThroughOptionType | Used to pass attributes to the filter rule list' DOM element. |
2465
+ | filterRule | ColumnPassThroughOptionType | Used to pass attributes to the filter rule's DOM element. |
2466
+ | pcFilterConstraintDropdown | any | Used to pass attributes to the Select component. |
2467
+ | filterRemove | ColumnPassThroughOptionType | Used to pass attributes to the filter remove button container's DOM element. |
2468
+ | pcFilterRemoveRuleButton | any | Used to pass attributes to the Button component. |
2469
+ | filterAddButtonContainer | ColumnPassThroughOptionType | Used to pass attributes to the filter add button container's DOM element. |
2470
+ | pcFilterAddRuleButton | any | Used to pass attributes to the Button component. |
2471
+ | filterButtonbar | ColumnPassThroughOptionType | Used to pass attributes to the filter buttonbar's DOM element. |
2472
+ | pcFilterClearButton | any | Used to pass attributes to the Button component. |
2473
+ | pcFilterApplyButton | any | Used to pass attributes to the Button component. |
2474
+ | rowToggleButton | ColumnPassThroughOptionType | Used to pass attributes to the row toggler button's DOM element. |
2475
+ | rowToggleIcon | ColumnPassThroughOptionType | Used to pass attributes to the row toggler icon's DOM element. |
2476
+ | nodeToggleButton | ColumnPassThroughOptionType | Used to pass attributes to the node toggle button's DOM element. |
2477
+ | nodeToggleIcon | ColumnPassThroughOptionType | Used to pass attributes to the node toggle icon's DOM element. |
2478
+ | bodyCell | ColumnPassThroughOptionType | Used to pass attributes to the body cell's DOM element. |
2479
+ | reorderableRowHandle | ColumnPassThroughOptionType | Used to pass attributes to the reorderable row handle's DOM element. |
2480
+ | pcRowRadiobutton | any | Used to pass attributes to the radiobutton's DOM element. |
2481
+ | pcRowCheckbox | any | Used to pass attributes to the checkbox's DOM element. |
2482
+ | pcNodeCheckbox | any | Used to pass attributes to the node checkbox's DOM element. |
2483
+ | pcRowEditorInit | ColumnPassThroughOptionType | Used to pass attributes to the row editor init button's DOM element. |
2484
+ | pcRowEditorSave | ColumnPassThroughOptionType | Used to pass attributes to the row editor save button's DOM element. |
2485
+ | pcRowEditorCancel | ColumnPassThroughOptionType | Used to pass attributes to the row editor cancel button's DOM element. |
2486
+ | footerCell | ColumnPassThroughOptionType | Used to pass attributes to the footer cell's DOM element. |
2487
+ | columnFooter | ColumnPassThroughOptionType | Used to pass attributes to the footer content DOM element. |
2488
+ | bodyCellContent | ColumnPassThroughOptionType | Used to pass attributes to the body cell content's DOM element. |
2489
+ | hooks | any | Used to manage all lifecycle hooks. |
2490
+
2491
+ ### Theming
2492
+
2493
+ ## Tree Node API