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

Dynamic loading - children #37

Closed
rat43 opened this issue Jun 20, 2012 · 39 comments
Closed

Dynamic loading - children #37

rat43 opened this issue Jun 20, 2012 · 39 comments

Comments

@rat43
Copy link

rat43 commented Jun 20, 2012

At the first moment my tree contains only the root nodes and their children.
This children don't have children because they are loaded dynamically when the user clicks on the node (using loadData).

In this case, the layout doesn't show the arrows on the nodes that don't have children, but I need the arrows, for presentation issues.

To resolve this, I added an anchor with class="toggler closed", but this arrow doesn't have the open and close event.

How can I solve this case?

@mbraak
Copy link
Owner

mbraak commented Jun 21, 2012

You could add a single phantom node to the children.

Very sketchy sample code:

$tree.tree.appendNode(
  {
    label: 'phantom',
    phantom: true
  },
  parent_node
);

Catch the tree.open event. This event is fired when a node is opened.

$tree.bind(
  'tree.open',
  function(e) {
    var node = e.node;
    var first_child = node.children[0];

    // Is this a phantom node?
    if (first_child.phantom) {
      // Remove the node
      $tree.removeNode(first_child);

      // Load children. Insert your code here.
    }
  }
);

@mbraak
Copy link
Owner

mbraak commented Jun 21, 2012

Do you think that jqTree should add support for dynamically loading of children? If so, what should the API look like?

@rat43
Copy link
Author

rat43 commented Jun 25, 2012

Ok, the phantom node helps me.

About second comment, I think it's interesting.
We could work with a property hasChildren in the data and enable an option onOpenNode in Tree.
So, when user open the node and he hasChildren, we call onOpenNode, which loads the data from the server.

@rat43
Copy link
Author

rat43 commented Jun 29, 2012

Hello,

It doesn't work!
The tree don't bind de node correctly, when i remove the phantom and load new data.

@mbraak
Copy link
Owner

mbraak commented Jun 30, 2012

I made an example on http://jsfiddle.net/QAt6Z/6/ to demonstrate the idea.

@rosenfeld
Copy link
Contributor

I'm using this exact technique here, so I guess it would be great to have some common API. In my case, instead of 'phantom' I use the "loading..." label and the "fetched" property to check if the children were already fetched or not.

@mbraak
Copy link
Owner

mbraak commented Jul 1, 2012

I can see that there is a need for lazy loading of nodes. I will look into it.

@rat43
Copy link
Author

rat43 commented Jul 2, 2012

Thank you!
My problem was in the json data, a property was not being serialized correctly.

@mbraak
Copy link
Owner

mbraak commented Jul 8, 2012

I'm still thinking about a good API for lazily loading nodes, but I haven't found a good solution yet.

@mbraak
Copy link
Owner

mbraak commented Jul 25, 2012

JqTree now supports load-on-demand. It's in the load-on-demand branch.

There is no documentation yet, but there is an example in /examples/example5.html.

@rosenfeld
Copy link
Contributor

Great, I'll try it soon

@rat43
Copy link
Author

rat43 commented Jul 26, 2012

Thanks!

@rosenfeld
Copy link
Contributor

Could you please provide some hook for onLoadData() with the original data? The problem is that I need to keep the original one (containing 'label', for instance)

@mbraak
Copy link
Owner

mbraak commented Jul 27, 2012

So, just to make sure I understand you correctly. You want jQtree to fire an event when the data is loaded. And this event should have a link to the original loaded data.
Event could be tree.load_data. Original loaded data could be in event.tree_data. EDIT: (changed event.data to event.tree_data)

I think that is possible. I also think it should be a general event. So, it is fired when the initial data for the tree is loaded, and when data is loaded on demand. (And also when data is loaded without ajax, using the data option).

Is this what you what you had in mind?

By the way, thanks for the pull-request that fixes the load-on-demand example.

@rosenfeld
Copy link
Contributor

Exactly, thanks :) No problem :)

@mbraak
Copy link
Owner

mbraak commented Jul 28, 2012

I added the tree.load_data event. It's in the load-on-demand tree.

Detail: the data is in the event.tree_data property. The data property is already used by jQuery.

@rosenfeld
Copy link
Contributor

Thank you so much. I could finally replace my custom handling with the built-in handling you have just implemented. :)

@rat43
Copy link
Author

rat43 commented Jul 30, 2012

I need more than one parameter of the node-id.
Because my node id is not unique in the tree, but is unique in its category.
The query server is given by type and id.

Is there any way to pass additional parameters?

@mbraak
Copy link
Owner

mbraak commented Jul 30, 2012

At this moment that's not possible.

@rat43
Copy link
Author

