Ga naar hoofdinhoud

CnTreeView

Recursive hierarchical tree widget. Nested nodes with click-to-expand carets, optional badges + icons, an inline per-row actions slot, and select-on-click semantics. Configurable id / label / children keys so consumers don't have to reshape their data.

Drag-and-drop reorder is deferred to a follow-up under nextcloud-vue#278. The public contract here is forward-compatible — adding draggable: true later won't change existing v-model bindings.

Try it

<CnTreeView
:nodes="nodes"
:expanded-ids.sync="expanded"
:selected-id.sync="selected"
@select="onSelect">
<template #actions="{ node }">
<button @click.stop="edit(node)">Edit</button>
<button @click.stop="del(node)">Delete</button>
</template>
</CnTreeView>
const nodes = [
{ id: 1, label: 'Knowledge base', children: [
{ id: 2, label: 'How-tos', badge: 12, children: [
{ id: 3, label: 'Reset password' },
]},
{ id: 4, label: 'Reference' },
]},
]

Props

PropTypeDefaultDescription
nodesArray<{id,label,children?,icon?,badge?}>(required)Root-level nodes.
expandedIdsArray<*>[]Currently-expanded ids. Use .sync.
selectedIdAnynullCurrently-selected id. Use .sync.
idKey / labelKey / childrenKeyString'id' / 'label' / 'children'Override the key names on node objects.
indentNumber18Pixels of padding per depth level.
title / descriptionString''Optional header.
emptyLabelString'No items.'Empty-state text.
expandLabel / collapseLabelString'Expand' / 'Collapse'A11y labels for the caret button.
expandAllOnMountBooleanfalseExpand every node on mount (emits update:expanded-ids).

Events

EventPayloadDescription
selectnodeRow clicked. Original node object.
update:selected-idid.sync of selectedId.
update:expanded-idsArray<id>.sync of expandedIds.

Public methods

MethodDescription
expandAll()Emit update:expanded-ids with every node id in the tree.
collapseAll()Emit update:expanded-ids with [].

Slots

  • #actions — inline per-row actions. Scope: { node, depth }. Click handlers should call @click.stop to avoid bubbling into the row's select.

Follow-up

  • Drag-drop reorder (draggable: true + @drop event surface).
  • Keyboard navigation (arrow keys + Space/Enter for select).
  • Lazy-load children (loadChildren(node) => Promise<children>).

See also