Wednesday, October 6, 2010

Wicket: Lazy Loading TreeTable




I followed the steps mentioned below in order to enable lazy loading of child nodes in TreeTable in Wicket. I did not find a component in Wicket to do this directly. (I may be wrong, as I am new to Wicket)



It seems javax.swing.tree.DefaultTreeModel and javax.swing.tree.DefaultMutableTreeNode are generally used for creating the TreeTable.


The two important things to be done are overidding the isLeaf() method of DefaultMutableTreeNode and then call setAllowsChildren(true) for nodes that will contain children nodes when expanded. It is explained in detail below.



org.apache.wicket.extensions.markup.html.tree.table.TreeTable uses isLeaf() method of javax.swing.tree.DefaultMutableTreeNode to find if the node needs to be rendered as a folder or a leaf. isLeaf() method returns true only if the node has a child node. This behavior needs to be changed for lazy loading. The method needs to return true for a node that can potentially contain a child node and false otherwise. So, in the below code DefaultMutableTreeNode is extended and isLeaf() method is overridden.


public class MutableTreeNode extends DefaultMutableTreeNode {
    .
    .
    .
    public boolean isLeaf() {
        return !getAllowsChildren();
    }
}

Therefore, for any node that can potentially have a child, setAllowsChildren() method should be called


Now create the TreeTable as usual using MutableTreeNode (created earlier) instead of DefaultMutableTreeNode. Just make sure to call the setAllowsChildren(true) for nodes that will have child node loaded when expanded.

The following is some sample code for creating a TreeTable.

MutableTreeNode rootNode = new MutableTreeNode();

for (VariableGroup group : grps) {

    //Create initial nodes.
    child = new MutableTreeNode(group);
    //The following line will make sure that isLeaf() method will return true for all initial nodes.
    child.setAllowsChildren(true);
    rootNode.add(child);
}

//Create the treemodel
DefaultTreeModel model = new DefaultTreeModel(rootNode);
model.setAsksAllowsChildren(true);
//Now create the TreeTable.
varGrpTree = new TreeTable("treeVariableGroup"new CompoundPropertyModel(model), columns) {
      
        //Override the onJunctionLinkClicked callback method to retrieve the child records and add them as child
        protected void onJunctionLinkClicked(AjaxRequestTarget target, javax.swing.tree.TreeNode node){

            //Return if the Children are already added.
            if (node.getChildCount() != 0) {
                return;
            }

            MutableTreeNode treeNode = (MutableTreeNodenode;

            VariableGroup parentGrp = (VariableGrouptreeNode.getUserObject();

            //Retrieve the recorders from Database
            List childGrps = variableManager.fetchChildroup(parentGrp.getId());
            MutableTreeNode child = null;

            for (VariableGroup group : childGrps) {

                child = new MutableTreeNode(group);
                //Business rule says if group.getLft().equals(group.getRgt() - 1 is false then the record will have child record.
                child.setAllowsChildren(!group.getLft().equals(group.getRgt() 1));
                treeNode.add(child);
            }
            addChildGroups(treeNode);
            varGrpTree.getTreeState().expandNode(treeNode);               

        }

    };

Code was converted to HTML using Java2html

No comments: