0

Combobox in tree with renderer

asked 2009-03-19 18:08:04 +0800

edudant gravatar image edudant
219 1 1 1
zk.datalite.cz

Dear all,

when I use dynamic tree with model and renderer, there is problem with combobox inside treeitem. When comobox has many comboitems (roughly about 100), then when I open parent treenode, I get on client small window with (probably javascript) exception: "addAft". After I click "redraw", the data are displayed correctly.

Here is a simple example:

<?page id="kukatkoPage2" title="Test Tree item"?>

<zk xmlns="http://www.zkoss.org/2005/zul"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:h="http://www.w3.org/1999/xhtml">
    
    <window title="Test" height="100%" apply="TestController">
        <tree id="tree" width="100%" height="100%" >
            <treecols sizable="true">
                <treecol label="Name" />
                <treecol label="Description" />
            </treecols>
        </tree>
    </window>
</zk>

And the controller class (only relevant part is the with DLTreeItemRenderer inner class, there is the construction of combobox with 500 items)

import java.util.ArrayList;
import java.util.List;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.AbstractTreeModel;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Comboitem;
import org.zkoss.zul.Tree;
import org.zkoss.zul.Treecell;
import org.zkoss.zul.Treeitem;
import org.zkoss.zul.TreeitemRenderer;
import org.zkoss.zul.Treerow;




public class TestController extends GenericForwardComposer {

    Tree tree;

    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        comp.setVariable("ctl", this, true);

        String[] name2 = {"Paul","Eric","Gray"};
        String[] accountId2 = {"p002","e009","g019"};
        ArrayList alc2 = new ArrayList();
        for(int i =0; i < name2.length; i++){
            DataItem person = new DataItem(name2<i >,accountId2<i >);
            SimpleTreeNode stn = new SimpleTreeNode(person,new ArrayList());
            alc2.add(stn);
        }

        SimpleTreeNode salesDep = new SimpleTreeNode(new DataItem("Sales",""),alc2);
        ArrayList al = new ArrayList();
        al.add(salesDep);
        SimpleTreeNode root = new SimpleTreeNode("ROOT",al);

        tree.setTreeitemRenderer(new DLTreeItemRenderer());
        tree.setModel(new DLTreeModel(root));
        
    }


    class DataItem{
        private String polozka;
        private String hodnota;
        public DataItem(String polozka, String hodnota) {
            this.polozka = polozka;
            this.hodnota = hodnota;
        }
        public String getHodnota() {return hodnota;}
        public void setHodnota(String hodnota) {this.hodnota = hodnota;}
        public String getPolozka() {return polozka;}
        public void setPolozka(String polozka) {this.polozka = polozka;}
    }

    class DLTreeItemRenderer implements TreeitemRenderer {
        public void render(Treeitem item, Object data) throws Exception {
            SimpleTreeNode t = (SimpleTreeNode) data;
            DataItem person = (DataItem) t.getData();
            Treecell tcName = new Treecell(person.getPolozka());
            Treecell tcEmail = new Treecell();
            Combobox l = new Combobox();
            for (int i = 0; i < 500; i++) {
                Comboitem ci = new Comboitem();
                ci.setValue(i);
                ci.setLabel("Label: " + i);
                ci.setParent(l);
            }
            l.setParent(tcEmail);

            Treerow tr = null;
            if (item.getTreerow() == null) {
                tr = new Treerow();
                tr.setParent(item);
            } else {
                tr = item.getTreerow();
                tr.getChildren().clear();
            }
            tcName.setParent(tr);
            tcEmail.setParent(tr);
            item.setOpen(false);
        }
    }

    class DLTreeModel extends AbstractTreeModel {
        public DLTreeModel(SimpleTreeNode root) {super(root);}
        public Object getChild(Object parent, int index) {
            SimpleTreeNode node = (SimpleTreeNode)parent;
            return node.getChildAt(index);
        }
        public int getChildCount(Object parent) {
            SimpleTreeNode node = (SimpleTreeNode)parent;
            return node.getChildCount();
        }
        public boolean isLeaf(Object node) {
            if(node instanceof SimpleTreeNode){
                SimpleTreeNode node_ = (SimpleTreeNode)node;
                return node_.isLeaf();
            }else{
                return true;
            }
        }
    }

    public class SimpleTreeNode {
        private Object _data;
        private List _children;

        public SimpleTreeNode(Object data, List children){
            _data = data;
            _children = children;
        }
        public Object getData(){return _data;}
        public List getChildren(){return _children;}
        public String toString(){return (_data == null)?"Data is null":_data.toString();}
        public boolean isLeaf(){return (_children.size() == 0);}
        public Object getChildAt(int childIndex){return _children.get(childIndex);}
        public int getChildCount(){return _children.size();}
    }
}

