Search code examples
listgridzk

show and modify List in grid ZK


I have a list that is dynamically generated from the view. when the button is clicked, a new row is added, the value is entered and saved.

.zul

<zk>
    <window border="normal" title="hello" viewModel="@id('vm') @init('gemalto.CreateServiceVersion')" apply="org.zkoss.bind.BindComposer">

        <grid id="demoGrid"
              model="@load(vm.profileList) @template((each.editingStatus) ? 'editable' : 'noneditable')">
            <columns sizable="true">
                <column width="160px" >Value</column>
                <column width="160px" ></column>
            </columns>
            <rows>
                <template name="editable">
                    <row>
                        <textbox id="valueTextBox"
                                 value="@load(each.serviceProfile.valueVariable) @save(each.serviceProfile.valueVariable, before='confirm')" />
                        <button
                            image="/img/save.png" label="save"
                            onClick="@command('confirm', currentVariable=each)"/>
                    </row>
                </template> 
                <template name="noneditable">
                    <row>
                        <label value="@load(each.serviceProfile.valueVariable)" />
                    </row>
                </template>
            </rows>


        </grid> 

        <div align="center">
            <button label="Add" image="/img/create.png" onClick="@command('onAddNew')" />
        </div>

    </window>
</zk>

view model

public class CreateServiceVersion extends SelectorComposer<Component> {

    private boolean isEditing = false;
    private boolean displayEdit = true;
    private boolean isAddNew = false;
    private List<ServiceProfileStatus> profileList = new ArrayList<ServiceProfileStatus>();

    public List<ServiceProfileStatus> getProfileList() {
        return profileList;
    }

    @AfterCompose
    public void afterCompose() {
        profileList.add(new ServiceProfileStatus(new ServiceProfile("value1"), false));
        profileList.add(new ServiceProfileStatus(new ServiceProfile("value2"), false));
    }

    @Command
    public void CrudServiceVersion() {
        Executions.sendRedirect("CrudServiceVersion.zul");
    }

    @Command
    @NotifyChange({"profileList"})
    public void onAddNew() {
        if (!isEditing) {
            ServiceProfileStatus sps = new ServiceProfileStatus(new ServiceProfile(""), displayEdit);
            profileList.add(0, sps);
            isAddNew = true;
            isEditing = true;
        }
    }

    @Command
    public void confirm(@BindingParam("currentVariable") ServiceProfileStatus sps) {
        isEditing = false;
        isAddNew = false;
        sps.setEditingStatus(isEditing);
        BindUtils.postNotifyChange(null,null,sps,"*");
    }
}

the problem is that I add a new item, the value is copied to all others items.

I put the images to see more clearly what is happening.

  1. imgur.com/7u7OkPG
  2. imgur.com/mf8PUYI
  3. imgur.com/aJpNoXM

Solution

  • I tested with your code and it works normally with me.
    Now I changed the code a little bit :

    • Removed the extends SelectorComposer from your viewmodel cause that is not needed for MVVM.
    • Changed your 2 templates to 1 template.
    • Usage of your boolean in your viewmodel in the zul.

    Zul :

    <?xml version="1.0" encoding="UTF-8"?>
    <zk>
        <window border="normal" title="hello" viewModel="@id('vm') @init('be.chillworld.CreateServiceVersion')" apply="org.zkoss.bind.BindComposer">
            <grid id="demoGrid" model="@load(vm.profileList)">
                <columns sizable="true">
                    <column width="160px" >Value</column>
                    <column width="160px" ></column>
                </columns>
                <rows>
                    <template name="model">
                        <row>
                            <textbox value="@load(each.serviceProfile.valueVariable) @save(each.serviceProfile.valueVariable, before='confirm')" />
                            <button disabled="@load(not each.editingStatus)" visible="@load(each.editingStatus)" image="/img/save.png" label="save"
                                onClick="@command('confirm', currentVariable=each)"/>
                        </row>
                    </template>
                </rows>
            </grid> 
            <div align="center">
                <button disabled="@load(vm.mayCreateNew)" label="Add" image="/img/create.png" onClick="@command('onAddNew')" />
            </div>
    
        </window>
    </zk>
    

    Viewmodel :

    package be.chillworld;
    
    import java.util.ArrayList;
    import java.util.List;
    import org.zkoss.bind.BindUtils;
    import org.zkoss.bind.annotation.AfterCompose;
    import org.zkoss.bind.annotation.BindingParam;
    import org.zkoss.bind.annotation.Command;
    import org.zkoss.bind.annotation.NotifyChange;
    import org.zkoss.zk.ui.Executions;
    
    /**
     *
     * @author chillworld     */
    public class CreateServiceVersion {
    
        private boolean isEditing = false;
        private List<ServiceProfileStatus> profileList = new ArrayList<ServiceProfileStatus>();
    
        public List<ServiceProfileStatus> getProfileList() {
            return profileList;
        }
    
        @AfterCompose
        public void afterCompose() {
            profileList.add(new ServiceProfileStatus(new ServiceProfile("value1"), false));
            profileList.add(new ServiceProfileStatus(new ServiceProfile("value2"), false));
        }
    
        @Command
        public void CrudServiceVersion() {
            Executions.sendRedirect("CrudServiceVersion.zul");
        }
    
        @Command
        @NotifyChange({"profileList","mayCreateNew"})
        public void onAddNew() {
            isEditing = true;
            ServiceProfileStatus sps = new ServiceProfileStatus(new ServiceProfile(""), true);
            profileList.add(0, sps);
        }
    
        @Command
        @NotifyChange("mayCreateNew")
        public void confirm(@BindingParam("currentVariable") ServiceProfileStatus sps) {
            isEditing = false;
            sps.setEditingStatus(isEditing);
            BindUtils.postNotifyChange(null, null, sps, "*");
        }
    
        public boolean getMayCreateNew() {
            return isEditing;
        }
    }
    

    ServiceProfileStatus.java :

    package be.chillworld;
    
    /**
     *
     * @author chillworld
     */
    public class ServiceProfileStatus {
    
        private ServiceProfile serviceProfile;
        private boolean editingStatus;
    
        public ServiceProfileStatus(ServiceProfile serviceProfile, boolean editingStatus) {
            this.serviceProfile = serviceProfile;
            this.editingStatus = editingStatus;
        }
    
        public boolean isEditingStatus() {
            return editingStatus;
        }
    
        public void setEditingStatus(boolean editingStatus) {
            this.editingStatus = editingStatus;
        }
    
        public ServiceProfile getServiceProfile() {
            return serviceProfile;
        }
    
        public void setServiceProfile(ServiceProfile serviceProfile) {
            this.serviceProfile = serviceProfile;
        }
    
        public ServiceProfileStatus(ServiceProfile serviceProfile) {
            this.serviceProfile = serviceProfile;
        }
    }
    

    ServiceProfile.java :

    package be.chillworld;
    
    /**
     *
     * @author chillworld
     */
    public class ServiceProfile {
    
        private String valueVariable;
    
        public ServiceProfile(String valueVariable) {
            this.valueVariable = valueVariable;
        }
    
        public String getValueVariable() {
            return valueVariable;
        }
    
        public void setValueVariable(String valueVariable) {
            this.valueVariable = valueVariable;
        }
    }