rat43 commented Jul 30, 2012

And if we sent the node object as parameter, it would be a bad idea?

@rosenfeld
Copy link
Contributor

I really believe this should be a GET request and I'm not sure if the node object would even be serializable to be sent in a POST request either.

I also had to change my server code as my URLs were like /nodes_from_parent/324 and now the requests are like /nodes_from_parent?node=324. Maybe we could provide an option to the tree() call:

$('#tree').tree( {
  dataUrl: function(parentNode) {
    return {
      url: '/from_parent',
      type: 'get',
      data: { node: parentNode.id }
    };
  } 
});

I guess something like that would be very flexible.

@rat43
Copy link
Author

rat43 commented Jul 30, 2012

Yes, that would be perfect.

@mbraak
Copy link
Owner

mbraak commented Jul 30, 2012

I guess it's possible to customize the url. And this looks like an elegant solution.

So, your idea is: the dataUrl option can be a url, or it can be a function that returns an url object.

What do you think of this?

  • The function returns a url string (not an object)
  • The function is called for load-on-demand, but also for the initial data
$('#tree').tree({
  dataUrl: function(parentNode) {
    if (! parentNode) {
      return '/my_data/';
    }
    else {
      return '/my_data/' + parentNode.id + '/';
    }
  }
})';

@rosenfeld
Copy link
Contributor

Yep, that is exactly what I had in mind (except for the initial data, but I also agree on it).

I guess you're talking about two possibilities:

1 - the function returns a string

We should then issue a GET request to that string.

2 - the function returns an object

Use like in my prior example

And, of course, if dataUrl is a string itself, the current behavior would remain intact.

@mbraak
Copy link
Owner

mbraak commented Jul 31, 2012

Yes, those are the options. I think I'm going for the first option because that is the most simple one.

@rosenfeld
Copy link
Contributor

Sorry, but I don't understand. They're not exclusive options. You can support all of them. Please let me know what do you think you need to decide between.

@mbraak
Copy link
Owner

mbraak commented Jul 31, 2012

I think that jqTree should support the following for dataUrl:

string:

dataUrl: '/nodes/'

or a function that returns a string:

dataUrl: function(node) {
    if (node) {
        // load on demand
        return '/nodes/' + node.id + '/';
    }
    else {
        // initial data
        return '/nodes/';
    }
}

@rosenfeld
Copy link
Contributor

The problem with returning just a string is that you would be limited to GET requests only. Also, you'd need to encode the URL by yourself, while you could let jQuery handle it for you...

I mean, returning a string would be good to my situation but not that good for @rat43.

@mbraak
Copy link
Owner

mbraak commented Jul 31, 2012

I'm guessing that a GET request will also work for rat43.

@rosenfeld
Copy link
Contributor

But still he'll need to build the query string by himself, since he needs to send multiple parameters (data type and id). What if data type needs to be URL encoded? If he could just return an object with the data to be encoded, jQuery.ajax would take care of it.

@rat43
Copy link
Author

rat43 commented Jul 31, 2012

A GET request solve my problems.
Just to understand, when I inform the url the plugin will no longer inform the node-id as a parameter, right?

@mbraak
Copy link
Owner

mbraak commented Jul 31, 2012

Yes, if you use the function, then no parameter is added.

I'm still thinking about the url encoding. Is there another way to encode the parameters correctly?

@rosenfeld
Copy link
Contributor

$.param({a: 1, b: 'a b'}) == "a=1&b=a+b"

@mbraak
Copy link
Owner

mbraak commented Aug 2, 2012

I updated the load-on-demand branch. It is now possible to use a function for the dataUrl option.

Note that the function must return a url string. This was far easier to implement than the object version.

Example:

dataUrl: function(node) {
    if (node) {
        // load on demand
        return '/nodes/' + node.id + '/';
    }
    else {
        // initial data
        return '/nodes/';
    }
}

@rosenfeld
Copy link
Contributor

Thank you, Marco

@rat43
Copy link
Author

rat43 commented Aug 7, 2012

Thanks, I'll look soon

@rosenfeld
Copy link
Contributor

Any estimates about when this will be merged to master and released? I've already tested it on my application and it is working great. Maybe a loading indicator could be interesting if the network connection is pretty bad, but it is already good enough for me as it is.

@mbraak
Copy link
Owner

mbraak commented Aug 14, 2012

It's now in the master branch. This version is 0.12.

By the way, jqTree does add a jqtree-loading class to the li that is being loaded. See examples/example.css.

@rosenfeld
Copy link
Contributor

Humm... this is insteresting :) Thank you for letting me know. Looking forward to 0.12...

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

No branches or pull requests

3 participants