javazkzk-grid

zk - is it possible to add binding to each record in model?


<zk>
    <grid width="auto" sizedByContent="true" span="1" sclass="tblWithoutHover">
        <attribute name="onCreate">
            authorPublisherEtcInclude.insertBefore(self, authorBox);
        </attribute>
        <columns>
            <column/>
            <column/>
        </columns>
        <rows>
            <row valign="center">
                <cell colspan="2"><label use="${authorPublisherComponents.originalFieldsLabel}"/></cell>
            </row>
            <row valign="center">
                <label use="${authorPublisherComponents.titleAuthorOriginalLabel}"/>
                <textbox use="${authorPublisherComponents.titleAuthorOriginalTextbox}"/>
            </row>
            <row valign="center">
                <label use="${authorPublisherComponents.mainAuthorOriginalLabel}"/>
                <textbox use="${authorPublisherComponents.mainAuthorOriginalTextbox}"/>
            </row>
            <row valign="center">
                <label use="${authorPublisherComponents.mainAuthorResponsibilityLabel}"/>
                <selectbox use="${authorPublisherComponents.mainAuthorResponsibilitySelectbox}"/>
            </row>
            <row valign="center">
                <label use="${authorPublisherComponents.authorityDatesOriginalLabel}"/>
                <textbox use="${authorPublisherComponents.authorityDatesOriginalTextbox}"/>
            </row>
            <row valign="center">
                <cell>
                    <label use="${authorPublisherComponents.addMainAuthorsOriginalLabel}"/>
                    <toolbarbutton use="${authorPublisherComponents.addAuthorButton}"/>
                </cell>
                <cell id="addAuthorsCell">
                    <grid id="addAuthorsContainer" model="@bind(ivm.inventory.addAuthorsBeans)">
                        <columns>
                            <column/>
                            <column/>
                            <column/>
                        </columns>
                        <rows>
                                <row>
                                    <textbox value="@load(xgbfxb.authorName)" onChange="@command('test', component = self, index=s.index)"/>
                                    <button label="Del" onClick="@command('delAuthor', container=addAuthorsContainer, index=modelIndex )">
                                        <custom-attributes modelIndex="${s.index}"/>
                                    </button>
                                </row>
                        </rows>
                    </grid>
                    <textbox use="${authorPublisherComponents.addMainAuthorsOriginalTextbox}"/>
                </cell>
            </row>

Here is part of my zul page. addAuthorsBeans is list of classes with fields. When I change data in my combobox, application call set method for all classes in list, but I want it to call only for corresponding item. Is it possible? Or should I cast black magic with onChange events and ViewModel methods?

Edit (21/12/2013). It works like this: I have got three items 1, 2, 3. Then I activate setAuthor for 2 item. And then application call setAuthor method for 2 item, then for 3 item, then for 1 item and then looking for this method in container.

I have 'black magic' temporary solution to create static variable and change it on first call of setAuthor method and unblock it in container.

But it's not a final solution, because it's consume more resources and really not how should it really works.

Solution: if you've got grid with model in another grid it will behaive very strange. So just use listbox instead.


Solution

  • The combobox will only trigger item.setAuthorName(...) of the object witch represent item. If other setters are called you must have @NotifyChange or @DependsOn in your ViewModel class linked to this.

    edit: try changing:

    <grid model="@bind(ivm.inventory.addAuthorsBeans)">
    

    to

    <grid model="@load(ivm.inventory.addAuthorsBeans)">
    

    Update : a working example from me created for this topic : http://forum.zkoss.org/question/90188/notifychange-to-grid-that-is-inside-a-row-of-another-grid/?answer=90284#post-id-90284 ) :

    First simple pojo class :

    package be.chillworld;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     *
     * @author chillworld
     */
    public class Person {
        private int id;
        private String naam;
        private List<Person> childs = new ArrayList<Person>();
    
        public Person(int id) {
            this.id = id;
            naam = "test " + id;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public void setNaam(String naam) {
            this.naam = naam;
        }
    
        public String getNaam() {
            System.out.println("asked getter (naam) of "+ id);
            return naam;
        }
    
        public List<Person> getChilds() {
            System.out.println("asked getter (childs) of "+ id);
            return childs;
        }
    
        public void setChilds(List<Person> childs) {
            this.childs = childs;
        }
    
        public boolean addChild(Person person) {
            return childs.add(person);
        }
    
        @Override
        public String toString() {
            return "Person{" + "id=" + id + ", name=" + getNaam() + '}';
        }
    }
    

    then the IndexVM:

    package be.chillworld;
    
    import java.util.ArrayList;
    import java.util.List;
    import org.zkoss.bind.BindUtils;
    import org.zkoss.bind.annotation.BindingParam;
    import org.zkoss.bind.annotation.Command;
    
    /**
     *
     * @author chillworld
     */
    public class IndexVm {
    
        private List<Person> persons;
        int i;
    
        public IndexVm() {
            System.out.println("starting creating list");
            persons = new ArrayList<Person>();
            for (i = 0; i < 100; i++) {
                Person person = new Person(i);
                person.addChild(new Person(++i));
                persons.add(person);
            }
            System.out.println("ending creating list");
    
        }
    
        public List<Person> getPersons() {
            return persons;
        }
    
        public void setPersons(List<Person> persons) {
            this.persons = persons;
        }
    
        @Command
        public void showIndex(@BindingParam("person") Person person) {
            System.out.println("changed name");
            person.setNaam("Chillworld");
            BindUtils.postNotifyChange(null, null, person, "naam");
        }
    
        @Command
        public void addChild(@BindingParam("person") Person person) {
            System.out.println("add child");
            Person child = new Person(++i);
            child.setNaam("new child");
            person.addChild(child);
            BindUtils.postNotifyChange(null, null, person, "childs");
        }
    }
    

    and at last the index.zul :

    <?xml version="1.0" encoding="UTF-8"?>
    <zk xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.zkoss.org/2005/zul"
    xsi:schemaLocation="http://www.zkoss.org/2005/zul
                       http://www.zkoss.org/2005/zul/zul.xsd">
    <window border="normal" closable="false"
            apply="org.zkoss.bind.BindComposer"
            viewModel="@id('vm') @init('be.chillworld.IndexVm')">
        <grid width="1000px" model="@load(vm.persons)">        
            <columns>            
                <column label="naam" /> 
                <column label="add child" />            
                <column label="childs" />        
            </columns>        
            <template name="model" >            
                <row>                
                    <textbox value="@bind(each.naam)" /> 
                    <button onClick="@command('addChild',person = each)" label="add child"/>                       
                    <grid width="400px" model="@load(each.childs)">        
                        <columns>            
                            <column label="naam" />            
                            <column label="button" />        
                        </columns>        
                        <template name="model" var="item">            
                            <row>                
                                <textbox value="@bind(item.naam)" /> 
                                <button onClick="@command('showIndex',person = item)" label="change value"/>        
                            </row>        
                        </template>    
                    </grid>           
                </row>        
            </template>    
        </grid>
    </window>
    </zk>
    

    this gives as output (after startup) :

    changed name
    asked getter of 11
    changed name
    asked getter of 7
    changed name
    asked getter of 19
    

    Greetz chill.