Clear tree selection and state on UI

4,059 views
Skip to first unread message

Roshan Kariyadan

unread,
May 10, 2015, 3:53:32 AM5/10/15
to jst...@googlegroups.com
Hi Ivan,
Thanks for creating such a cool plugin. We had a critical requirement and jstree suited our requirement. (JsTree 3.0.9, jquery 1.11.2)Using AJAX to load data from DB(adjacency model - Alternative JSON format,3k records). Current requirement is to load two trees based on dropdown value. Have one jsTree Config and using refresh to load different trees with data from DB. Everything works fine.

We have a requirement where if user select parent then all child should be disabled(Parent value is selected and added to Shopping Cart) This also works fine. 
User need a clear button which should clear all the selections that user made. I tried below
 
  //$("#container").jstree(true).clear_state();   // Didnt cleared the selections and state. Nothing changed.
  //$("#container").jstree(true).refresh(false, true);   // Cleared the selections and state. But makes Ajax calls to server.
  $("#container").jstree(true).deselect_all(true);  //This removed all the selections. But children are still disabled.
  
 Can you please help in finding a solution which will clear all selections and state (disabled) from UI.
 jsFiddle :
 
Also for 2nd tree we are still working on the DB model. Not sure if that will be in adjacency model. Will be having different IDs. Should we use two jsTree configurations or stick to one and load two JSON data formats using AJAX with Different IDs ? (if state needs to be kept in trees I think we need two Configs..any other reason)

Also once user select a item from tree its added to shopping cart. User can again make selections from the same tree. I am working on the cart duplicate case,(Case 1)if first parent is added to shopping cart then adding children give warning (Case 2)If children is already added then while adding parent give warning to user to make correct selections /remove items from Cart. Case 2 I think I can handle with get_selected, get_top_selected. If you have any suggestions on case 1 please let me know. Or if there is any other better approach please let me know your thoughts.

Sorry was such a long mail. Everytime I was planning to put a question I got the answers from Forum or from your documentation. This time I had ran out of options.

Ivan Bozhanov

unread,
May 10, 2015, 4:21:50 AM5/10/15
to jst...@googlegroups.com, rosh...@gmail.com
Hi,

I am glad you chose jstree - looks like an interesting project you are working on. I am glad to hear using jstree has been fine so far.

On the clear selection issue:

1) You can use refresh as you noticed, but you can also configure the massload plugin to make sure the full refresh happens with one AJAX call. However I realize this is far from optimal.

2) You can continue using deselect_all, but do not suppress the changed.jstree event (the true param). There is a plugin I am working on which will likely make it to the core - you can find it here:
https://github.com/vakata/jstree/blob/master/src/misc.js#L23
Include this plugin in your page, list it in your plugins config array and from then on you can rely on the changed collection of nodes to enable or disable nodes. Here is a demo:
http://jsfiddle.net/gLx3851k/5/

As for the single / multiple configs - it all depends on your use case really - you correctly noticed that if you need to restore state you'd be better off with two configs. I can't think of any other reason if everything else is the same - jsTree will work fine with both data formats even if using a single config.

I can't really help you with the duplicate items - it is too specific and I can't think of a general solution. From what I know about your requirements I'd probably use a combination of get_top_selected or get_bottom_selected to determine which nodes would be duplicated, or if possible I will not warn the user at all - if a parent is added and its child is added as well - I'd simply ignore it, if a child is added and its parent is added I would remove the child and leave only the parent ... basically I'd simply use get_top_selected if possible and not warn the user at all, just make the best possible selection. Of course - that may not be possible with your requirements, but I believe you are on the right track - using the get_selected, get_top_selected and get_bottom_selected functions should be enough for any type of check.

Let me know if the clear selection solution is OK for you (and ask away if you have any follow-ups).

Best regards,
Ivan

Roshan Kariyadan

