-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi all,
I am creating a grid given a list as its model.
I want to put a button in each row of the grid while using data-binding and save-when, ... features.
The important thing is that the actions of the button should affect only the components on its own row, not the other rows.
For example, consider the following zul file:
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?> <?page title="Books"?> <zk xmlns="http://www.zkoss.org/2005/zul" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd " > <include src="/commons/header.zul"/> <zscript><![CDATA[ class Book { private int id; private String title; public int getId() { return id; } public void setId(int i) { id = i; } public String getTitle() { return title; } public void setTitle(String t) { title = t; } } Book b1 = new Book(); b1.setId(1); b1.setTitle("b1"); Book b2 = new Book(); b2.setId(2); b2.setTitle("b2"); List bookList = new ArrayList(); bookList.add(b1); bookList.add(b2); ]]></zscript> <window width="100%" height="100%" > <grid model="@{bookList}" > <columns> <column label="id" /> <column label="TitleEdit" /> <column label="Titleview" /> <column /> </columns> <rows > <row self="@{each=book}" > <label value="@{book.id}" /> <textbox value="@{book.title, save-when='btnSave.onClick', load-after='btnSave.onClick' }" /> <label value="@{book.title, load-after='btnSave.onClick'}"/> <button id="btnSave" label="Save changes" /> </row> </rows> </grid> </window> </zk>
Consider the following scenario:
1- Edit the textbox in the first row.
2- Edit the textbox in the second row.
3- Click the button in the second row.
What I want is that the new value of ONLY the "textbox" in row#2, be saved in "b2.title" and be loaded to the "label" in row#2.
But, by following the above scenario, you will see that the value of the textbox in row#1 is also saved in the "b1.title", and is seen in the label in row#1.
It seams that the buttons created in the 4th column are not distinct buttons, and they are considered as a single button.
I think the problem is that the "id" of the buttons is the same in multiple rows and we cannot define different values for the "save-when" attributes of the textboxes.
Is there a simple way to solve this problem without doing a big surgery to the code?
Well, I have no idea how data-binding can be done through java codes.
Could you please provide an equivalent java code which works correctly?
Though, naturally, I would be much more happy if no java code was needed for that.
Thanks a lot.
Hi
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?> <?page title="Books"?> <zk xmlns="http://www.zkoss.org/2005/zul" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd " > <window width="100%" height="100%" > <grid id="grid" > <columns> <column label="id" /> <column label="TitleEdit" /> <column label="Titleview" /> <column /> </columns> </grid> <zscript><![CDATA[ class Book { private int id; private String title; public int getId() { return id; } public void setId(int i) { id = i; } public String getTitle() { return title; } public void setTitle(String t) { title = t; } } class MyRowRenderer implements RowRenderer { public void render(Row row, Object data) { Book b = (Book)data; row.appendChild(new Label("" + b.getId())); final Textbox tb = new Textbox(b.getTitle()); row.appendChild(tb); final Label title = new Label(b.getTitle()); row.appendChild(title); Button btn = new Button("Save changes"); btn.addEventListener(Events.ON_CLICK, new org.zkoss.zk.ui.event.EventListener(){ public void onEvent(Event event) { String str_Title = tb.getText(); title.setValue(str_Title); } }); row.appendChild(btn); } } Book b1 = new Book(); b1.setId(1); b1.setTitle("b1"); Book b2 = new Book(); b2.setId(2); b2.setTitle("b2"); List bookList = new ArrayList(); bookList.add(b1); bookList.add(b2); SimpleListModel model = new SimpleListModel(bookList); grid.setModel(model); MyRowRenderer renderer = new MyRowRenderer(); grid.setRowRenderer(renderer); ]]></zscript> </window> </zk>
Thanks a lot for your code.
But, there is no data-binding here anymore.
For example, the value of the Label is updated automatically in data-binding, but here, you have to take care of everything.
I was wondering if there exists an equivalent java code for "data-binding".
Thanks again.
Hi @mirjalali
below are the partial (but running) codes from a LoC (Line of Codes) demonstration that should show zul vs. java.
These are the codes for a Richlet and shows the integration of the automatically DataBinder in java
as aquivalent to the same in zul:
I hope i don't forget a class.
best
Stephan
myPersonRichlet.java
import org.zkoss.zk.ui.GenericRichlet; import org.zkoss.zk.ui.Page; /** * Richlet sample that shows the automatically Databinder working in java code * with the org.zkoss.zkplus.databind.DataBinder class.<br> * <br> * needed classes:<br> * Person.java<br> * PersonDAO.java<br> * PersonDAOImpl.java<br> * PersonList.java<br> * PersonListItemRenderer.java<br> * PersonSearchDialog.java <br> * <br> * From the zl 3.6.3 documentation; page: 234 .<br> * One Richlet per URL Like servlets, a richlet is created and shared for the * same URL. In other words, the richlet (at least the service method) must be * thread-safe. On the other hands, components are not shareable. Each desktop * has an independent set of components. Therefore, it is generally not a good * idea to store components as a data member of a richlet. <br> * <hr> * * * @author sgerth sge(at)forsthaus(dot)de */ public class MyPersonRichlet extends GenericRichlet { @Override public void service(Page page) { new MyPersonRichletImpl(page); // create and forget } }
.
myPersonRichletImpl.java
import org.zkoss.util.resource.Labels; import org.zkoss.zk.ui.Page; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zkex.zul.Columnchildren; import org.zkoss.zkex.zul.Columnlayout; import org.zkoss.zkplus.databind.BindingListModelList; import org.zkoss.zkplus.databind.DataBinder; import org.zkoss.zul.Button; import org.zkoss.zul.Caption; import org.zkoss.zul.Column; import org.zkoss.zul.Columns; import org.zkoss.zul.Div; import org.zkoss.zul.Grid; import org.zkoss.zul.Groupbox; import org.zkoss.zul.Label; import org.zkoss.zul.Listbox; import org.zkoss.zul.Listitem; import org.zkoss.zul.Panel; import org.zkoss.zul.Panelchildren; import org.zkoss.zul.Row; import org.zkoss.zul.Rows; import org.zkoss.zul.Separator; import org.zkoss.zul.Textbox; import org.zkoss.zul.Toolbar; import org.zkoss.zul.Vbox; import org.zkoss.zul.Window; import com.zksample.backend.dao.impl.PersonDAOImpl; import com.zksample.backend.model.Person; /** * PersonRichlet implementation. * * @author sgerth sge(at)forsthaus(dot)de * */ public class MyPersonRichletImpl { private MyPersonRichletImpl myPersonRichletImpl; // Window as NameSpace private Window _main; // DataBinder private DataBinder binder; // Listbox that shows the Person Bean data private Listbox listBoxPerson; // Textbox for bean property: Person.lastName private Textbox txtb_LastName; // Textbox for bean property: Person.lastName private Textbox txtb_FirstName; // Textbox for bean property: Person.firstName private Textbox txtb_StreetName; // Textbox for bean property: Person.city private Textbox txtb_City; // Textbox for bean property: Person.phone private Textbox txtb_Phone; // Textbox for bean property: Person.fax private Textbox txtb_Fax; // Bean to bind private Person person; /** * Constructor * * @param page */ public MyPersonRichletImpl(Page page) { myPersonRichletImpl = this; _main = new Window(); _main.setPage(page); set_main(_main); page.setTitle("myRichlet Page"); binder = new DataBinder(); page.setAttribute("binder", binder); Vbox vbox = new Vbox(); vbox.setWidth("100%"); vbox.setHeight("100%"); _main.appendChild(vbox); vbox.appendChild(createPersonListbox()); vbox.appendChild(createToolbarAndButtons()); vbox.appendChild(createDetailFields()); initDataBinding(); } /** * Creates the Listbox for the Person data. * * @return Div with the person Listbox. */ private Div createPersonListbox() { Div div = new Div(); Window win = new PersonList(); win.setParent(div); listBoxPerson = (Listbox) win.getFellow("listBoxPerson"); setListBoxPerson(listBoxPerson); if (listBoxPerson != null) { listBoxPerson.addEventListener("onSelect", new EventListener() { @Override public void onEvent(Event event) throws Exception { Listitem item = listBoxPerson.getSelectedItem(); if (item != null) { // casting setPerson((Person) item.getAttribute("data")); System.out.println("onSelect(): " + (getPerson().getLastName())); } } }); } return div; } /** * Creates the Buttons. * * @return Div with the Buttons */ private Div createToolbarAndButtons() { Div div = new Div(); div.setWidth("100%"); div.setSclass("z-toolbar"); div.setStyle("padding:0"); Separator sep; // +++++++++++++++++++++++++++++++++++++ Toolbar tb = new Toolbar(); tb.setWidth("100%"); tb.setAlign("start"); tb.setStyle("float:left"); tb.setParent(div); Button btnHelp = new Button(); btnHelp.setId("btnHelp"); btnHelp.setLabel("Help"); btnHelp.setTooltiptext(Labels.getLabel("btnHelp.label")); btnHelp.setImage("/images/icons/light_16x16.gif"); btnHelp.addEventListener("onClick", new OnClickBtnHelpEventListener()); btnHelp.setParent(tb); Button btnSearch = new Button(); btnSearch.setId("btnSearch"); btnSearch.setLabel("Search"); btnSearch.setTooltiptext("I create a searchDialog Window with inside code."); btnSearch.setImage("/images/icons/btn_search2_16x16.gif"); btnSearch.addEventListener("onClick", new OnClickBtnSearchEventListener()); btnSearch.setParent(tb); sep = new Separator(); sep.setOrient("vertical"); sep.setSpacing("20"); sep.setBar(true); sep.setParent(tb); // +++++++++++++++++++++++++++++++++++++ Button btnNew = new Button(); btnNew.setId("btnNew"); btnNew.setLabel("Search 2"); btnNew.setTooltiptext("I create a searchDialog Window from external code."); btnNew.setImage("/images/icons/btn_new2_16x16.gif"); btnNew.addEventListener("onClick", new EventListener() { @Override public void onEvent(Event event) throws Exception { PersonSearchDialog psd = new PersonSearchDialog(myPersonRichletImpl); } }); btnNew.setParent(tb); sep = new Separator(); sep.setOrient("vertical"); sep.setSpacing("20"); sep.setBar(true); sep.setParent(tb); // ++++++++++++++++++++++++++++++++ Button btnSave = new Button(); btnSave.setId("btnSave"); btnSave.setLabel("Save"); btnSave.setTooltiptext("I'm the save button"); btnSave.setImage("/images/icons/btn_save2_16x16.gif"); btnSave.setParent(tb); Button btnEdit = new Button(); btnEdit.setId("btnEdit"); btnEdit.setLabel("Edit"); btnEdit.setTooltiptext("I'm the edit button"); btnEdit.setImage("/images/icons/btn_edit2_16x16.gif"); btnEdit.setParent(tb); Button btnDelete = new Button(); btnDelete.setId("btnDelete"); btnDelete.setLabel("Delete"); btnDelete.setTooltiptext("I'm the delete button"); btnDelete.setImage("/images/icons/btn_delete2_16x16.gif"); btnDelete.setParent(tb); Button btnCancel = new Button(); btnCancel.setId("btnCancel"); btnCancel.setLabel("Cancel"); btnCancel.setTooltiptext("I'm the cancel button"); btnCancel.setImage("/images/icons/btn_cancel2_16x16.gif"); btnCancel.setParent(tb); return div; } /** * Creates the detail fields for showing the person bean data. * * @return Div with the detail fields. */ private Div createDetailFields() { Div div = new Div(); div.setWidth("100%"); div.setHeight("100%"); Row row; Rows rows; Label label; Grid grid; Columns columns; Column column; // ++++++++++++ Containers ++++++++++++++++ Columnlayout colLayout = new Columnlayout(); colLayout.setParent(div); Columnchildren colChildren1 = new Columnchildren(); colChildren1.setWidth("50%"); colChildren1.setParent(colLayout); Columnchildren colChildren2 = new Columnchildren(); colChildren2.setWidth("50%"); colChildren2.setParent(colLayout); // +++++++++++++++ left GroupBox + Container Panel panelName = new Panel(); panelName.setParent(colChildren1); Panelchildren panelchildrenName = new Panelchildren(); panelchildrenName.setParent(panelName); Groupbox gbName = new Groupbox(); gbName.setMold("3d"); gbName.setParent(panelchildrenName); Caption captionGBName = new Caption(); captionGBName.setLabel("Name and Address"); captionGBName.setImage("/images/icons/view.gif"); captionGBName.setParent(gbName); grid = new Grid(); grid.setParent(gbName); columns = new Columns(); columns.setParent(grid); column = new Column(); column.setWidth("40%"); column.setParent(columns); rows = new Rows(); rows.setParent(grid); row = new Row(); row.setParent(rows); label = new Label("Last Name"); label.setId("lbl_LastName"); label.setParent(row); txtb_LastName = new Textbox(); txtb_LastName.setId("txtb_LastName"); txtb_LastName.setWidth("98%"); txtb_LastName.setParent(row); row = new Row(); row.setParent(rows); label = new Label("First Name"); label.setId("lbl_FirstName"); label.setParent(row); txtb_FirstName = new Textbox(); txtb_FirstName.setId("txtb_FirstName"); txtb_FirstName.setWidth("98%"); txtb_FirstName.setParent(row); row = new Row(); row.setParent(rows); label = new Label("Street"); label.setId("lbl_Street"); label.setParent(row); txtb_StreetName = new Textbox(); txtb_StreetName.setId("txtb_StreetName"); txtb_StreetName.setWidth("98%"); txtb_StreetName.setParent(row); row = new Row(); row.setParent(rows); label = new Label("City"); label.setId("lbl_City"); label.setParent(row); txtb_City = new Textbox(); txtb_City.setId("txtb_City"); txtb_City.setWidth("98%"); txtb_City.setParent(row); // +++++++++++++++ right GroupBox + Container Panel panelPhone = new Panel(); panelPhone.setParent(colChildren2); Panelchildren panelchildrenPhone = new Panelchildren(); panelchildrenPhone.setParent(panelPhone); Groupbox gbPhone = new Groupbox(); gbPhone.setMold("3d"); gbPhone.setParent(panelchildrenPhone); Caption captionGBPhone = new Caption(); captionGBPhone.setLabel("Phone and Fax"); captionGBPhone.setImage("/images/icons/telephone_16x16.png"); captionGBPhone.setParent(gbPhone); grid = new Grid(); grid.setParent(gbPhone); columns = new Columns(); columns.setParent(grid); column = new Column(); column.setWidth("40%"); column.setParent(columns); rows = new Rows(); rows.setParent(grid); row = new Row(); row.setParent(rows); label = new Label("Phone"); label.setId("lbl_Phone"); label.setParent(row); txtb_Phone = new Textbox(); txtb_Phone.setId("txtb_Phone"); txtb_Phone.setWidth("98%"); txtb_Phone.setParent(row); row = new Row(); row.setParent(rows); label = new Label("Fax"); label.setId("lbl_Fax"); label.setParent(row); txtb_Fax = new Textbox(); txtb_Fax.setId("txtb_Fax"); txtb_Fax.setWidth("98%"); txtb_Fax.setParent(row); return div; } /** * Initiates the databinding. <br> * 1. Bind a variable name to the bean.<br> * 2. Attach the component.ID to a bean.property.<br> * 3. Attach the listBox selectedItem to the bean.<br> */ private void initDataBinding() { // init the bean with the first record in the personList setPerson(new PersonDAOImpl().getFirstPersonInList()); // add bindings binder.bindBean("person", person); binder.addBinding(listBoxPerson, "selectedItem", "person"); binder.addBinding(txtb_LastName, "value", "person.lastName"); binder.addBinding(txtb_FirstName, "value", "person.firstName"); binder.addBinding(txtb_StreetName, "value", "person.street"); binder.addBinding(txtb_City, "value", "person.city"); binder.addBinding(txtb_Phone, "value", "person.phone"); binder.addBinding(txtb_Fax, "value", "person.fax"); binder.loadAll(); } /** * */ public final class OnClickBtnHelpEventListener implements EventListener { @Override public void onEvent(Event event) throws Exception { Window win = new Window(); win.setTitle("I'm a help window in modal mode"); win.setWidth("300px"); win.setHeight("250px"); win.setClosable(true); win.setParent(_main); Label lbl = new Label("This is a help text. I hope it can be useful for you."); lbl.setParent(win); win.doModal(); } } public final class OnClickBtnSearchEventListener implements EventListener { @Override public void onEvent(Event event) throws Exception { Window win = new Window(); win.setId("searchWindow"); win.setTitle("Search for Customers"); win.setHeight("100px"); win.setWidth("300px"); win.setClosable(true); win.setParent(_main); Grid grid = new Grid(); grid.setParent(win); Columns columns = new Columns(); columns.setParent(grid); Column column = new Column(); column.setWidth("40%"); column.setParent(columns); column = new Column(); column.setWidth("60%"); column.setParent(columns); Rows rows = new Rows(); rows.setParent(grid); Row row = new Row(); row.setParent(rows); Label label = new Label("Last Name"); label.setId("lbl_SearchLastName"); label.setParent(row); Textbox txtb_Search = new Textbox(); txtb_Search.setId("txtb_SearchLastName"); txtb_Search.setWidth("98%"); txtb_Search.setParent(row); Separator sep = new Separator(); sep.setBar(true); sep.setParent(win); Button btnOK = new Button(); btnOK.setLabel("Search"); btnOK.addEventListener("onClick", new OnClickBtnOKEventListener()); btnOK.setParent(win); win.doModal(); } } /** * * @author sge * */ public final class OnClickBtnOKEventListener implements EventListener { @Override public void onEvent(Event event) throws Exception { System.out.println(event.getName()); Window win = (Window) event.getTarget().getFellow("searchWindow"); String lastName = ((Textbox) win.getFellow("txtb_SearchLastName")).getValue(); listBoxPerson.setModel(new BindingListModelList(new PersonDAOImpl().getPersonsByLastName(lastName), true)); win.onClose(); } } // ++++++++++++++++ Getter/Setter ++++++++++++++++ public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } public Listbox getListBoxPerson() { return listBoxPerson; } public void setListBoxPerson(Listbox listBoxPerson) { this.listBoxPerson = listBoxPerson; } public Window get_main() { return _main; } public void set_main(Window main) { _main = main; } }
.
PersonList.java
import org.zkoss.zkplus.databind.BindingListModelList; import org.zkoss.zul.Div; import org.zkoss.zul.Listbox; import org.zkoss.zul.Listhead; import org.zkoss.zul.Listheader; import org.zkoss.zul.Window; import com.zksample.backend.dao.PersonDAO; import com.zksample.backend.dao.impl.PersonDAOImpl; /** * Creates a listBox for the person data.<br> * * @author sgerth sge(at)forsthaus(dot)de * */ public class PersonList extends Window { private static final long serialVersionUID = 1L; private Listbox listBoxPerson; private Listheader lh_LastName; private Listheader lh_FirstName; private Listheader lh_City; private Listheader lh_Street; private Listheader lh_phone; private PersonDAO personDAO; public PersonList() { super(); this.appendChild(createPersonList()); } /** * Creates the listBox for the person data. * * @return Div with listBox */ public Div createPersonList() { Div div = new Div(); div.setId("divListBoxPerson"); listBoxPerson = new Listbox(); listBoxPerson.setId("listBoxPerson"); listBoxPerson.setWidth("100%"); listBoxPerson.setHeight("300px"); // listBoxPerson.setVflex("1"); listBoxPerson.setMultiple(false); listBoxPerson.setMold("paging"); listBoxPerson.setParent(div); Listhead listhead = new Listhead(); listhead.setSizable(true); listhead.setParent(listBoxPerson); lh_LastName = new Listheader(); lh_LastName.setLabel("last_name"); lh_LastName.setWidth("20%"); lh_LastName.setImage("/images/icons/create_doc.gif"); lh_LastName.setParent(listhead); lh_FirstName = new Listheader(); lh_FirstName.setLabel("first_name"); lh_FirstName.setWidth("20%"); lh_FirstName.setImage("/images/icons/create_doc.gif"); lh_FirstName.setParent(listhead); lh_City = new Listheader(); lh_City.setLabel("city"); lh_City.setWidth("20%"); lh_City.setImage("/images/icons/create_doc.gif"); lh_City.setParent(listhead); lh_Street = new Listheader(); lh_Street.setLabel("street"); lh_Street.setWidth("20%"); lh_Street.setImage("/images/icons/create_doc.gif"); lh_Street.setParent(listhead); lh_phone = new Listheader(); lh_phone.setLabel("phone"); lh_phone.setWidth("20%"); lh_phone.setImage("/images/icons/create_doc.gif"); lh_phone.setParent(listhead); listBoxPerson.setPageSize(15); // init with data listBoxPerson.setModel(new BindingListModelList(getPersonDAO().getAllPersons(), true)); listBoxPerson.setItemRenderer(new PersonListItemRenderer()); return div; } // +++++++++++++++++++++ getter / setter ++++++++++++ public void setPersonDAO(PersonDAO personDAO) { this.personDAO = personDAO; } public PersonDAO getPersonDAO() { if (personDAO == null) { personDAO = new PersonDAOImpl(); setPersonDAO(personDAO); } return personDAO; } }
.
PersonListItemRenderer.java
import org.zkoss.zul.Listcell; import org.zkoss.zul.Listitem; import org.zkoss.zul.ListitemRenderer; import com.zksample.backend.model.Person; /** * ListItemRenderer for the PersonListbox.<br> * * @author sgerth sge(at)forsthaus(dot)de * */ public class PersonListItemRenderer implements ListitemRenderer { @Override public void render(Listitem item, Object data) throws Exception { Person person = (Person) data; Listcell lc; lc = new Listcell(person.getLastName()); lc.setParent(item); lc = new Listcell(person.getFirstName()); lc.setParent(item); lc = new Listcell(person.getCity()); lc.setParent(item); lc = new Listcell(person.getStreet()); lc.setParent(item); lc = new Listcell(person.getPhone()); lc.setParent(item); item.setAttribute("data", data); } }
.
PersonSearchDialog.java
import org.zkoss.zk.ui.SuspendNotAllowedException; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zkplus.databind.BindingListModelList; import org.zkoss.zul.Button; import org.zkoss.zul.Column; import org.zkoss.zul.Columns; import org.zkoss.zul.Grid; import org.zkoss.zul.Label; import org.zkoss.zul.Listbox; import org.zkoss.zul.Row; import org.zkoss.zul.Rows; import org.zkoss.zul.Separator; import org.zkoss.zul.Textbox; import org.zkoss.zul.Window; import com.zksample.backend.dao.PersonDAO; import com.zksample.backend.dao.impl.PersonDAOImpl; /** * Search Dialog for the person bean.<br> * * @author sgerth sge(at)forsthaus(dot)de * */ public class PersonSearchDialog extends Window { private static final long serialVersionUID = 1L; private Window personSearchDialog; private Textbox txtb_Search; private PersonDAO personDAO; public PersonSearchDialog(final MyPersonRichletImpl myPersonRichletImpl) throws SuspendNotAllowedException, InterruptedException { System.out.println("PersonSearchDialog created"); personSearchDialog = this; this.setId("searchWindow"); this.setTitle("Search for Customers"); this.setHeight("100px"); this.setWidth("300px"); this.setClosable(true); this.setParent(myPersonRichletImpl.get_main()); Grid grid = new Grid(); grid.setParent(this); Columns columns = new Columns(); columns.setParent(grid); Column column = new Column(); column.setWidth("40%"); column.setParent(columns); column = new Column(); column.setWidth("60%"); column.setParent(columns); Rows rows = new Rows(); rows.setParent(grid); Row row = new Row(); row.setParent(rows); Label label = new Label("Last Name"); label.setId("lbl_SearchLastName"); label.setParent(row); txtb_Search = new Textbox(); txtb_Search.setId("txtb_SearchLastName"); txtb_Search.setWidth("98%"); txtb_Search.setParent(row); Separator sep = new Separator(); sep.setBar(true); sep.setParent(this); Button btnOK = new Button(); btnOK.setLabel("Search"); btnOK.addEventListener("onClick", new EventListener() { @Override public void onEvent(Event event) throws Exception { System.out.println("PersonSearchDialog " + event.getTarget() + " " + event.getName()); // process searching // Window w = (Window) myPersonRichletImpl.get_main(); Listbox listBoxPerson = myPersonRichletImpl.getListBoxPerson(); listBoxPerson.setModel(new BindingListModelList(getPersonDAO().getPersonsByLastName(txtb_Search.getValue()), true)); personSearchDialog.onClose(); } }); btnOK.setParent(this); this.doModal(); } // ++++++++++++++++ getter / setter ++++++++++++ public void setPersonDAO(PersonDAO personDAO) { this.personDAO = personDAO; } public PersonDAO getPersonDAO() { if (personDAO == null) { personDAO = new PersonDAOImpl(); setPersonDAO(personDAO); } return personDAO; } }
.
Person.java
import java.io.Serializable; /** * Person Bean.<br> * * @author sgerth sge(at)forsthaus(dot)de * */ public class Person implements Serializable { private static final long serialVersionUID = -4591732272301777879L; private int id = 0; private String firstName = ""; private String lastName = ""; private String city = ""; private String street = ""; private String phone = ""; private String fax = ""; public Person() { } public Person(int id, String firstName, String lastName, String city, String street, String phone, String fax) { this.setId(id); this.firstName = firstName; this.lastName = lastName; this.city = city; this.street = street; this.phone = phone; this.fax = fax; } public void setId(int id) { this.id = id; } public int getId() { return id; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getFirstName() { return firstName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getLastName() { return lastName; } public void setCity(String city) { this.city = city; } public String getCity() { return city; } public void setStreet(String street) { this.street = street; } public String getStreet() { return street; } public void setPhone(String phone) { this.phone = phone; } public String getPhone() { return phone; } public void setFax(String fax) { this.fax = fax; } public String getFax() { return fax; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((city == null) ? 0 : city.hashCode()); result = prime * result + ((fax == null) ? 0 : fax.hashCode()); result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + id; result = prime * result + ((lastName == null) ? 0 : lastName.hashCode()); result = prime * result + ((phone == null) ? 0 : phone.hashCode()); result = prime * result + ((street == null) ? 0 : street.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (city == null) { if (other.city != null) return false; } else if (!city.equals(other.city)) return false; if (fax == null) { if (other.fax != null) return false; } else if (!fax.equals(other.fax)) return false; if (firstName == null) { if (other.firstName != null) return false; } else if (!firstName.equals(other.firstName)) return false; if (id != other.id) return false; if (lastName == null) { if (other.lastName != null) return false; } else if (!lastName.equals(other.lastName)) return false; if (phone == null) { if (other.phone != null) return false; } else if (!phone.equals(other.phone)) return false; if (street == null) { if (other.street != null) return false; } else if (!street.equals(other.street)) return false; return true; } }
.
PersonDAO.java
import java.util.List; import com.zksample.backend.model.Person; /** * DAO methods for the person bean.<br> * * @author sgerth sge(at)forsthaus(dot)de * */ public interface PersonDAO { /** * EN: Gets back a list off all persons.<br> * DE: Gibt eine Liste aller Personen Objekte zurueck.<br> * * @return List of Persons / Liste von Personen */ public List<Person> getAllPersons(); /** * EN: Gets back a list off all persons by their LastName.<br> * DE: Gibt eine Liste aller Personen zurueck deren Nachname mit dem * Parameter uebereinstimmt.<br> * * @param lastName * LastName for searching * * @return List of Persons / Liste von Personen */ public List<Person> getPersonsByLastName(String lastName); /** * EN: Gets back the first persons in the list.<br> * DE: Gibt das erste Personen Objekt in der Liste zurueck.<br> * * @return Person obj / Person obj */ public Person getFirstPersonInList(); }
.
PersonDAOImpl.java
import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import com.zksample.backend.dao.PersonDAO; import com.zksample.backend.model.Person; /** * EN: DAO method implementation for the person bean.<br> * DE: DAO Methoden Implementierung fuer den person bean.<br> * * @author sgerth sge(at)forsthaus(dot)de * */ public class PersonDAOImpl implements PersonDAO { @Override public List<Person> getAllPersons() { List<Person> result = new ArrayList<Person>(); Person person; person = new Person(1, "Hans", "Möller", "Hamburg", "Hauptstrasse 23", "034568234", "3786487634"); result.add(person); person = new Person(2, "Werner", "Meier", "Freiburg", "Hauptstrasse 6", "74837468234", "45653786487634"); result.add(person); person = new Person(3, "Lutz", "Hafflinger", "Berlin", "An der Siegessäule 234", "2347468234", "6123786487634"); result.add(person); person = new Person(4, "Bill", "Gates", "New York", "50, street 1234", "2347468234", "111213786487634"); result.add(person); person = new Person(5, "Shawn", "Cassidy", "New Orleans", "23, baker street 343", "1247468234", "1323786487634"); result.add(person); person = new Person(6, "Hans", "Müller", "Hamburg", "Hauptstrasse 23", "034568234", "2223786487634"); result.add(person); person = new Person(7, "Uli", "Huber", "Mannheim", "In den Weihern 12", "034568234", "1113786487634"); result.add(person); person = new Person(8, "Stephan", "Schneider", "Olvenstedt", "Hasselbachplatz 44", "034568234", "1233786487634"); result.add(person); person = new Person(9, "Volker", "Schindler", "Frankfurt", "Am breiten Weg 21", "034568234", "2133786487634"); result.add(person); person = new Person(10, "Rüdiger", "Krombach", "München", "Werner-Siemens-Ring 45", "034568234", "1563786487634"); result.add(person); person = new Person(11, "Felix", "Haudrauf", "Bischoffingen", "Hauptstrasse 81", "034568234", "1873786487634"); result.add(person); person = new Person(12, "Björn", "Weissglut", "Stuttgart", "Ambrosiusstrasse 34", "034568234", "1673786487634"); result.add(person); person = new Person(13, "Klaus", "Ritter", "Ober Ursel", "Stoffelweg 66", "034568234", "4443786487634"); result.add(person); person = new Person(14, "Michael", "Urbräu", "Unter Ursel", "Neben den Gleisen 34", "034568234", "4553786487634"); result.add(person); person = new Person(15, "Helmut", "Riegeler", "Hügelheim", "Am Bach 12", "034568234", "663786487634"); result.add(person); person = new Person(16, "Xaver", "Ganther", "Stendal", "Hauptstrasse 45", "034568234", "773786487634"); result.add(person); person = new Person(17, "Hans", "Meier", "Hamburg", "Hauptstrasse 23", "034568234", "883786487634"); result.add(person); person = new Person(18, "Werner", "Meier", "Freiburg", "Hauptstrasse 6", "74837468234", "993786487634"); result.add(person); person = new Person(19, "Lutz", "Ritter", "Berlin", "An der Siegessäule 234", "2347468234", "7773786487634"); result.add(person); person = new Person(20, "Bill", "Gates", "New York", "50, street 1234", "2347468234", "443786487634"); result.add(person); person = new Person(21, "Shawn", "Cassidy", "New Orleans", "23, baker street 343", "1247468234", "5553786487634"); result.add(person); person = new Person(22, "Hans", "Meier", "Stendal", "Hauptstrasse 23", "034568234", "4323786487634"); result.add(person); person = new Person(23, "Uli", "Haudrauf", "Mannheim", "In den Weihern 12", "034568234", "1763786487634"); result.add(person); person = new Person(24, "Stephan", "Schneider", "Olvenstedt", "Hasselbachplatz 44", "034568234", "7243786487634"); result.add(person); person = new Person(25, "Volker", "Schindler", "Hügelheim", "Am breiten Weg 21", "034568234", "3763786487634"); result.add(person); person = new Person(26, "Rüdiger", "Krombach", "München", "Werner-Siemens-Ring 45", "034568234", "17233786487634"); result.add(person); person = new Person(27, "Felix", "Haudrauf", "Bischoffingen", "Hauptstrasse 81", "034568234", "3453786487634"); result.add(person); person = new Person(28, "Björn", "Cassidy", "Stuttgart", "Ambrosiusstrasse 34", "034568234", "5643786487634"); result.add(person); person = new Person(29, "Klaus", "Ritter", "Ober Ursel", "Stoffelweg 66", "034568234", "5673786487634"); result.add(person); person = new Person(30, "Michael", "Riegeler", "Mannheim", "Neben den Gleisen 34", "034568234", "8883786487634"); result.add(person); person = new Person(31, "Helmut", "Riegeler", "München", "Am Bach 12", "034568234", "9993786487634"); result.add(person); person = new Person(32, "Xaver", "Ganther", "Stendal", "Hauptstrasse 45", "034568234", "9873786487634"); result.add(person); person = new Person(33, "Hans", "Miller", "Hamburg", "Hauptstrasse 23", "034568234", "3453786487634"); result.add(person); person = new Person(34, "Werner", "Meier", "Freiburg", "Hauptstrasse 6", "74837468234", "2953786487634"); result.add(person); person = new Person(35, "Lutz", "Hafflinger", "Berlin", "An der Siegessäule 234", "2347468234", "5433786487634"); result.add(person); person = new Person(36, "Bill", "Gates", "New York", "50, street 1234", "2347468234", "9993786487634"); result.add(person); person = new Person(37, "Shawn", "Cassidy", "New Orleans", "23, baker street 343", "1247468234", "9123786487634"); result.add(person); person = new Person(38, "Hans", "Riegeler", "Hamburg", "Hauptstrasse 23", "034568234", "3873786487634"); result.add(person); person = new Person(39, "Uli", "Urbräu", "Mannheim", "In den Weihern 12", "034568234", "9153786487634"); result.add(person); person = new Person(40, "Stephan", "Ritter", "Olvenstedt", "Hasselbachplatz 44", "034568234", "1093786487634"); result.add(person); person = new Person(41, "Volker", "Haudrauf", "Frankfurt", "Am breiten Weg 21", "034568234", "1043786487634"); result.add(person); person = new Person(42, "Rüdiger", "Krombach", "Hügelheim", "Werner-Siemens-Ring 45", "034568234", "1023786487634"); result.add(person); person = new Person(43, "Felix", "Haudrauf", "Bischoffingen", "Hauptstrasse 81", "034568234", "1003786487634"); result.add(person); person = new Person(44, "Björn", "Weissglut", "Stuttgart", "Ambrosiusstrasse 34", "034568234", "1083786487634"); result.add(person); person = new Person(45, "Klaus", "Ritter", "Ober Ursel", "Stoffelweg 66", "034568234", "2346487634"); result.add(person); person = new Person(46, "Michael", "Urbräu", "Bischoffingen", "Neben den Gleisen 34", "034568234", "8763786487634"); result.add(person); person = new Person(47, "Helmut", "Riegeler", "Hamburg", "Am Bach 12", "034568234", "34653786487634"); result.add(person); return result; } @Override public List<Person> getPersonsByLastName(String lastName) { List<Person> allList = new ArrayList<Person>(); List<Person> result = new ArrayList<Person>(); allList = getAllPersons(); if (StringUtils.isEmpty(lastName) && StringUtils.isBlank(lastName)) { result = allList; return result; } int i = 0; for (Person person : allList) { if (((Person) allList.get(i)).getLastName().equalsIgnoreCase(lastName)) { result.add(person); } i = i + 1; } return result; } @Override public Person getFirstPersonInList() { Person person = null; List<Person> list = getAllPersons(); if (list.size() > 0) { person = (Person) list.get(0); } return person; } }
Hi,
many examples here... :-)
The the root-cause:
I think there is bug: the databinder seems to setup a wrong event-handling.
It seems, that the event is fired for the last row with cursor hold. Everything works fine, if you use only the button with the "cursor holding row".
So, i think you should post an bug.
One more example and work-a-round, by handling the event inside the controller/composer:
The zul-file: (i moved the databinderinit to the composer and removed all binder-events)
<?page title="Books"?> <zk xmlns="http://www.zkoss.org/2005/zul" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd " > <window id="win" width="100%" height="100%" apply="demo.BookController"> <grid model="@{win$composer.bookList}" > <columns> <column label="id" /> <column label="TitleEdit" /> <column label="Titleview" /> <column /> </columns> <rows > <row self="@{each=book}" > <label value="@{book.id}" /> <textbox value="@{book.title, save-when='none'}" /> <label value="@{book.title}"/> <button id="btnSave" label="Save changes" /> </row> </rows> </grid> </window> </zk>
The composer/controller:
package demo; import ... @SuppressWarnings("serial") public class BookController extends GenericForwardComposer { AnnotateDataBinder binder; ArrayList<Book> bookList; public void doAfterCompose(Component comp) throws Exception { super.doAfterCompose(comp); binder = new AnnotateDataBinder(comp); Book b1 = new Book(); b1.setId(1); b1.setTitle("b1"); Book b2 = new Book(); b2.setId(2); b2.setTitle("b2"); bookList = new ArrayList<Book>(); bookList.add(b1); bookList.add(b2); binder.loadAll(); } /* * Handle the Save-button, retrieve the row and execute * a binding-save */ public void onClick$btnSave(ForwardEvent event) { Component row = event.getOrigin().getTarget().getParent(); binder.saveComponent(row); } public List<Book> getBookList() { return bookList; } }
- I setup my own binder-instance inside the afterCompose and have to init the first load (binder.loadAll()).
- the composer handles the onClick-Event and perform the binding-save for the target-row
And it's of course a "matter of taste", but i prefer that the "controller manage the events".
/Robert
You can store the binder to any component (in my example: win) and retrieve the binder with getAttribute("binder")
Here is the zscript example:
+ root-option for the databinder
+ id for the window-component for storing the databinder
+ onSave method
+ onClick event-handling with zscript
- remove all binding-events
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" root="./win"?> <?page title="Books"?> <zk xmlns="http://www.zkoss.org/2005/zul" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd " > <zscript><![CDATA[ class Book { private int id; private String title; public int getId() { return id; } public void setId(int i) { id = i; } public String getTitle() { return title; } public void setTitle(String t) { title = t; } } Book b1 = new Book(); b1.setId(1); b1.setTitle("b1"); Book b2 = new Book(); b2.setId(2); b2.setTitle("b2"); List bookList = new ArrayList(); bookList.add(b1); bookList.add(b2); public void onSave(Component row) { AnnotateDataBinder binder = (AnnotateDataBinder) win.getAttribute("binder"); binder.saveComponent(row); } ]]></zscript> <window id="win" width="100%" height="100%" > <grid model="@{bookList}" > <columns> <column label="id" /> <column label="TitleEdit" /> <column label="Titleview" /> <column /> </columns> <rows > <row self="@{each=book}" > <label value="@{book.id}" /> <textbox value="@{book.title, save-when='none' }" /> <label value="@{book.title}"/> <button id="btnSave" label="Save changes" onClick="onSave(self.getParent())"/> </row> </rows> </grid> </window> </zk>
Note:
1.) zscript will be interpreted
2.) In my opinion, your example should work also - this is a bug (the event is always fired for the row with the last onChange, but should fired for the row with the button).
/Robert
Asked: 2010-04-30 04:08:10 +0800
Seen: 1,126 times
Last updated: May 05 '10