LinkTree lazy loading possible?

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

LinkTree lazy loading possible?

pixotec-2
I want to use LinkTree to represent a very very large hierarchy (the loading of the whole thing is expensive...).
Is there an AJAX way of loading the children of a node just when clicking on the "plus-icon" for expanding?
Reply | Threaded
Open this post in threaded view
|

Re: LinkTree lazy loading possible?

Matej Knopp-2
Of course. You just need to implement proper TreeModel that lazily
loads children.

-Matej

On 9/21/07, pixotec <[hidden email]> wrote:

>
> I want to use LinkTree to represent a very very large hierarchy (the loading
> of the whole thing is expensive...).
> Is there an AJAX way of loading the children of a node just when clicking on
> the "plus-icon" for expanding?
>
> --
> View this message in context: http://www.nabble.com/LinkTree-lazy-loading-possible--tf4493231.html#a12814684
> Sent from the Wicket - User mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: LinkTree lazy loading possible?

swaroop belur
In reply to this post by pixotec-2

Initially when building the tree , just add a single child node to each  first level of nodes u show
You can mark this node as a "indicator node" or a "busy node" - this will allow the + sign to come
up for the actual node. When u click on the + sign , representing the actual node , just
remove the busy/ indicator node after all the actual children have been added ...(also just check if the indicator  node is the only child - this way u will avoid another database hit for the second open click
for the same node.)




pixotec wrote
I want to use LinkTree to represent a very very large hierarchy (the loading of the whole thing is expensive...).
Is there an AJAX way of loading the children of a node just when clicking on the "plus-icon" for expanding?
Reply | Threaded
Open this post in threaded view
|

Re: LinkTree lazy loading possible?

Matej Knopp-2
Heh, sorry, didn't read the entire question. This seems to be the
right approach.

-Matej

On 9/21/07, swaroop belur <[hidden email]> wrote:

>
>
> Initially when building the tree , just add a single child node to each
> first level of nodes u show
> You can mark this node as a "indicator node" or a "busy node" - this will
> allow the + sign to come
> up for the actual node. When u click on the + sign , representing the actual
> node , just
> remove the busy/ indicator node after all the actual children have been
> added ...(also just check if the indicator  node is the only child - this
> way u will avoid another database hit for the second open click
> for the same node.)
>
>
>
>
>
> pixotec wrote:
> >
> > I want to use LinkTree to represent a very very large hierarchy (the
> > loading of the whole thing is expensive...).
> > Is there an AJAX way of loading the children of a node just when clicking
> > on the "plus-icon" for expanding?
> >
> >
>
> --
> View this message in context: http://www.nabble.com/LinkTree-lazy-loading-possible--tf4493231.html#a12814930
> Sent from the Wicket - User mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: LinkTree lazy loading possible?

Matej Knopp-2
In reply to this post by swaroop belur
Well, actually, I'm not sure how this would work, as you'd have to
load the children asynchronously and then update the tree. That
certainly isn't a trivial thing. I guess it would be better to replace
the link with an indicatingajaxlink or something like that.

-Matej

On 9/21/07, swaroop belur <[hidden email]> wrote:

>
>
> Initially when building the tree , just add a single child node to each
> first level of nodes u show
> You can mark this node as a "indicator node" or a "busy node" - this will
> allow the + sign to come
> up for the actual node. When u click on the + sign , representing the actual
> node , just
> remove the busy/ indicator node after all the actual children have been
> added ...(also just check if the indicator  node is the only child - this
> way u will avoid another database hit for the second open click
> for the same node.)
>
>
>
>
>
> pixotec wrote:
> >
> > I want to use LinkTree to represent a very very large hierarchy (the
> > loading of the whole thing is expensive...).
> > Is there an AJAX way of loading the children of a node just when clicking
> > on the "plus-icon" for expanding?
> >
> >
>
> --
> View this message in context: http://www.nabble.com/LinkTree-lazy-loading-possible--tf4493231.html#a12814930
> Sent from the Wicket - User mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: LinkTree lazy loading possible?

ianpg
In reply to this post by pixotec-2
I am doing the same thing.

I have it working except for one problem.

The loading works fine but so far I have not found a way to make the tree update its display when an item is added to the data. If nothing new is added to the dataset then every thing works fine.

The main issue I found was that you only get the + symbol if the item has children. What I do it always load one more level than is actually displayed. So when click on the + I dont load the children I load the children's children.

To do the loading I sub classed LinkTree and override thew onJunctionLinkClicked(AjaxRequestTarget target, TreeNode node) method.

Still working on the display update when a new item is added to the part of the tree that is already displayed.
 
Ian

----- Original Message ----
From: pixotec <[hidden email]>
To: [hidden email]
Sent: Friday, 21 September, 2007 11:55:46 AM
Subject: LinkTree lazy loading possible?


I want to use LinkTree to represent a very very large hierarchy (the loading
of the whole thing is expensive...).
Is there an AJAX way of loading the children of a node just when clicking on
the "plus-icon" for expanding?

--
View this message in context: http://www.nabble.com/LinkTree-lazy-loading-possible--tf4493231.html#a12814684
Sent from the Wicket - User mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]








      ___________________________________________________________
Want ideas for reducing your carbon footprint? Visit Yahoo! For Good  http://uk.promotions.yahoo.com/forgood/environment.html
Reply | Threaded
Open this post in threaded view
|

Re: LinkTree lazy loading possible?