unread,
May 11, 2015, 9:54:59 PM5/11/15
to jst...@googlegroups.com, rosh...@gmail.com

Thanks Ivan for the quick reply. Really appreciate that. As you said its a very interesting project. And when we analyzed all the plugins jsTree matched all the requirements we had.

1) I thought massload plugin is used for lazy loading. So in our case can you please help in mapping massload with the data config below. (I am loading the whole tree once - Alternative JSON format).
What does the cache config means at this level ? If I am using two different tree configs, cache means it will cache the tree in browser cache without making AJAX call when user open the tree again in UI(Our Tree data only changes in 24 hours. We have server level cache and refresh logic will run in night to refresh server cache). If I am using one tree config, using refresh to load two data formats then I think cache doesn't have any significance ?

'data' : {
  "type": 'GET',
  'cache': false,
  "dataType" : "json",
  "url": getTreeURL 
},
"plugins" : ["changed","massload","search","wholerow","checkbox","state","sort","types"]

2) changed plugin (deselect_all) is working exactly the way I needed. Thanks for sharing the new plugin. If(future need, not needed now) user needs a requirement to collapse all the children and expand only the childrens under top level parent can I configure that(when they do clear using deselect_all)

3) Two Tree Configs : Thanks for confirming.

4) User needs a warning in both cases.  Case 2 I am able to handle it. For Case 1, parent first and then adding children : Do we have any methods which will give all the parents for a selected tree item. (.parent gives immediate parent, how to get all the parents to check if any other top level parent is already in the cart ?)

Ivan Bozhanov

unread,
May 12, 2015, 2:49:41 AM5/12/15
to jst...@googlegroups.com, rosh...@gmail.com
Hi again,

1) Yes, massload is for lazy loading only, so it is not needed in your case. You could use caching to let the browser cache the AJAX response (and control the caching with the headers you return). Btw - when using data as an AJAX config - all the options are passed directly to jQuery (aside from data and url, which you can set to functions), so caching works as documented in the jQuery docs. To sum up - massload is not needed in your case, sorry - it was my mistake - I did not realize you are loading everything in a single request anyway (the purpose of massload is grouping requests). As you mentioned data only changes once in 24 hours - you may leverage the localStorage (if the data size allows for this) - set core.data to a function, when invoked if the localStorage is empty make an AJAX call, save the results and the datetime in localStorage, any future calls will fetch the data from localStorage until the time validity expires. I am just suggesting this in case you want to use refresh() instead of solution 2 - the one with the fiddle

2) I am glad the fiddle worked for you. If at some point you need to extend what the "clear selection" does you can - it will be a matter of invoking deselect_all(), then close_all() and then open_node(instance._model.data['#'].children)

4) Use the node's .parents property - it is an array of IDs (you can also take a look at the get_path() function: http://www.jstree.com/api/#/?q=get_path&f=get_path%28obj%20[,%20glue,%20ids]%29

Best regards,
Ivan

Roshan Kariyadan

unread,
May 13, 2015, 12:53:27 AM5/13/15
to jst...@googlegroups.com, rosh...@gmail.com
Thanks Ivan.
1) Thanks for the detailed info. 

2) Thanks that worked.

3) Already closed

4) .parents, get_path() gives all the top level parents. .children give all the children for a node. Initially I thought to handle this check using the AddtoCart button. But looks like get_selected,get_bottom_selected,get_top_selected gives a array for all the selected nodes. I meant the child-parent relationship is lost. Should I handle this in the "changed.jstree" event. In the event check inside the cart and give user the warning.

Also I thought of a different solution. Not sure if that work. After user added the items to cart, load the tree later I will diable the already selected nodes(parent, children). This way I can block from selecting the same parent node, children node. But user can still select top level parent. That I think again I need to handle in "changed.jstree" event ? Should I disable with selected or without selected ? Because get_selected,get_bottom_selected,get_top_selected returns the old selected values. 

