vakata / jstree

jquery tree plugin
http://jstree.com
MIT License
5.13k stars 1.39k forks source link

Unexpected JSTree state behavior #2728

Closed Mr-Saltman closed 12 months ago

Mr-Saltman commented 1 year ago

Hello there! So I am using JSTree in my Django project and I am experiencing some unexpected behavior when retrieving the state.

Before I explain what the issue is, I want to introduce how I intend to use the JSTree. So I have a menu on the left side of my main page, which always stays there. The JSTree is located in this menu and functions like an explorer, giving the user an interface to navigate through the objects displayed, just like folders in e.g. windows explorer. When the user (for instance) adds new objects (that are displayed in the JSTree), he is returned to the main page, where the JSTree is destroyed and reinitialized (thats the current implementation, I might opt to change it in the future tho). My desired behavior would be, that the JSTree keeps its state, so if the user decides to add/delete/edit an object, he does not have to open the folder structure again, to reach the point where he was before.

Currently, everything expect restoring the state is working properly. Although, there is a scenario, where it behaves as expect. There are two different scenarios:

1.) When I am on the main page and refresh the page in my browser, the JSTree restores the state as expected, which is great.

2.) When I click on the Logo on the top menu (which hrefs the user to the main page, in whichs html the tree script is located), the tree does only restore the state of top-level objects. So every objects that were opened below top level will be closed, which seems kind of odd, since in the local storage, the value of the jstree seems to be the state the tree should be in, but in fact it is not. I guess it is having trouble retrieving the state from the local storage?

As far as I understand, the behavior should be the same in both scenarios, since its basically just running the script in my html either way, so I am unable to explain this behavior.

My script looks like this:

<script>
    function formatData(data) {
    var formattedData = [];

    data.forEach(function (node) {
        var formattedNode = {
            'id': node.id,
            'text': node.text,
            'state': node.state,
            'data': node.data,
            'children': formatData(node.children || []) // Recursively format the children
        };

        formattedData.push(formattedNode);
    });

    return formattedData;
    }

    $.getScript("{% static 'cabinets/node_modules/jstree/dist/jstree.min.js' %}")
        .done(function() {
            function initJSTREE() {
                var jstreeElement = $('#jstree_global');

                jstreeElement.jstree('destroy');

                jstreeElement
                    .on('select_node.jstree', function(e, data) {
                        if (data.selected.length) {
                            partialNavigation.setLocation(data.instance.get_node(data.selected[0]).data.href);
                            }
                        })
                    .jstree({
                        'core': {
                        'data': function(node, callback) {
                            $.ajax({
                                'url': "{% url 'common:jstreerefreshview' %}",
                                'dataType': 'json',
                                'success': function(data) {
                                    console.log('Data collected: ', data);
                                    callback.call(this, formatData(data));
                                }
                            });
                            },
                            'themes': {
                                'responsive': true
                            },
                            'check_callback': true
                        },
                        'plugins': ['state']
                    });
        }

        initJSTREE();
        })
        .fail(function(jqxhr, settings, exception) {
            console.error('Error loading jstree.min.js:', exception);
        });
</script>

When the jstree.min.js is loaded, the jstree is destroyed and reinitialized (I also tried redraw and refresh, but this will not update the tree data).

I am looking forward to any ideas or suggestions,

Thank you in advance!

vakata commented 1 year ago

As long as the object is accessible in localStorage (which should be the case if the domain and port are the same), then jstree will restore opened and selected nodes based on their IDs - are the node IDs the same between refreshes?

vakata commented 12 months ago

Will reopen when more information is available

Mr-Saltman commented 11 months ago

Hey there! First of all, I want to thank you, because I somehow actually messed up the ids of my nodes... So I fixed that now. What I am wondering now is if there is a way to use the state plugin without the selected feature? The nodes in my tree use href to link to a corresponding page but my saving the last selected node, the user will never be able to reach the actual main page (since there the jstree is initialized again & again, which makes the state plugin select the node which hrefs to another page).

Or is there a option to deselect a node?

Thank you in advance