Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FancyTree load all nested children on select

Here's my issue. I'm using checkboxes and lazy load via ajax. However, if you were to check a parent item without expanding it, none of the child nodes have been loaded so they don't get checked. How can I load all child and nested child nodes under a parent, and check them all, when they check the parent? Thanks, and this is what I have so far

$(function () {
    // Create the tree inside the <div id="tree"> element.
    $("#tree").fancytree({
        source: { url: "/Home/GetData", cache: true }
        , checkbox: true
        , icons: false
        , cache: true
        , lazyLoad: function (event, data) {
            var node = data.node;
            data.result = {
                url: "/Home/GetTreeViewData/" + node.key
                , data: { mode: "children", parent: node.key }
                , cache: true
            };
        }
        , selectMode: 3
        , select: function (event, data) { //here's where I need to load the children and any sub children for that node, if it has them, so they can be set to checked

        }
        , strings: {
            loading: "Grabbing places and events…",
            loadError: "Load error!"
        },
    })
});

Update The reason I need to pull these client side is because this is a treeview that will be loading google map markers. So if I have a structure like

Parent1
->child1-1
->->child1-1-1
->child1-2

all of those child nodes load lazy. however, if they were to check the parent node 1, then I'd need to load the markers for all of those child nodes. That's why I'm looking for a way to recursively get all the children. Because it would be really hard to keep track of what markers have/haven't been added, if I don't just load the treeview items and check the boxes. Make sense?

like image 375
Michael Andrews Avatar asked Jan 11 '23 00:01

Michael Andrews


2 Answers

I think you could use select event:

select: function(event, data) {
    var node = data.node;

    if (node.isSelected()) {
        if (node.isUndefined()) {
            // Load and select all child nodes
            node.load().done(function() {
                node.visit(function(childNode) {
                    childNode.setSelected(true);
                });
            });
        } else {
            // Select all child nodes
            node.visit(function(childNode) {
                childNode.setSelected(true);
            });
        }
    }
}

That way if the child nodes haven't been loaded they will be loaded and selected after that.

like image 151
Andrey M. Avatar answered Jan 22 '23 04:01

Andrey M.


First: maybe you don't even need to load all child nodes.

In selectMode: 3 a selected parent means 'all children are selected too', so if you post the top-most selected parent nodes to your server, the backend could handle it accordingly. The stopOnParent argument of the tree.getSelectedNodes method supports this as well.

Another option would be to fix the the selection state of child nodes after a lazy parent was loaded:

$("#tree").fancytree({
  checkbox: true,
  selectMode: 3,
  source: { url: "/getTreeData", cache: false },
  lazyLoad: function(event, data) {
      data.result = {
          url: "/getTreeData",
          data: {mode: "children", parent: node.key},
          cache: false
      };
  },
  loadChildren: function(event, data) {
    // Apply parent's state to new child nodes:
    data.node.fixSelection3AfterClick();
  },

Update

If you really need to load the lazy child nodes when the parent is selected, you could try in addition to the above code (untested)

$("#tree").fancytree({
  ...
  select: function(event, data) {
    if( data.node.isUndefined() ) {
      data.node.load(); // triggers lazyLoad to load children
      // alternative:  node.expand()
    }
  },
like image 34
mar10 Avatar answered Jan 22 '23 04:01

mar10