Node Manipulation
Custom Node
There are two ways of customizing nodes:
- Use named slot
node
- Use
render
prop
Show code
vue
<template>
<VTree :data="data">
<template #node="{ node }">
<span :style="{ color: 'violet' }">{{ node.title }}</span>
</template>
</VTree>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import VTree from '@wsfe/vue-tree'
const data = ref([
{
title: 'node-1',
id: 'node-1',
children: [
{
title: 'node-1-1',
id: 'node-1-1',
children: [
{
title: 'node-1-1-1',
id: 'node-1-1-1',
},
{
title: 'node-1-1-2',
id: 'node-1-1-2',
},
{
title: 'node-1-1-3',
id: 'node-1-1-3',
},
],
},
{
title: 'node-1-2',
id: 'node-1-2',
children: [
{
title: 'node-1-2-1',
id: 'node-1-2-1',
},
{
title: 'node-1-2-2',
id: 'node-1-2-2',
},
],
},
{
title: 'node-1-3',
id: 'node-1-3',
children: [
{
title: 'node-1-3-1',
id: 'node-1-3-1',
},
{
title: 'node-1-3-2',
id: 'node-1-3-2',
},
],
},
],
},
{
title: 'node-2',
id: 'node-2',
children: [
{
title: 'node-2-1',
id: 'node-2-1',
children: [
{
title: 'node-2-1-1',
id: 'node-2-1-1',
},
{
title: 'node-2-1-2',
id: 'node-2-1-2',
},
],
},
],
},
])
</script>
Drag and Drop
Enable draggable
and droppable
Show code
vue
<template>
<VTree :data="data" checkable draggable droppable />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import VTree from '@wsfe/vue-tree'
const data = ref([
{
title: 'node-1',
id: 'node-1',
children: [
{
title: 'node-1-1',
id: 'node-1-1',
children: [
{
title: 'node-1-1-1',
id: 'node-1-1-1',
},
{
title: 'node-1-1-2',
id: 'node-1-1-2',
},
{
title: 'node-1-1-3',
id: 'node-1-1-3',
},
],
},
{
title: 'node-1-2',
id: 'node-1-2',
children: [
{
title: 'node-1-2-1',
id: 'node-1-2-1',
},
{
title: 'node-1-2-2',
id: 'node-1-2-2',
},
],
},
{
title: 'node-1-3',
id: 'node-1-3',
children: [
{
title: 'node-1-3-1',
id: 'node-1-3-1',
},
{
title: 'node-1-3-2',
id: 'node-1-3-2',
},
],
},
],
},
{
title: 'node-2',
id: 'node-2',
children: [
{
title: 'node-2-1',
id: 'node-2-1',
children: [
{
title: 'node-2-1-1',
id: 'node-2-1-1',
},
{
title: 'node-2-1-2',
id: 'node-2-1-2',
},
],
},
],
},
])
</script>
Node Creation and Removal
- Invoke
insertBefore
,insertAfter
method of tree component to insert new node before and after tree nodes - Invoke
prepend
,append
method of tree component to prepend or append to child list - Invoke
remove
to remove a node
Show code
vue
<template>
<VTree ref="tree" :data="data">
<template #node="{ node }">
<span>{{ node.title }}</span>
<button @click="handleAdd(node)">Add sibling</button>
<button @click="handleAppend(node)">Append child</button>
<button @click="handleRemove(node)">Remove</button>
</template>
</VTree>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import VTree from '@wsfe/vue-tree'
const tree = ref()
let nodeAddCount = 0
let nodeAppendCount = 0
const handleAdd = (node) => {
tree.value.insertAfter({ title: `node-added-${nodeAddCount}` }, node.id)
nodeAddCount++
}
const handleAppend = (node) => {
tree.value.append({ title: `node-appended-${nodeAppendCount}` }, node.id)
nodeAppendCount++
}
const handleRemove = (node) => {
tree.value.remove(node.id)
}
const data = ref([
{
title: 'node-1',
id: 'node-1',
children: [
{
title: 'node-1-1',
id: 'node-1-1',
children: [
{
title: 'node-1-1-1',
id: 'node-1-1-1',
},
{
title: 'node-1-1-2',
id: 'node-1-1-2',
},
{
title: 'node-1-1-3',
id: 'node-1-1-3',
},
],
},
{
title: 'node-1-2',
id: 'node-1-2',
children: [
{
title: 'node-1-2-1',
id: 'node-1-2-1',
},
{
title: 'node-1-2-2',
id: 'node-1-2-2',
},
],
},
{
title: 'node-1-3',
id: 'node-1-3',
children: [
{
title: 'node-1-3-1',
id: 'node-1-3-1',
},
{
title: 'node-1-3-2',
id: 'node-1-3-2',
},
],
},
],
},
{
title: 'node-2',
id: 'node-2',
children: [
{
title: 'node-2-1',
id: 'node-2-1',
children: [
{
title: 'node-2-1-1',
id: 'node-2-1-1',
},
{
title: 'node-2-1-2',
id: 'node-2-1-2',
},
],
},
],
},
])
</script>
<style scoped>
button {
margin-left: 8px;
border: 1px solid lightgray;
border-radius: 4px;
padding: 0 4px;
font-size: 12px;
line-height: 12px;
height: 20px;
}
</style>
Update Node Title
Invoke updateNode
method to update some fields of tree node
Invoke updateNodes
to update multiple nodes
Show code
vue
<template>
<button @click="handleUpdateSingleNode">Update node-1</button>
<button @click="handleUpdateMultipleNode">Update node-1 & node-2</button>
<VTree ref="tree" />
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import VTree from '@wsfe/vue-tree'
const tree = ref()
const data = [
{
title: 'node-1',
id: 'node-1',
children: [
{
title: 'node-1-1',
id: 'node-1-1',
},
{
title: 'node-1-2',
id: 'node-1-2',
},
],
},
{
title: 'node-2',
id: 'node-2',
children: [
{
title: 'node-2-1',
id: 'node-2-1',
},
],
},
]
onMounted(() => {
tree.value.setData(data)
})
const count = ref(0)
const handleUpdateSingleNode = () => {
count.value++
tree.value.updateNode('node-1', { title: `node-1 - ${count.value}` })
}
const handleUpdateMultipleNode = () => {
count.value++
tree.value.updateNodes([
{
id: 'node-1',
title: `node-1 - ${count.value}`,
},
{
id: 'node-2',
title: `node-2 - ${count.value}`,
},
])
}
</script>
<style scoped>
button {
border: 1px solid lightgray;
border-radius: 8px;
padding-left: 10px;
padding-right: 10px;
margin-right: 20px;
}
</style>
Update Custom Field
Invoke updateNode
method to update custom fields in tree node
Show code
vue
<template>
<button @click="handleUpdateCount">Update node-1 count</button>
<VTree ref="tree">
<template #node="{ node }">
<span>{{ node.title }}</span>
<span v-if="typeof node.count === 'number'">
Count: {{ node.count }}
</span>
</template>
</VTree>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue'
import VTree from '@wsfe/vue-tree'
const tree = ref()
const data = [
{
title: 'node-1',
id: 'node-1',
count: 0,
children: [
{
title: 'node-1-1',
id: 'node-1-1',
},
{
title: 'node-1-2',
id: 'node-1-2',
},
],
},
{
title: 'node-2',
id: 'node-2',
children: [
{
title: 'node-2-1',
id: 'node-2-1',
},
],
},
]
onMounted(() => {
tree.value.setData(data)
})
const handleUpdateCount = () => {
const key = 'node-1'
const currentCount = tree.value.getNode(key).count
tree.value.updateNode(key, { count: currentCount + 1 })
}
</script>
<style scoped>
button {
border: 1px solid lightgray;
border-radius: 8px;
padding-left: 10px;
padding-right: 10px;
margin-right: 20px;
}
</style>
Reload Child Nodes
Invoke updateNode
and pass a new children
list to reload child nodes
Show code
vue
<template>
<button @click="handleClearChildren">Clear node-1 children</button>
<button @click="handleSetChildren">Set node-1 children</button>
<button @click="handleUpdateChildren">Update node-1 children</button>
<div :style="{ height: '300px' }">
<VTree ref="tree" checkable selectable />
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import VTree from '@wsfe/vue-tree'
const tree = ref()
const children = Array.from({ length: 100000 }).map((_, i) => {
return {
title: `node-1-${i + 1}`,
id: `node-1-${i + 1}`,
}
})
const data = [
{
title: 'node-1',
id: 'node-1',
children,
},
{
title: 'node-2',
id: 'node-2',
children: [
{
title: 'node-2-1',
id: 'node-2-1',
},
],
},
]
onMounted(() => {
tree.value.setData(data)
})
const handleSetChildren = () => {
tree.value.updateNode('node-1', { children })
}
const handleClearChildren = () => {
tree.value.updateNode('node-1', { children: [] })
}
const handleUpdateChildren = () => {
tree.value.updateNode('node-1', {
children: children.map((child) => {
return {
...child,
title: `${child.title} ${Date.now()}`,
checked: true,
}
})
})
}
</script>
<style scoped>
button {
border: 1px solid lightgray;
border-radius: 8px;
padding-left: 10px;
padding-right: 10px;
margin-right: 20px;
}
</style>