phphe / he-tree Goto Github PK
View Code? Open in Web Editor NEWHighly customizable draggable Vue.js tree component.
Home Page: https://hetree.phphe.com/
Highly customizable draggable Vue.js tree component.
Home Page: https://hetree.phphe.com/
Hi there,
Not sure if this is the best place to ask but, is there any keyboard support for navigation?
Thank you and thank you for the library.
Artur
Hi, I'm facing the following issues when trying to make each node to be able to drag and drop under their own parents only:
Both cases happens even though there is no placeholder shown on the dropping area.
按照官方示例引入后,拖拽节点时会出现无父节点可以drop的情况,导致 组件内部 _checkIDExists 报错。
I have a folder & document structure that you can see on the picture:
My question: is there any best practice how to set droppable property for all nodes? Because it works in my solution, but I don't know is there any better way?
Sample data:
{
id: 1,
text: "Folder",
isFolder: true,
children: [
{
id: 33,
text: '1-1 §',
children: []
}
],
},
Template:
<Draggable
:each-droppable="eachDroppable"
:rootDroppable="false"
/>
Script:
methods: {
eachDroppable(node) {
return !!toRaw(node.data.isFolder);
},
}
Thanks in advanced.
in packages/vue3/package.json
{
+ "types": "types/lib-entry.d.ts"
}
Thanks for the library, the folding and drag-and-drop is working nicely on my flat data, but I am having trouble in retrieving the modified data. After nodes have been dragged how does one retrieve the new positions? The documentation does not seem to answer this.
我使用 Draggable 的 drop-change 後想透過 outputFlatData 這個 methods 去取得拖曳後結果,但拿到的東西都是 proxy,請問有其他方法可以拿到拖曳結果嗎?翻遍文件跟範例了...
Draggable(
:treeData="menuItemTree",
idKey="id",
parentIdKey="parent_id"
triggerClass="drag-trigger",
ref="tree"
@drop-change="dropChangeHandler"
)
template(v-slot="{ node, tree }")
.drag-area
//....省略
Hello - first of all, he-tree is really great! I am very happy with it.
But I have a small problem: vl-items
has always an element style of padding-bottom: 19px;
It does not matter if there are 1 or multiple items in the list.
Items do not have a margin-bottom
set.
Not sure if this is a bug, but I can't find a solution.
Thanks a lot,
Paul
现在只有添加子级,增加平级比较麻烦
It's a really great component. I noticed that the data model, neither flatData nor treeData does not update after drag and drop. is this normal?
Also, AddNode dose not work, It replaces with the previously added node.
How do we achieve filtering/searching feature like in the he-tree-vue.
I am trying to walk the tree data, but i am unable to set the hidden prop of the node. Is there any example for that?
Hello
Could you please add tree filtering?
Hello,
First I would like to thank you for this Awesome project !
I have a limitation hough, the old version had an option to set a max level prop (Pro license), how could we do the same with the new version PLEASE ?
Thank's in advance.
Hello,
I do have a serious problem:
<Draggable idKey="id" :flatData="fdata" parentIdKey="parent" <template v-slot="{ node }"> <div>...</div> </template> </Draggable>
I started using your package in one of my projects and so far everything works great. I'm however facing a problem in regards to having certain children checked by default.
I'm not entirely sure how to achieve this behaviour. I saw this example on your website, but I'm struggling to get it to work with an initial state.
Do you have an example of how this can be achieved? Do I need to specify a custom statHandler, or how would you solve this?
Another question I have is whether it's possible to not check the parent if all children are checked. I would like to be able to check every single node in the tree individually, without automatically selecting the parent. This this somehow supported?
Thanks in advance!
From the documentation, I can't find out how to set a minimum height for the VirtualizationList.
I've tried setting the .vl-items { height: 100% !important; }
but it is causing missing entries at the bottom, because the VirtualizationList update method results become outdated when the height of the VirtualizationList changes. I see that the VirtualizationList controls its .vl-items
height (this.totalHeight
).
From what I've investigated so far, I see the following events:
height: 100%
makes the VirtualizationList a bit larger yet, making its $el.clientHeight 328px, large enough to show more items.update()
manually, they are shown, but this causes more space to be taken, ergo the parent height changes, so the height: 100%
causes the VirtualizationList to grow again, causing more items to be shown, etc. etc.However, I can't find an alternative to this from the documentation. Could you please help me out?
I couldn't use it on mobile.
I don't know why, but both on android and on the browser inspector, the same behavior happens.
我想请问一下,拖拽了node位置以后,怎么取得这个node在兄弟node的第几顺序?
为了让每次加载的node数跟用户手动调整的顺序一致,我想把这个顺序保存到后台。
First of all, I don't fully understand what triggerClass
is. My guess is it is to specify a handler that drags nodes.
Therefore, I wrote the code like this:
<Draggable
v-model="data"
:triggerClass="['handler']"
ref="tree"
>
<template #default="{ node, stat }">
<div class="my-node">
<div>
<button class="handler">
drag
</button>
<button
v-if="stat.children.length" @click="stat.open = !stat.open"
>
{{ stat.open ? "-" : "+" }}
</button>
{{ node.text }}
</div>
</div>
</template>
</Draggable>
However, it shows an error like the below:
Uncaught Can't find drag node Error
Do I understand what triggerClass
is? If so, How can I resolve this problem?
Thank you
Hello, I do not want to have a tree structure, how can I prevent this?
I have the following snippets of code to override the Draggable default slot:
<template>
<!-- ... -->
<Draggable ...>
<template v-slot="{ node, tree }">
<!-- ... -->
</template>
</Draggable>
</template>
<script setup lang="ts">
import { Draggable } from "@he-tree/vue3";
// ...
</script>
However, on the line of the <template v-slot>
, I get the following typescript error:
ts(7053): Element implicitly has an 'any' type because expression of type '"default"' can't be used to index type '{} | {}'.
Property 'default' does not exist on type '{} | {}'.
The types come from Just tried generating .d.ts declarations for a Vue component with slots but it appears the slots aren't in the type definition at all? How is this supposed to work at all when including Vue SFC components from npm packages?node_modules/@he-tree/vue3/types/draggable/Draggable.vue.d.ts
but it doesn't seem to contain slot definitions, hence the error.
The example given with the Pro version isn't working because it's written for the old version of the plugin:
import {Tree, // Base tree
Fold, Check, Draggable, // plugins
} from 'he-tree-vue'
import 'he-tree-vue/dist/he-tree-vue.css' // base style
import DraggablePro from 'yourpath/DraggablePro.vue'
DraggablePro.LICENSE_NUMBER = 'your license number'
export default {
components: {
Tree: Tree.mixPlugins([Fold, Check, Draggable, DraggablePro]),
},
}
Specifically, this has to be replaced:
import {Tree, // Base tree
Fold, Check, Draggable, // plugins
} from 'he-tree-vue'
with this:
import {Tree, Draggable, BaseTree} from '@he-tree/vue2';
And then BaseTree
doesn't have mixPlugins
method.
Please give instructions on how to use it with https://github.com/phphe/he-tree/ Vue 2.
想实现根目录固定不变,不能拖拽,把「rootDraggable」属性设置成false,还是能够拖拽
<Draggable :flatData="flatData" idKey="id" parentIdKey="pid" :rootDraggable="false" :rootDroppable="false" >
<template v-slot="{ node }">
{{node.text }}
</template>
</Draggable>
Hello.
First let me tell you, your component is great!!!
I want to add a node programmatically to the root. Currently the addNode()
method works, passing a simple object as parameter, but the new node is not reactive, I cannot expand or collapse it (e.g. lazy loading does not work)
I also tried adding the node to the original data pointed by treeData
but then the lazy loading does not work either.
What is the right wat to add a node with code?
Some of the dependencies (e.g tslib v. 1.x) are quite old and have a few bugs that are annoying (e.g. missing esm support). Could you please update them! Thanks
I would suggest to activate rennovate or dependabot to take of these updates automatically.
(This applies also to your draggable-helper package)
Hi,
when I use :ondragend
property hook to not made changes. moving tree node is after drop deleted.
After I start moving with another node, deleted node show on original position..
My intention / uses case is to show confirmation dialog before node position is changed, and if user say no, restore original tree / or prevent any chnages on tree. Is this possible what about JS promises ?
<DragableTree virtualization="virtualization" :ondragend="onDragEnd" edge-scroll :gap="6" :tree-data="files.children">
<template v-slot="{node, index, tree}">
<div class="d-inline-flex">
<div class="expend--wrap" @click="node.$folded=!node.$folded">
<ArrowIcon :size="'small'" v-if="node.$children.length > 0" :direction="node.$folded ? 'right' : 'bottom' "></ArrowIcon>
</div>
<div class="expend-folder--wrap" @click="node.$folded=!node.$folded">
<i class="fa" :class="{ 'fa-folder-open': !node.$folded, 'fa-folder': node.$folded }" style="color: #ffd26a;" />
</div>
<span>{{node.name}}</span>
</div>
</template>
</DragableTree>
onDragEnd(node){
console.log(node);
return false; // prevent to change tree this shod also accept promises ?
},
I´m using VUE2 version.
Thanks for help!
I started using this library with drag and drop feature but I didn't find out how to get the dragContext and I didn't find in the documentation (https://hetree.phphe.com/v2/api#dragcontext). I need the startInfo
and targetInfo
.
Do you have an example of how this can be achieved?
Thanks in advanced.
Hi,
when I install VUE 2 version, I have problem with DragAndDrop behavior, I´m suing the same example as you have, but I got this error:
Uncaught DOMException: Failed to execute 'querySelector' on 'Element': '[data-id=4]' is not a valid selector.
at VueComponent.getElByID (http://localhost:8080/js/9.js:833:23)
at doInsert (http://localhost:8080/js/9.js:2243:96)
at Object.movePlaceholder (http://localhost:8080/js/9.js:2251:19)
at Object.beforeMove (http://localhost:8080/js/9.js:1817:13)
at HTMLDocument.onMousemoveOrTouchMove (http://localhost:8080/js/9.js:6457:33)
at HTMLDocument.wrapper (http://localhost:8080/js/9.js:5807:22)
<DragableTree virtualization="virtualization" edge-scroll :gap="6" :tree-data="files.children">
<template v-slot="{node, index, tree}">
<div class="d-inline-flex">
<div class="expend--wrap" @click="node.$folded=!node.$folded">
<ArrowIcon :size="'small'" v-if="node.$children.length > 0" :direction="node.$folded ? 'right' : 'bottom' "></ArrowIcon>
</div>
<div class="expend-folder--wrap" @click="node.$folded=!node.$folded">
<i class="fa" :class="{ 'fa-folder-open': !node.$folded, 'fa-folder': node.$folded }" style="color: #ffd26a;" />
</div>
<span>{{node.name}}</span>
</div>
</template>
</DragableTree>
我是想比如左侧树树,右侧是一个ul li的列表,我想把li的东西可以拖动到树里面,这哥支持吗?
您好,我想请教下,如何让节点只能在当前的层级进行拖拽,而不能拖拽到上级或者下级呢?
我查看官方文档没有相关的属性和案例,谢谢您的回答
Reproduction steps:
How to accomplish to update tree in database.
I need to on drop event get where node was droped and get all nodes for that node.
Thanks
const treedataq = reactive([
{
text: "Projects",
children: [
{
text: "Frontend",
children: [
{
text: "Vue",
children: [
{
text: "Nuxt",
},
],
},
{
text: "React",
children: [
{
text: "Next",
},
],
},
{
text: "Angular",
},
],
},
{
text: "Backend",
},
],
},
{
text: "Download",
},
])
const add = () => {
treedataq.push({
text: "######Download1111111",children: []
})
}
<Draggable v-model="treedataq" ref="tree" @enter="change" virtualization style="height: 500px">
<template #default="{ node, stat }">
<span v-if="stat.children.length" @click="stat.open = !stat.open">
{{ stat.open ? "-" : "+" }}
</span>
{{ node.text }}
</template>
</Draggable>
when i click add, the reactive alrealy new vlaue, the the Draggable can't auto refresh
Hello @phphe
Tree can't handle more than 1735 nodes in chrome.
Example:
<script lang="ts">
import { Draggable } from "@he-tree/vue";
import "@he-tree/vue/style/default.css";
import { reactive, defineComponent, onMounted } from "vue";
import data from "./data.json";
export default defineComponent({
components: { Draggable },
data() {
return {
data: [
...new Array(1736).fill(1).map((v) => ({
text: 'Node-' + Math.random().toString().substring(2, 5),
})),
],
};
},
mounted() {},
});
</script>
<template>
<div>
<Draggable v-model="data" ref="tree" virtualization style="height: 500px">
<template #default="{ node, stat }">
<span v-if="stat.children.length" @click="stat.open = !stat.open">
{{ stat.open ? "-" : "+" }}
</span>
<!-- <span v-else> </span>
<input type="checkbox" v-model="stat.checked" /> -->
{{ node.text }}
</template>
</Draggable>
</div>
</template>
<style></style>
i need to reload only the children of a specific parent when an API retrieves me the result, but the lazy load seems to not recalculate children once the parent was already opened once, can someone suggest me a method?
Hello,
amazing package, thanks for your great work! Can you please help how can I customize the node "template" with default slot? Basically I would like to append an icon after the text with the ID of the node, eg. for opening a modal to insert a new node after/under that node. I tried to find the structure or the default slot both in docs and the source, but couldn't really figure it out.
regards, Gabor
I don't understand how to use it with new
updateBehavior for vuex for example.
change
event has no data.
How to get changes?
Hi @phphe
Please watch video.
Hi @phphe
Current checked behavior:
Is it possible to make it so that when one node is checked, parents and child nodes state does not change?
Hi @phphe, thank you for writing this library!
I encountered an issue trying to update the tree from Javascript. For each node, I have an "add" button to create a child node:
<Draggable ref="categories" :flatData="categories" idKey="categoryId" parentIdKey="parentId">
<template v-slot="{node}">
<span>{{ node.name }}</span> <span @click="addCategory(node)">[+]</span>
</template>
</Draggable>
export default defineComponent({
[...]
methods: {
addCategory(parent: Category) {
const name = prompt("Enter a name for the new category");
if (!name) {
return;
}
const draggable = this.$refs.categories as typeof Draggable;
draggable.addNode({
categoryId: this.nextCategoryId(),
name,
parentId: parent.categoryId,
}, parent.categoryId);
}
}
[...]
});
I have a two-node tree:
* Root [+]
* First category [+]
When I click the [+] button next to "First category" and enter a name for the new category, it adds the node, but indented as a root node:
* Root [+]
* First category [+]
* Second category [+]
Since I give a parentId
for the new category, I would expect the tree to look like this:
* Root [+]
* First category [+]
* Second category [+]
When I inspect the new Node in the Vue debugger, I see that its parent is recognized correctly, however, the level is set incorrectly, causing the wrong indentation:
node:
$checked: false
$children: []
$folded: false
$id: 3
$level: 1 <---- should be 3
$pid: 2
categoryId: 3
name: "Second category"
parentId: 2
parent:
$checked: false
$children: [...]
$folded: false
$id: 2
$level: 2 <-----
$pid: 1
categoryId: 2
name: "First category"
parentId: 1
Looking at packages/vue3/src/BaseTree.vue addNode()
I see that the parent
is recognized correctly. However, hp.walkTreeData()
is called, which then calls the anonymous function with a parent of null
. Hence, child.$level
is not set to parent.$level
(shouldn't this be parent.$level + 1
?) but instead to 1
.
https://hetree.phphe.com/v1/guide#max-level
hp.walkTreeData
- here hp
is undefined, obviously. Can you give a working example of how to limit the max level? We're using Vue2
will this project support touch devices? like phone devices
I'm attempting to implement this into an app to control the ordering of the filesystem, but in my initial testing the drag and drop example doesn't seem to work as presented.
可否支持不定高虚拟滚动
Hello, thanks for your work, that's perfect.
But not very convenient to use on devices with touch screens.
Since my draggable list is also scrollable this gives some conflicts concerning touch gestures on mobiles or tablets.
Because the normal scrolling gesture ('swiping' over the list) is interpreted as a drag gesture. The scrolling currently only works if I either touch in between list items or directly on the scroll bar. Of course, this is not wrong behavior.
But because it is kind of awkward to use, I would like to add some kind of delay for the drag and drop stuff.
I would like to have a situation like this:
I hope I made my problem clear enough.
regards
[email protected]
typescript@~4.5.5
Draggable添加虚拟列表属性virtualization
报错如下
<script setup>
const tagNodes = ref([{ text: "a" }])
</script>
<template>
<Draggable v-model="tagNodes">
</Draggable>
</template>
初始化 tagNodes
之后,再次用其他数据赋值 tagNodes,比如 tagNode.value = [{ text: "b"}]
这时,视图没有发生任何改变。
理想情况:应该跟着外部变化。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.