Proper way to load tree state on a page refresh?

In short:
Is there a better way to restore the state of the tree when the page loads?

Some details:
I have an interesting problem.

I’m using a treetable and would like to save the state when someone opens or closes nodes.

When the page reloads I would also like for the tree to restore itself to the state it was in before they left the page.

What I’m doing below works (yay). However… you have to click the plus sign two times instead of one time in order for the node to open. If I remove the onAfterLoad event, it only requires one click - not two - but the state doesn’t restore when the page reloads.

I see that the onAfterLoad event is being triggered with each node that gets opened (thankfully only on the first click).

Is there a better way to restore the state of the tree when the page loads? (I’ve also tried to restore the state within on a webix.ready event but the state of the tree doesn’t update.)

Here is the code. Any thoughts?


            {

                id:"requirementsContent", 

                view:"treetable",

                url:"/requirements.json",

                columns:[

                    { 

                        id:"name",

                        header:"Component",

                        template:"{common.treetable()} #name#",

                        fillspace:true

                    },

                    {

                        id:"kind",

                        header:"Type",

                        fillspace:true

                    },

                    {

                        id:"state",

                        header:"Status",

                        fillspace:true

                    },

                    {

                        id:"actions",

                        header:"Actions",

                        fillspace:true,

                        template:" Edit |  Add"

                    }

                ],

                on:{

                    onBeforeOpen: function(id){

                        // If children have not been loaded yet, load them.

                        if (this.getItem(id).$count === -1){

                            this.loadBranch(id, null);  // null means no callback

                            webix.message({ 
                              type:"error", 
                              text:"Please click the plus sign a second time. 
                                      This is a bug we are working to resolve."
                            })

                        }

                    },

                    onAfterOpen: function(id){

                        //webix.message("After Open " + id);

                        // Save the state of the tree after an element been opened.

                        var state = this.getState();

                        webix.storage.local.put("requirements_content_treetable_state", state);

                    },

                    onAfterClose: function(id){

                        //webix.message("Closing " + id);

                        // Save the state of the tree after an element been opened.

                        var state = this.getState();

                        webix.storage.local.put("requirements_content_treetable_state", state);

                    },

                    // TODO: This causes the user to need to click the + 
                    // symbol 2 times. Need to understand why. 
                    // For now we'll leave this.

                    onAfterLoad: function(id){

                        var state = webix.storage.local.get("requirements_content_treetable_state");

                        if (state){

                            this.setState(state);

                        }

                    }

                }

            }

Hi. Check the following snippet, please: http://webix.com/snippet/5d71146c

I didn’t manage to spot the problem with two clicks. In the snippet you can see how state changes with every open/close event.

To save the state of a treetable on page reloading, use the next code:

webix.attachEvent('unload', function(){
     webix.storage.local.put("state", $$("treetable").getState());
});

To restore the state, call the setState after component initialization (as shown in the snippet above) or within ready handler (http://webix.com/snippet/79879117).

Hi Helga,

After looking at your example I see were I can improve.

This is remarkably helpful! I’ve made these changes and it’s working great.

Also, I was able to remove the onAfterClose and onAfterOpen events I had put in there just to capture the state of the treetable. (At the time I didn’t think about other events I might need to do this with. Sorting, resizing, etc… So, your solution definitely seems like the best practice for this.)

For anyone else interested in doing this:

  1. Capture the state of the table when someone leaves the page (unload event).
  2. Reload the state of the tree when it’s ready (the treetable’s ready event).

Now that I think of it, these both are pretty straight forward (it makes a lot more sense than what I was trying to do).

=)

Thanks a bunch for your help on this!

Sincerely,
Jay

For anyone having issues with state not being saved:

I did some more testing on this and it looks like unload event isn’t always triggered in every browser. It also doesn’t work if you use javascript (window.location) to move to a different page.

So I’ve added the onAfterClose and onAfterOpen again. I’ll update this if I come up with something better.

Sorry to keep updating my own thread here… but I found a very solid solution (seems solid so far).

Using the beforeunload event allows you to use window.location.href for page navigation and it still captures the state of the treetable.

This has worked for me in all the cases.

`
$(window).on('beforeunload', function(){
  webix.storage.local.put("tree_table_state", $$("treetable").getState());
});
`

Thanks again Helga I would not have looked into this without your initial direction.

webix.storage.local

This api stores the value in the local storage ( not cookies )
If you want to store data in cookies, you can use webix.storage.cookie.put

Please…is the state data saved to a client/server disk in a cookie? Where exactly? When does it expires?