vue-jstree
vue-jstree copied to clipboard
@item-toggle is called twice
I added @item-toggle="ItemToggle" and created the function: ItemToggle( ){ ... }
The function ItemToggle is called twice, why?
I am experiencing this as well..
Probably related. If you are using async data and expand a node the load data call is called twice as well.
experiencing same issue, made an ugly workaround where i would ignore the second toggle with a timeout.
can anyone suggest a fix?
What I am doing is
import _ from 'underscore'
const debouncedItemToggle = _.debounce((model) => {
// do what you need to do
}, 250);
export default {
....
....
onItemToggle(oriNode, model) {
debouncedItemToggle(model);
},
.....
};
I think this is a bug. in tree-item.vue
; the handleItemToggle
methods changed the status of open
and carry out the this.onItemToggle
method, but you can see, in watch, on model.opened
change, the
this.onItemToggle
method be carry out again. that is why @item-toggle
is called twice
The underlying issue here is even worse in my case, because it is causing my (expensive) @async
function to be called twice every time a folder is expanded for the first time.
Is there a fix or workaround that would work?
Following is a simple example to reproduce the issue:
<template>
<v-jstree ref="tree" class="tree" v-bind:data="nodes" v-bind:async="loadChildren" />
</template>
<script>
import VJstree from "vue-jstree"
export default {
name: "bug",
data: function() {
return {
nodes: []
}
},
methods: {
loadChildren: function(ctx, cb) {
var id = ctx.data.id
var done = function() {
console.log("Children loaded")
return cb( [{text: "Rabbit Hole", isLeaf: false}] )
}
console.log("Simulating long time loading children for node " + id + "...")
setTimeout(done, 2000)
}
},
components: {
VJstree
}
}
</script>
<style>
.tree {
width: 400px;
height: 400px;
border: 1px solid #999;
float: left;
overflow: scroll;
}
</style>
which produces the following console output...
bug.vue:22 Simulating long time loading children for node undefined...
bug.vue:19 Children loaded
bug.vue:22 Simulating long time loading children for node 2...
bug.vue:22 Simulating long time loading children for node 2...
bug.vue:19 Children loaded
bug.vue:19 Children loaded
bug.vue:22 Simulating long time loading children for node 6...
bug.vue:22 Simulating long time loading children for node 6...
bug.vue:19 Children loaded
bug.vue:19 Children loaded
bug.vue:22 Simulating long time loading children for node 10...
bug.vue:22 Simulating long time loading children for node 10...
bug.vue:19 Children loaded
bug.vue:19 Children loaded
@sburr see what I posted above as a workaround. You will have to debounce the call to load your children so it only happens once. Dirty, but effective.
Thank you. I did read that but had missed a nuance in the way that underscore's debounce method works in an effort to avoid yet another dependency.
This repo may interest you if you don't want to import more libs
https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore
On Fri, Jan 4, 2019, 2:44 PM Steven Burr <[email protected] wrote:
Thank you. I did read that but had missed a nuance in the way that underscore's debounce method works in an effort to avoid yet another dependency.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/zdy1988/vue-jstree/issues/67#issuecomment-451548454, or mute the thread https://github.com/notifications/unsubscribe-auth/AAp45bEdCQkR8PpHCAgoKDoXJeuVjMQnks5u_680gaJpZM4VzeKO .
If you are using async data and expand a node the load data call is called twice as well.
I'm experiences this also. Annoying issue..
What I am doing is
import _ from 'underscore' ..... };
Some more details for a quick workaround in tree.vue using TypeScript library ts-debounce:
import { debounce } from 'ts-debounce';
....
const debouncedItemToggle = debounce((proxyForThis, oriNode, oriItem, e) => {
if (oriNode.model.opened) {
proxyForThis.handleAsyncLoad(oriNode.model[proxyForThis.childrenFieldName],
oriNode,
oriItem,
);
}
proxyForThis.$emit('item-toggle', oriNode, oriItem, e);
}, 250);
export default {
....
....
onItemToggle(oriNode, oriItem, e) {
debouncedItemToggle(this, oriNode, oriItem, e);
},
.....
};
What I am doing is
import _ from 'underscore' const debouncedItemToggle = _.debounce((model) => { // do what you need to do }, 250); export default { .... .... onItemToggle(oriNode, model) { debouncedItemToggle(model); }, ..... };
how to call method or variable in "debouncedItemToggle" sir? can you give an example? I'm new to vue-jstree
What I am doing is
import _ from 'underscore' const debouncedItemToggle = _.debounce((model) => { // do what you need to do }, 250); export default { .... .... onItemToggle(oriNode, model) { debouncedItemToggle(model); }, ..... };
how to call method or variable in "debouncedItemToggle" sir? can you give an example? I'm new to vue-jstree
You can pass in 'this' to the debouncedItemToggle
I have modified this method,delete this code" ,this.onItemToggle(this,this.model)",and it worked ;I don't know whether there will be other side effects. handleItemToggle: function(e) { this.isFolder && (this.model.opened = !this.model.opened) },
@renqWork good job man 🥳 Please open a PR and notify the Author. After your fix is merged to the main branch and published, close this issue.