It looks like a ZK bug to me. Does anyone experience similar problems?

Best Regards,

Jiri Bubnik

delete flag offensive retag edit

5 Replies

Sort by ยป oldest newest

answered 2009-03-24 01:20:26 +0800

RyanWu gravatar image RyanWu
533 2
about.me/flyworld

can you reduce your code and repost it ?

link publish delete flag offensive edit

answered 2009-03-27 13:05:51 +0800

edudant gravatar image edudant
219 1 1 1
zk.datalite.cz

This is as reduced as possible :-)

<?xml version="1.0" encoding="UTF-8"?>
<zk xmlns="http://www.zkoss.org/2005/zul"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:h="http://www.w3.org/1999/xhtml">

    <zscript><![CDATA[
       // initialize the model
       List rList = new ArrayList();
       rList.add("Level 2 - A");
       rList.add("Level 2 - B");
       SimpleTreeNode r = new SimpleTreeNode("Root", rList);

       List rootList = new ArrayList();
       rootList.add(r);
       SimpleTreeNode root = new SimpleTreeNode("Root", rootList);

       SimpleTreeModel model = new SimpleTreeModel(root);

       // create renderer
       TreeitemRenderer renderer = new TreeitemRenderer() {
         public void render(Treeitem item, Object data) throws Exception {

            // combobox with many items - usually 100 is enaugh to reproduce this problem
            Combobox combo = new Combobox();
            for (int i = 0; i < 500; i++) {
                Comboitem ci = new Comboitem();
                ci.setLabel("Label: " + i);
                ci.setParent(combo);
            }

            // attach the combo as only item in tree row
            Treerow row = new Treerow();
            Treecell cell = new Treecell();
            combo.setParent(cell);
            cell.setParent(row);
            row.setParent(item);
         }        
       }
        
    ]]></zscript>
    <tree model="${model}" treeitemRenderer="${renderer}">
        <treecols sizable="true">
            <treecol label="Col" />
        </treecols>
    </tree>
</zk>

It loads correctly, but after you try to expand first row, it throws javascript error:
addAft
a is undefined

Regards,

JB

link publish delete flag offensive edit

answered 2009-03-31 07:44:32 +0800

RyanWu gravatar image RyanWu
533 2
about.me/flyworld

Hi JB,
After trying you code, i found that's a bug of ZK, and it only happens when the i is > 141 or more (maybe racing problem)
i post a bug here, you can follow it :)

imho, render 500 combo items is very slow(because it will add add add many times)
you can create it all in server side and invalidate() the tree.
it can also avoid the bug above.

/Ryan Wu

link publish delete flag offensive edit

answered 2009-03-31 10:20:45 +0800

edudant gravatar image edudant
219 1 1 1
zk.datalite.cz

Hi thanks for your response.

I don't understand what you mean by multiple adding. I thought that it will be transfered to the client in one shot...

Regards,

JB

link publish delete flag offensive edit

answered 2009-04-01 01:02:24 +0800

RyanWu gravatar image RyanWu
533 2
about.me/flyworld

yes, you got the answer !!
if you transfer the "tree" which contains lots of comboitem to client in one shot,
it's much faster than "render" it.

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2009-03-19 18:08:04 +0800

Seen: 997 times

Last updated: Apr 01 '09

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More