Vue Draggable Sortable Tree Component

3.1.2 · active · verified Sun Apr 19

he-tree-vue is a robust Vue 3 component library designed for rendering draggable, sortable, and nested tree structures. Currently at stable version 3.1.2, it is actively maintained with a development-driven release cadence, focusing on bug fixes, performance improvements, and alignment with modern Vue ecosystem features. Key differentiators include comprehensive TypeScript definitions for enhanced developer experience, a built-in dragging placeholder for intuitive user interaction, and full compatibility with Vue 3's Composition API. It provides a powerful solution for managing hierarchical data with advanced interaction capabilities, distinguishing itself from simpler tree components by its focus on comprehensive drag-and-drop functionality.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates a basic draggable and sortable tree component using `he-tree-vue` with Vue 3's `<script setup>`, TypeScript, and custom styling. It shows data binding, event handling for drag-and-drop, and dynamic node addition.

<template>
  <div id="app">
    <h1>My Draggable Tree</h1>
    <Draggable
      v-model="treeData"
      :indent="20"
      :eachNodeAttributes="(node) => ({ 'data-id': node.id })"
      @change="onTreeChange"
      @node-drop="onNodeDrop"
      class="my-custom-tree"
    >
      <template #default="{ node, index, path, tree }">
        <div class="tree-node-back">
          {{ node.text }}
          <button @click="addNode(node)">Add Child</button>
        </div>
      </template>
    </Draggable>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Draggable, type TreeDataItem } from 'he-tree-vue';
import 'he-tree-vue/style/default.css';

interface MyTreeDataItem extends TreeDataItem {
  id: number;
  text: string;
  children?: MyTreeDataItem[];
}

let nextId = 4;

const treeData = ref<MyTreeDataItem[]>([
  { id: 1, text: 'Node 1', children: [
    { id: 2, text: 'Node 1.1' },
    { id: 3, text: 'Node 1.2' }
  ]}
]);

const onTreeChange = (data: MyTreeDataItem[]) => {
  console.log('Tree data changed:', data);
};

const onNodeDrop = (dragInfo: any) => {
  console.log('Node dropped:', dragInfo);
  // You might want to persist the updated treeData to a backend here
};

const addNode = (parentNode: MyTreeDataItem) => {
  if (!parentNode.children) {
    parentNode.children = [];
  }
  const newNode: MyTreeDataItem = { id: nextId++, text: `New Child of ${parentNode.text}` };
  parentNode.children.push(newNode);
  console.log('Added new node:', newNode);
};
</script>

<style>
.my-custom-tree {
  border: 1px solid #eee;
  padding: 10px;
  min-height: 100px;
}
.tree-node-back {
  padding: 5px;
  border: 1px solid #ccc;
  margin: 2px 0;
  background-color: #f9f9f9;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.he-tree-drag-placeholder {
  background-color: #e0f2f7 !important; /* Light blue placeholder */
  border: 1px dashed #90caf9 !important;
}
</style>

view raw JSON →