Also is "ready.jstree" correct event to disable the nodes once the tree is loaded in UI ?

Below is the jsFiddle I was playing around. Still in working stage. Please see if I am in the correct direction. Thanks for your help.

Roshan Kariyadan

unread,
May 14, 2015, 8:42:49 PM5/14/15
to jst...@googlegroups.com
Hi Ivan. Thanks for your inputs.

Looks like I was able to implement most of the features. 
I am using the ready.jstree refresh.jstree event to control the disable of the nodes.I have a array with the default items, shppoing cart items and use that to disable using the below functions. Its working fine.
 data.instance.disable_node(shoppingCartNode);
 data.instance.disable_node(shoppingCartNode.children_d);

One issue I noticed.

1) Used $("#jstree_so").jstree(true).refresh();
I see the changed event is getting called each time the tree is loaded. (Deselected, selected events getting fired to instate the state). This was slowing my tree. I didnt set the state plugin. Refresh by default reinstate the state ?  

2)So I planned to use $("#jstree_so").jstree(true).refresh(false,true);

This didnt initiated a changed event because we are not reinstating the state. I am using selectedTopParentsArray =  instance.get_top_selected(true);
to get the top selected, its also returning the disabled nodes (which are not selected).Is there any other setting I need to change. Below is my tree config (getTreeURL - returns the URL to be called)

"#jstree_demo").jstree({
 "core" : {
 "multiple" : true,
 "animation" : 0, 
 "check_callback" : false,
 "themes" : { "theme": "default", "stripes" : true , "responsive" : true ,"icons": true}, 
 "types" : {
    "demo" : {
        "icon" : "glyphicon glyphicon-leaf"
    }
    },
 "data" : {
    "type": "GET",
    "cache": false,
    "dataType" : "json",
    "url": getTreeURL
   
  }
 },
 "plugins" : ["changed","search","wholerow","checkbox","sort","types"],
 
 "checkbox": { "keep_selected_style": false, "three_state": false, "cascade": "down"},
});

Roshan Kariyadan

unread,
May 14, 2015, 9:24:13 PM5/14/15
to jst...@googlegroups.com
Currently using below work around to get only the selected items from the top_selected. For the other items I see the state , selected:false.

shoppingCartTopParentsArray =  instance.get_top_selected(true);
for(k = 0, l = shoppingCartTopParentsArray.length; k < l; k++){  
if(instance.is_selected(shoppingCartTopParentsArray[k])){
          topParent =  shoppingCartTopParentsArray[k].id;
          childrenArray = shoppingCartTopParentsArray[k].children_d;

Ivan Bozhanov

unread,
May 15, 2015, 12:44:16 AM5/15/15
to jst...@googlegroups.com, rosh...@gmail.com
That is very odd - I will try and reproduce it - get_top_selected should only return selected nodes. If it is not too much too ask - can you provide a fiddle with a demo of this happening, if you do not have the time, I will try to find this myself, but it defeinitely is a but if get_top_selected returns nodes that are not selected.

Best regards,
Ivan

Roshan Kariyadan

unread,
May 15, 2015, 4:44:30 PM5/15/15
to jst...@googlegroups.com, rosh...@gmail.com
Sure. Let me try that. I will let you know once I can reproduce the same in jsFiddle. In the mean time let me show you the scenario, may be that will help.

1) On click of a button I load the tree in a new pop up page. And I make a selection in tree, close the pop up. Then click the button again to bring the tree again(this time make server call, refresh(false,true)).
Here we said not to reinstate the state. So my old selection should have being removed.

2) This time I dont make any selection in the screen. And I click on my Save button. In save button in my Tree popup I make a function call and get Tree instance in that.
var instance = $('#jstree_so').jstree(true);
Then I look do a top_selected I am seeing the old selection item, but its in disabled state.
selectedTopParentsArray =  instance.get_top_selected(true);
The object state is below :
disabled:false
loaded:true
opened:false
selected:false