Kent Tong
In reply to this post by pixotec-2
pixotec wrote
I want to use LinkTree to represent a very very large hierarchy (the loading of the whole thing is expensive...).
Is there an AJAX way of loading the children of a node just when clicking on the "plus-icon" for expanding?
You may try my code below which seems to work, even though it's not using ajax:

<pre>
public class TreePage extends WebPage {
        private DefaultTreeModel treeModel;
        private TreeChildrenProvider provider;

        private class MyTreeNode extends DefaultMutableTreeNode {
                public MyTreeNode(String nodeName) {
                        super(nodeName);
                }
                public String getName() {
                        return (String) getUserObject();
                }
                public boolean isLeaf() {
                        return provider.getChildren(getName()).isEmpty();
                }
        }

        public TreePage() {
                provider = makeMockProvider();
                MyTreeNode a = new MyTreeNode("a");
                treeModel = new DefaultTreeModel(a);
                LinkTree tree = new LinkTree("tree", new PropertyModel(this,
                                "treeModel"));
                add(tree);
                ITreeState treeState = tree.getTreeState();
                treeState.collapseAll();
                treeState.addTreeStateListener(new ITreeStateListener() {
                        public void nodeUnselected(TreeNode node) {
                        }
                        public void nodeSelected(TreeNode node) {
                        }
                        public void nodeExpanded(TreeNode node) {
                                if (!node.isLeaf() && node.getChildCount() == 0) {
                                        MyTreeNode myTreeNode = ((MyTreeNode) node);
                                        for (String childName : provider.getChildren(myTreeNode
                                                        .getName())) {
                                                myTreeNode.add(new MyTreeNode(childName));
                                        }
                                }
                        }
                        public void nodeCollapsed(TreeNode node) {
                        }
                        public void allNodesExpanded() {
                        }
                        public void allNodesCollapsed() {
                        }
                });
        }
        private TreeChildrenProvider makeMockProvider() {
                return new TreeChildrenProvider() {
                        public List<String> getChildren(String nodeName) {
                                if (nodeName.equals("a")) {
                                        return Arrays.asList(new String[] { "b", "c" });
                                }
                                if (nodeName.equals("b")) {
                                        return Arrays.asList(new String[] { "d", "e" });
                                }
                                return Collections.EMPTY_LIST;
                        }
                };
        }
        public DefaultTreeModel getTreeModel() {
                return treeModel;
        }
}

public interface TreeChildrenProvider {
        List<String> getChildren(String nodeName);
}
</pre>
Reply | Threaded
Open this post in threaded view
|

Re: LinkTree lazy loading possible?

MikeyG
Hi
I've tried both solutions offered here do the same thing however to force the nodes to be redrawn you need to call treeNodesChanged() - which in turn adds the right components to the ajax target.
 
Unfortunately the api is a bit awkward and uses Enumerations. Here's my solution which seems to work:

    @Override
    protected void onJunctionLinkClicked(AjaxRequestTarget target, TreeNode node) {
       
        // keep current list of children to mark changes
        Set<TreeNode> nodeChanges = new HashSet<TreeNode>();
        for (TreeNode treeNode : CollectionUtils.makeIterable((Enumeration<TreeNode>)node.children())) {
            nodeChanges.add(treeNode);
        }

        // expand the next level of the model
        modelChanging();
        if (isNodeExpanded(node)) { // node has already been (un)expanded for this cycle
            m_dataProvider.expand((DefaultMutableTreeNode)node, 1);
        } else {
            // otherwise delete the children and replace with our marker node to save memory
            m_dataProvider.expand((DefaultMutableTreeNode)node, 0);
        }
       
        // compile list of added and removed nodes
        Enumeration<TreeNode> children = node.children();
        while (children.hasMoreElements()) {
            TreeNode treeNode = children.nextElement();
            if (nodeChanges.contains(treeNode)) {
                nodeChanges.remove(treeNode);
            } else {
                nodeChanges.add(treeNode);
            }
        }
        modelChanged();

        // need array of ints to match changed node list
        int nchanges = nodeChanges.size();
        int[] indices = new int[nchanges];
        for (int i = 0; i < nchanges; ++i) {
            indices[i] = i;
        }
       
        // trigger redraw of clicked node's changed children
        treeNodesChanged(new TreeModelEvent(this, new TreePath(node), indices, nodeChanges.toArray() ));
               
        super.onJunctionLinkClicked(target, node);
    }

(m_dataProvider.expand(node, depth) adds children or replaces them with a marker node as appropriate.)

Hope that helps :-)

MikeG

Reply | Threaded
Open this post in threaded view
|

Re: LinkTree lazy loading possible?

MikeyG

Actually I was over complicating it. The following work better:

    @Override
    protected void onJunctionLinkClicked(AjaxRequestTarget target, TreeNode node) {
       
        // expand the next level of the model
        modelChanging();
        if (isNodeExpanded(node)) { // node has already been (un)expanded for this cycle
            m_dataProvider.expand((DefaultMutableTreeNode)node, 1);
        } else {
            // otherwise delete the children and replace with our marker node
            m_dataProvider.expand((DefaultMutableTreeNode)node, 0);
        }
               
        // trigger redraw of clicked node
        treeNodesChanged(new TreeModelEvent(this, new TreePath(node.getParent()), new int[]{0}, new TreeNode[]{node} ));
       
        modelChanged();
       
        super.onJunctionLinkClicked(target, node);
    }