bindingzk

Binding data to listitem in Zk


I try to figure out forEach attribute in Zk framework. Here is the definition of the forEach:

This attribute is used in conjunction with collections. For each element in the collection, the element is rendered with the concrete value. Example:

{listitem label="${each}" forEach="${elements}" /}

I have a zul page that tries to populate listitem:

<?page title="new page title" contentType="text/html;charset=UTF-8"?>
<zk>
    <window title="new page title" border="normal"
        apply="org.zkoss.bind.BindComposer"
        viewModel="@id('sampleViewModel')@init('deneme.tahasozgen.ornek1.SampleViewModel')">
        New Content Here!

        <hlayout>
            count:
            <label value="@load(sampleViewModel.count)" />
        </hlayout>

        <button label="add" onClick="@command('cmd')" />

        <button label="getir eleman sayısı"
            onClick="@command('getirKurumSayisi')" />

        <listitem label="${each}" forEach="${elements}" />

    </window>
    
</zk>

how can I populate listitem? How are each and elements defined above? Thanks in advance.


Solution

  • It looks like you are trying to use the forEach attribute. While it's a possible choice, I'd recommend against it because it's an older (and less wieldy) iteration option in ZK.

    Your option are: ZUTI - forEach element (require ZK EE)

    This is the easiest an most straightforward iterative template option. Collection and template goes in, templated result goes out.

    <forEach items="@load(vm.model)" >
      <label value="@load(each)"/>
    </forEach>
    

    It's also custom-designed for MVVM since that's what your sample code is using. You can pass a collection as a member of your VM, and you can automatically notify it when the collection changes to redrawn that part of your UI dynamically.

    Now, if you don't have access to ZUTI, second best (and available in CE) is children binding.

    It's essentially the same idea, except it's tied to a parent instead of being a standalone shadow-element.

    <vlayout id="load" children="@load(vm.nodes)">
        <template name="children" var="node">
            <label value="@bind(node.name)" style="padding-left:10px"/>
        </template>
    </vlayout>
    

    Explanations on the forEach attribute below in case you REALLY want to use it:

    First, there is a longer documentation available here.

    The forEach attribute will repeat a component "for each" of the objects in the collection passed in the forEach argument. This sample uses a listitem, but it could be any ZK component. (FYI the only valid parent for a listitem is a listbox, so if you don't plan on having a listbox in this page, you should change that to a simpler container, like a div, etc.)

    Regarding the "how to populate" part, the value passed in the argument can be any resolvable variable available in your zul page. I see that you are using mvvm, so you already have a viewModel declared. You could use that viewModel, assuming it has a getMyBeanList() method:

    <div forEach=${sampleViewModel.myBeanList}/>
    

    Now for the part that makes it unwieldy, when you declare <component randomAttribute="${each}" forEach="${collection}"/> where collection == [a,b,c], what you are actually declaring is:

    <component randomAttribute="${a}"/> 
    <component randomAttribute="${b}"/> 
    <component randomAttribute="${c}"/> 
    

    Essentially you are creating N copies of the declared component, with the value ${each} beeing replaced by the relevant value in your iterated list.

    AGAIN! I strongly recommend you look into other iteration methods in ZK, since this one is really old, and really awkward to use.