I did a clear in the before step(2) and I see a deselect_all is called. This time in the Data object I see a item called , old_selected and I see the same object. Also in the deselected array list I see the same object.
After this I did the step 2, this time selections was correct. I need to test more. but this is what I see for now

Roshan Kariyadan

unread,
May 15, 2015, 4:46:39 PM5/15/15
to jst...@googlegroups.com
Made one update below. In section 1


On Friday, May 15, 2015 at 4:44:30 PM UTC-4, Roshan Kariyadan wrote:
Sure. Let me try that. I will let you know once I can reproduce the same in jsFiddle. In the mean time let me show you the scenario, may be that will help.

1) On click of a button I load the tree in a new pop up page. And I make a selection in tree, close the pop up. Then click the button again to bring the tree again(this time make server call, refresh(false,true)).
Here we said not to reinstate the state. So my old selection should have being removed. In the UI the state was not shown. But looks like the tree is holding that.

Roshan Kariyadan

unread,
May 15, 2015, 8:18:09 PM5/15/15
to jst...@googlegroups.com
The workaround of checking if the state of the node is_selected didnt come handy. I selected the parent first, then reopen the tree and select the child, the top_selected returned me the top parent which was selected earlier with state of selected of false. Right now I am doing a deselect_all() when I reload the tree. Initial testing is looking good. I will use this for time being until we find any other alternative.

Also I have 3k records. If I select the top parent it takes around 3 seconds to get all the items selected(I am using Cascade down). Occasionally the page is getting hung for around 1 sec and then come back. Is there any setting, function to handle this behavior better. I will do research over the weekend. Thought I will check with you.

"plugins" : ["changed","search","wholerow","checkbox","sort","types"],
 "checkbox": { "keep_selected_style": false, "three_state": false, "cascade": 'down'},

Ivan Bozhanov

unread,
May 16, 2015, 2:07:46 AM5/16/15
to jst...@googlegroups.com, rosh...@gmail.com
It must be something with refresh, but clearing the state - it looks like I am not clearing it - I will have a look - thanks.

As for the cascade down - I am afraid I can't offer you a faster solution. I have a few ideas for future jstree versions but I am not ready yet.

Best regards,
Ivan

Ivan Bozhanov

unread,
May 16, 2015, 3:17:03 AM5/16/15
to jst...@googlegroups.com, rosh...@gmail.com
I just pushed a commit in the repo, that should fix the issue with the selected state being internally preserved.


Best regards,
Ivan

събота, 16 май 2015 г., 3:18:09 UTC+3, Roshan Kariyadan написа:

Roshan Kariyadan

unread,
May 19, 2015, 11:48:26 AM5/19/15
to jst...@googlegroups.com, rosh...@gmail.com
Thanks Ivan for getting the fix in such a short time.

I had taken the latest version(3.1.1) and initial testing is looking good. I had removed the deselect_all which I was doing earlier. I will let you know if I ran into any issues.

Roshan Kariyadan

unread,
May 19, 2015, 1:37:15 PM5/19/15
to jst...@googlegroups.com
Hi Ivan,
The old selection is cleaned up now. But looks like there is one issue that I am noticing. 

With the same use case on step 2. If I open the tree again and try to select the same item from the tree, the changed event is not returning any values inside the data.changed object(the new plugin). I can see the data.selected returning the list.
Because the data.changed.selected is empty, my cascade down is not disabled for childrens.
for(i = 0, j = data.changed.selected.length; i < j; i++) {
   data.instance.disable_node(data.instance.get_node(data.changed.selected[i]).children_d);
}

Roshan Kariyadan

unread,
May 19, 2015, 1:54:17 PM5/19/15
to jst...@googlegroups.com
Also for Use case 2 : If I make another selection from the tree I see the data.changed object containing the selected, deselected objects populated. In the deselected objects I see the old selection that I had made.

