Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy loading #16

Open
edgesoft opened this issue Oct 20, 2015 · 14 comments
Open

Lazy loading #16

edgesoft opened this issue Oct 20, 2015 · 14 comments

Comments

@edgesoft
Copy link

I have a very large tree that I won't be able to load on initialization. Would it be possible to do lazy loading? A user clicks on a node and fetches data from server and adds it to the tree. We would need some way of telling the node that it has children but it should be loaded from the server.

@wangzuo
Copy link
Contributor

wangzuo commented Oct 21, 2015

How large is the tree?

@edgesoft
Copy link
Author

More than 10.000 nodes ( Not for every user. Some has just 100 ). All won't expand every time a user works in the tree.

@dannav
Copy link

dannav commented Oct 21, 2015

Are you not able to do that in renderNode? You could update the tree when a node is selected.

@edgesoft
Copy link
Author

Let's say I want to move a node with many children to another nodes child. I need to expand the node on hover and then fetch data from server. And then be able to hover yet another node that was just fetched and fetch until the user finds which node he/she wants to move to. I need to refresh on hover and expand lazily. I don't know how to accomplish that right now.

@edgesoft
Copy link
Author

@wangzuo Proposing to add lazy boolean to the tree. If the tree is lazy then we should check index.hasChildren and not just index.children && index.children.length. An onBeforeOpenNode event should be called in toggleCollapse to allow fetching data from server before we expand.

{ module: 'parent', leaf: false, hasChildren: true }

@edgesoft
Copy link
Author

Something like this so far. This will enable lazyloading per node.

modules

{
   module: 'test',
   leaf: false,
   hasChildren: true,
   collapsed: true,
   lazy: true
}

react-ui-tree.js

 toggleCollapse(nodeId) {
    var tree = this.state.tree;
    var index = tree.getIndex(nodeId);
    var node = index.node;
    if( this.props.onLazyloadNode && node.lazy && node.hasChildren ){
      node.lazy = false;
      this.props.onLazyloadNode(node, function(nodes){
          nodes.map( newNode => {
             tree.append(newNode,nodeId);
          } );
         this.makeToggleUpdate(node);
      }.bind(this));
    }else{
      this.makeToggleUpdate(node);
    }
  },

  makeToggleUpdate(node){
    var tree = this.state.tree;
    node.collapsed = !node.collapsed;
    tree.updateNodesPosition();

    this.setState({
      tree: tree
    });

    this.change(tree);
  }

node.js. Updated node.hasChildren

renderCollapse() {
    var index = this.props.index;
    var node = index.node;
    if(node.hasChildren || (index.children && index.children.length)) {
      var collapsed = index.node.collapsed;

      return (
        <span
          className={cx('collapse', collapsed ? 'caret-right' : 'caret-down')}
          onMouseDown={function(e) {e.stopPropagation()}}
          onClick={this.handleCollapse}>
        </span>
      );
    }

    return null;
  },

exampel app.js

  <Tree
       paddingLeft={20}
       tree={this.state.tree}
       onChange={this.handleChange}
       isNodeCollapsed={this.isNodeCollapsed}
       renderNode={this.renderNode}
       shouldRenderRootNode={true}
       onLazyloadNode={this.onLazyloadNode}
   />


  onLazyloadNode(node,cb){
    console.log( "Before expand" );
    setTimeout(function(){
      var nodes  = [
        {module: 'mathias', leaf: false, collapsed: true, lazy: true,hasChildren : true}
      ];
      cb( nodes );
      console.log( "After expand" );
    },2000);

  },

@tobyndockerill
Copy link

This seems like a good improvement that will become more necessary as the amount of nodes increase. I have a project that has around 5000 nodes and it can get quite slow.

Should the suggested changes be in a pull request?

tobyndockerill pushed a commit to tobyndockerill/react-ui-tree that referenced this issue Oct 29, 2015
@wangzuo
Copy link
Contributor

wangzuo commented Oct 29, 2015

Thanks! will try to add this feature.

@edgesoft
Copy link
Author

@wangzuo I didn't commit this yet but accepted the pull request from @tobyndockerill because there is still a problem to solve. When clicking the expand arrow multiple times we should have a behaviour. What should happen? Right now we set the lazy to false so that we don't fetch data from server again. But the toggle is slow an feels unresponsive. Should we lock the node currently lazyloading to prevent toogle when loading? Have a spinner? any suggestions?

@edgesoft
Copy link
Author

The best suggestion so far is to lock click on the arrow and show a svg spinner instead of the arrow. Is this a good solution? @wangzuo @tobyndockerill

@tobyndockerill
Copy link

I agree. A loading indicator would go a long way to show the user that something is happening behind the scenes.

@rohan-deshpande
Copy link

I am also super interested in this, drag and drop becomes extremely slow even in a moderately sized tree

@mofadlalla
Copy link

I'm interested in this too, any chance there's going to be a PR for this soon?

@wizzardich
Copy link

I'd love to see this feature implemented as well. It would help immensely, and it is a very nice thing to have anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants