Dynamic Loading for Hierarchical Data Structures

This article discusses dynamic loading for Tree, TreeTable and TreeCollection. Refer to the main Dynamic Loading article if needed.

Data can be loaded dynamically into hierarchical components as follows:

  • First, the top parent nodes are loaded. Initially, they are collapsed (unless their open property is true).
  • Then, data is loaded under each node when it is expanded.
var tree = webix.ui({
  view: "tree",
  url: "data/data_dyn.php"
}); 
// or
var tree = webix.ui({});
tree.load("data/data_dyn.php");

By default, Webix expects JSON data. The server can also return XML - see Loading Tree Data.

Dynamic loading can be implemented in three different ways:

  • by setting the webix_kids property to true on nodes that can have children
  • by calling the loadBranch() method
  • by setting a custom handler for the onDataRequest event

Related sample:  Tree: Dynamic Loading

Using the webix_kids flag for dynamic loading

For parent data items that can have children, you can set the webix_kids flag to true. Adding this flag to the branch will result in rendering the related item as a folder.

webix.ui({
    view: "tree",
    url: "data/data_dyn.php",
    data: [
        // parent node below
        { id: "1", value: "Branch", webix_kids: true }
    ]
});

After the user opens the folder, the client will send a request to the server for more data, e.g.:

data/data_dyn.php?continue=true&parent=1

The URL in the request is based on the url property specified when initializing the component. Let's look at the URL more closely and, more specifically, at its parameters:

  • parent - the ID of the node/folder that has just been opened;
  • continue - the flag that indicates that it is an auto-generated request.

If url is specified, Webix will also make an initial request for that URL, without parameters. Make sure the server-side script can handle both situations: - the initial loading of data (top-level parent nodes), - loading children under a given parent node.

After sending the request, the client will expect to receive JSON with child items for the "Branch" item, e.g.:

{
    parent:"1", data:[
        { id:"11", value:"Some child item 1" },
        { id:"12", value:"Some child item 2" }
    ]
}

The child data can have the webix_kids attribute as well.

You can write custom scripts for dynamic loading of branches, or you can check the ready-made ServerSide connectors.

Using the loadBranch() function

You can catch the node expansion events (onBeforeOpen or onAfterOpen) to load branch data using the loadBranch method. Let's assume that we have initial data loaded:

webix.ui({
  view: "tree",
  data: [
    { id:1, value: "Layout Branch", webix_kids: true },
    { id:2, value: "Data Branch", webix_kids: true },
  ],
  on: {
    onBeforeOpen: function (id) {
      // if children have not been loaded yet
      if (this.getItem(id).$count === -1)
        this.loadBranch(id, null, "data/data_dyn.php");  // null means no callback
    }
  }
});

Related sample:  Loading branch Data

The URL of the new request will be based on the url property of the tree, which can be overridden by the loadBranch method - "data/data__dyn.php?continue=true&parent=1". The parameters are the same as above:

  • parent - the ID of the node that has just been opened;
  • continue - the flag that indicates that it is an auto-generated request.

If you want to use the same data source, omit the last parameter to loadBranch():

var tree = webix.ui({
  view: "tree",
  url: "data/data_dyn.php",
  ...
});
 
this.loadBranch(id, null);  // "data/data_dyn.php" will be used

Be sure the branch data sent by the server is an object with parent and data properties. A JSON response should look like this:

{ parent: 1, data: [ ...array of child items... ] }

Redefining onDataRequest Event

Set the onDataRequest event handler to redefine the default dynamic loading behavior and use any desired method to get the data from the server:

The event fires when the user expands a node that has the webix_kids property set:

{ id: "1", value: "Layout Branch", webix_kids: true }

As it is stated above, this event triggers dynamic loading. In other words, if a component features a data source (defined either by url property or load method) a request is issued using this url.

Still, the onDataRequest event makes it possible to redefine the logic in favor of custom one.

Let's assume that we have initial data loaded in some of the ways:

webix.ui({
    view: "tree",
    data: [
        { id: 1, value: "Layout Branch", webix_kids: true },
        { id: 2, value: "Data Branch", webix_kids: true },
    ],
    on: {
        onDataRequest: function (id) {
            webix.message("Getting children of " + id);
            this.parse(
                webix.ajax().get("data/data_dyn_json.php?parent="+id)
                .then(function(data){
                    return data = data.json();
                });
            );
            // canceling default behavior
            return false;
        }
    }
});

Related sample:  Dynamic Loading: Modifying onDataRequest Event

Here you completely redefine the default event handling and cancel default dynamic loading behavior.

Be sure the branch data you get is returned with parent and data properties. For JSON the returned data looks like this:

{ parent:1, data:[ ..array of child items..]}

Related Articles

Back to top