Ivan Bozhanov

unread,
May 20, 2015, 1:28:10 AM5/20/15
to jst...@googlegroups.com, rosh...@gmail.com
I am terribly sorry, but I can't connect all previous replies - what was step 2? It seems the changed plugin is functioning normally - if the same node is selected, there is actually no difference, so the changed objects should be empty. Shouldn't the nodes already be disabled from the previous selection?

Best regards,
Ivan

Ivan Bozhanov

unread,
May 20, 2015, 1:29:41 AM5/20/15
to jst...@googlegroups.com, rosh...@gmail.com
That too sounds normal, since the old selection is deselected when making the new one. What is the issue here?

Best regards,
Ivan

PS. Sorry for the two separate replies - please continue in a single reply about the two issues :)

Roshan Kariyadan

unread,
May 20, 2015, 12:38:22 PM5/20/15
to jst...@googlegroups.com, rosh...@gmail.com
Hi Ivan,
Below are the steps that I did for replicating the issue. Sorry that I didn't put all the details earlier.

1) On click of a button I load the tree in a new pop up page. And I make a selection in tree, close the pop up. Then click the button again to bring the tree again(this time make server call, refresh(false,true)).

2) This time if I try to select the same selection from the tree, cascade down is working fine. But in the changed event the data.changed.selected is empty. So disable is not working fine.

$('#jstree_so').on('changed.jstree', function (e, data) {
     for(i = 0, j = data.changed.selected.length; i < j; i++) {
         data.instance.disable_node(data.instance.get_node(data.changed.selected[i]).children_d);
     }

Thanks
Roshan 

Ivan Bozhanov

unread,
May 20, 2015, 1:02:23 PM5/20/15
to jst...@googlegroups.com, rosh...@gmail.com
Sorry, it took me so long to understand - I just pushed a commit that fixes this (it is in the src/misc.js file - the changed plugin - copy it again).

Best regards,
Ivan

Roshan Kariyadan

unread,
May 21, 2015, 2:49:45 PM5/21/15
to jst...@googlegroups.com, rosh...@gmail.com
Hi Ivan,
Looks like the fix didn't worked. I tested the same use case and below is what I see:
1) On click of a button I load the tree in a new pop up page. And I make a selection in tree, close the pop up. Then click the button again to bring the tree again(this time make server call, refresh(false,true)).
2) This time when I load the tree, the old state is showing up in tree. Also the refresh event was not fired.

Ivan Bozhanov

unread,
May 21, 2015, 3:05:13 PM5/21/15
to jst...@googlegroups.com, rosh...@gmail.com
I am terribly sorry - it has been a long week (which is no excuse, of course). I messed up the "fix", I just added a new commit - sorry I wasted your time with the previous one.

Best regards,
Ivan

Roshan Kariyadan

unread,
May 27, 2015, 10:56:15 AM5/27/15
to jst...@googlegroups.com, rosh...@gmail.com
Thanks Ivan. Got up with some work. Missed to updated you on the test results.
I had removed the $("#jstree_so").jstree(true).deselect_all(); and then used the jsTree version 3.1.1 and the latest changed plugin. Looks like its working fine now.
I will keep testing and let you know if I see any issues. Thanks for Ivan for the help.

Thanks...
Roshan

Roshan Kariyadan

unread,
May 27, 2015, 5:37:30 PM5/27/15
to jst...@googlegroups.com
Also can you please let me know if I can apply the theme (different color/shade) for disabled items. I have existing items, new Items which I have disabled in the tree. Anyway to distinguish between the two using themes.

Ivan Bozhanov

unread,
May 28, 2015, 12:56:53 AM5/28/15
to jst...@googlegroups.com, rosh...@gmail.com
Disabled nodes have a class, I believe it was .jstree-disabled - just inspect them.

Best regards,
Ivan
Reply all
Reply to author
Forward
0 new messages