listboxzkdynamically-generatedlistitemzul

How to dynamically add listheaders and listcells in ZK


I am totally new in ZK. I need to create N listheaders and N listcells in my zul file. But I do not know how to do it from my java controller and I am not using MVVM.

The problem would be something like:

   @Wire
   private Window idWindow;

   private Listheader header;
   private Listcell item1;

  @Override
    public void onCreate(Event event) {

    header.setLabel("laaaa");// It would set just one header but I can have many (N headers) and same for items

   }
<zk>
  <window id="idWindow" title="nameWindow" apply="controller.java" border="normal" closable="true" sizable="true" maximizable="true" maximized="true" height="85%" width="150%" style="overflow:auto;">
    <!-- CONTINUES -->

   <listbox id="mainList" hflex="1" vflex="1">
      <listhead>
          <listheader id="header" label="A" />
          <listheader id="header1" label="B"  /> 
          <listheader id="header2" label="C"  />
          ....
          <listheader id="headerN" label="N" />             
      </listhead>
      <listitem>
          <listcell id="item1" label="A"/>
          <listcell id="item2" label="B"/>
          <listcell id="item3" label="C"/>
          ....
          <listcell id="itemN" label="D"/>
      </listitem>
     </listbox>

   <!-- CONTINUES -->
    </window>
</zk>

Solution

  • You can leave the listhead empty in the zul, wire it into your controller and create the listheaders there. The important step is to ask the listbox for its listhead, and append the listheaders to it. For the cells, give your listbox a renderer that creates them for each item if you use a model to give your list data.

    Your zul will be much shorter:

    <zk>
        <window ... >
            <listbox id="mainList" hflex="1" vflex="1">
                <listhead />
            </listbox>
        </window>
    </zk>
    

    Then in your controller, you create the header in doAfterCompose and attach the renderer:

    @Wire
    private Listbox mainList;
    
    @Override  // This method should be specified by a composer super class
    public void doAfterCompose(Component comp)throws Exception
    {
        super.doAfterCompose(comp);
    
        mainList.setModel(someModelWithYourData);
    
        // create listheaders (manually/in for-loop/based on data...)
        Listhead head = mainList.getListhead();
        head.appendChild(new Listheader("A"));
        ...
    
        // attach renderer
        mainList.setItemRenderer(new ListitemRenderer<Object>() // use proper data type instead of Object
        {
            @Override
            public void render(Listitem item, Object data, int index)
                throws Exception
            {
                item.appendChild(new Listcell("a"));
                ...
            }
        });
    }
    

    There is also an example on zk's developer sites: https://www.zkoss.org/wiki/ZK_Developer%27s_Reference/MVC/View/Renderer/Listbox_Renderer

    In case you cannot use a model, you could also append the listitems in the zul or in the controller, and then create the listcells:

    for (Component child : mainList.getChildren()) 
    {
        if (child instanceof Listitem) 
        {
            Listitem item = (Listitem) child;
            // do the same as in the renderer
        }
    }