3

In jsTree, I want to draw a new tree replacing the previous one and have nodes initially selected in the new tree.

In the code below, I confirmed that state : {opened : true} made the node initially opened and state : {disabled : true} made the node initially disabled, so I thought state : {selected : true} works too, but actually it is not.

Please note that specifying state : {selected : true} when calling $('#using_json').jstree({...}); does result in the node selected as described in https://www.jstree.com/docs/json/. Then, I wonder why state : {selected : true} does not work when I replace a existing tree with a new tree (while state : {opened : true} and state : {disabled : true} are working).

How can we achieve nodes to be initially selected after replacing tree?

$('#using_json').jstree({ 'core' : {
    data : [
      {
         text : 'Previous root node',
      }
    ]
} });

const newData = [
       {
         text : 'New root node (Initially opened)',
         state : {
           opened : true,       //'opened' takes effect after refresh
         },
         children : [
           { text : 'Child 1 (Initially disabled)',
             state : {
               disabled : true, //'disabled' takes effect after refresh
             }
           },
           { text : 'Child 2 (Intended to be selected initially but failing)',
             state : {
               selected : true  //'selected' does NOT take effect after refresh
             }
           }
         ]
      }
    ]

$('#using_json').jstree(true).settings.core.data = newData;
$('#using_json').jstree(true).refresh(true);
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.4/themes/default/style.min.css" />
</head>
<body>
  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.4/jstree.min.js"></script>
  <div id="using_json"></div>
</body>
</html>
Tomoyuki Aota
  • 867
  • 9
  • 18

1 Answers1

3

You could try using the select_node config property when you initialize the tree, which you could do just once. For this you need to add some IDs to your nodes so you can then reference the selected node:

$('#using_json').jstree({
  'core': {
    select_node: 'c2',
    data: [{
      text: 'Root node after Refresh (Opened)',
      state: {
        opened: true, //'opened' takes effect after refresh
      },
      children: [{
        text: 'Child 1 (Disabled)',
        id: 'c1',
        state: {
          disabled: true, //'disabled' takes effect after refresh
        }
      }, {
        text: 'Child 2 (Intended to be selected but failing)',
        id: 'c2',
        state: {
          selected: true //'selected' does NOT take effect after refresh
        }
      }]
    }]
  }
});

//$('#using_json').jstree(true).settings.select_node = 'c2';
//$('#using_json').jstree(true).refresh(true);
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.4/themes/default/style.min.css" />
</head>
<body>
  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.4/jstree.min.js"></script>
  <div id="using_json"></div>
</body>
</html>

Check out this answer also.


Alternative with refresh

Since OP needs to keep the initial code structure (init -> change config data -> refresh) an alternative solution would be to "force" selection by using the callback of the refresh event:

$('#using_json').jstree({
  'core': {
    data: [{
      text: 'Previous root node',
    }]
  }
});

const newData = [{
  text: 'New root node (Initially opened)',
  state: {
    opened: true, //'opened' takes effect after refresh
    selected: true
  },
  children: [{
    text: 'Child 1 (Initially disabled)',
    id: 'c1',
    state: {
      disabled: true, //'disabled' takes effect after refresh
    }
  }, {
    text: 'Child 2 (Intended to be selected initially but failing)',
    id: 'c2',
    state: {
      selected: true //'selected' does NOT take effect after refresh
    }
  }]
}];

$('#using_json').jstree().settings.core.data = newData;
//$('#using_json').jstree(true).settings.select_node = 'c2';
$('#using_json').jstree(true).refresh(true);
$('#using_json').on("refresh.jstree", function(e) {
  $('#using_json').jstree('select_node', 'c2');
});
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.4/themes/default/style.min.css" />
</head>
<body>
  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.4/jstree.min.js"></script>
  <div id="using_json"></div>
</body>
</html>
Andrei Roba
  • 2,156
  • 2
  • 16
  • 33
  • I would like to have the node selected _not_ at the time of creating the tree for the first time but after replacing it with another new tree. (That is the reason why I assign`newData` to `$('#using_json').jstree(true).settings.core.data` and call `$('#using_json').jstree(true).refresh(true);`.) Sorry for misleading wording. I rephrased my question. – Tomoyuki Aota Dec 07 '17 at 16:12
  • When calling `$('#using_json').jstree({...});`, specifying `state : {selected : true}` does result in the node selected as described in https://www.jstree.com/docs/json/. – Tomoyuki Aota Dec 07 '17 at 16:18
  • I see what you mean - I propose an alternative version with refresh in this case. Regards, – Andrei Roba Dec 07 '17 at 16:44