Introduction
This article describe how to implement a ListitemRenderer to display the data of a specific class in listitem.
From official site:
ListitemRenderer:
When a listbox is assigned with a model, a default renderer is assigned too. The default renderer will assume that each item has only one column, and it converts the data into a string directly. If you want to display multiple columns or retrieve a particular field of the data, you have to implement ListitemRenderer to handle the rendering.
ListModel:
Listbox and Grid allow developers to separate the view and the model by implementing ListModel. Once the model is assigned (with Listbox.setModel(ListModel)), the display of the listbox is controlled by the model, and an optional renderer. The model is used to provide data, while the renderer is used to provide the custom look. By default, the data is shown as a single-column grid/listbox. If it is not what you want, please refer to the View section for writing a custom renderer
Pre-request
(must)
ZK Basic MVC Pattern with GenericForwardComposer
http://ben-bai.blogspot.tw/2012/10/zk-basic-mvc-pattern-with.html
(must)
ZK Build View in ZUL file or Java Code (the java code part)
http://ben-bai.blogspot.tw/2012/12/zk-build-view-in-zul-file-or-java-code.html
The Program
listbox_with_model_and_renderer.zul
In this file, simply declare 3 listboxes with different ID and apply the ListboxModelRendererComposer, the model and renderer will be assigned to listboxes in composer.
<zk>
<!-- Tested with ZK 6.0.2 -->
<div style="margin: 10px;"
apply="test.listbox.composer.ListboxModelRendererComposer">
<vbox>
<label value="listbox with string data in ListModel, do not need renderer" />
<div height="10px" />
<listbox id="lbOne" />
<div height="30px" />
<label value="listbox with Person in ListModel but no renderer, cannot display data well" />
<div height="10px" />
<listbox id="lbTwo" />
<div height="30px" />
<label value="listbox with Person in ListModel and ListitemRenderer, display person data without any problem" />
<div height="10px" />
<listbox id="lbThree" />
</vbox>
</div>
</zk>
ListboxModelRendererComposer.java
After components composed, assign the model/renderer to listboxes.
package test.listbox.composer;
import java.util.ArrayList;
import java.util.List;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import test.data.bean.Person;
import test.listbox.renderer.PersonListitemRenderer;
/**
* Tested with ZK 6.0.2
* @author benbai
*
*/
public class ListboxModelRendererComposer extends GenericForwardComposer {
Listbox lbOne;
Listbox lbTwo;
Listbox lbThree;
public void doAfterCompose (Component comp) throws Exception {
super.doAfterCompose(comp);
// set models and render to listbox after comopsed
lbOne.setModel(getSimpleStringModel());
lbTwo.setModel(getPersonModel());
lbThree.setModel(getPersonModel());
lbThree.setItemRenderer(new PersonListitemRenderer());
}
public ListModel getSimpleStringModel () {
List l = new ArrayList();
// simply add some Strings to a list
// than wrap the list by a ListModelList
l.add("data one");
l.add("data two");
l.add("data three");
return new ListModelList(l);
}
public ListModel getPersonModel () {
List l = new ArrayList();
// simply add some Persons to a list
// than wrap the list by a ListModelList
l.add(new Person("First Name One", "Last Name One", 21));
l.add(new Person("First Name Two", "Last Name Two", 22));
l.add(new Person("First Name Three", "Last Name Three", 23));
return new ListModelList(l);
}
}
Person.java
The class that contains some attributes of a person.
package test.data.bean;
public class Person {
private String _firstName = "";
private String _lastName = "";
private int _age = 1;
public Person(String firstName, String lastName, int age) {
_firstName = firstName;
_lastName = lastName;
_age = age;
}
public String getFirstName() {
return _firstName;
}
public String getLastName() {
return _lastName;
}
public String getFullName() {
return _firstName + " " + _lastName;
}
public int getAge () {
return _age;
}
}
PersonListitemRenderer.java
Implements ListitemRenderer, used to render a Person object while render Listitem, also build listheaders.
package test.listbox.renderer;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Listhead;
import org.zkoss.zul.Listheader;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.ListitemRenderer;
import test.data.bean.Person;
/**
* Tested with ZK 6.0.2
* @author benbai
*
*/
public class PersonListitemRenderer implements ListitemRenderer {
/**
* The method to implements of a renderer,
* will be called by listbox automatically while render items
*/
public void render (Listitem listitem, Object value, int index) {
Person p = (Person)value;
// keep value in listitem
listitem.setValue(value);
addListcell(listitem, p.getFirstName());
addListcell(listitem, p.getLastName());
addListcell(listitem, p.getAge() + "");
addListcell(listitem, p.getFullName());
// create list headers while render first item
if (index == 0) {
renderListheads(listitem.getListbox());
}
}
private void addListcell (Listitem listitem, String value) {
Listcell lc = new Listcell ();
Label lb = new Label(value);
lb.setParent(lc);
lc.setParent(listitem);
}
private void renderListheads (Listbox listbox) {
Listhead lh = new Listhead();
new Listheader("First Name").setParent(lh);
new Listheader("Last Name").setParent(lh);
new Listheader("Age").setParent(lh);
new Listheader("Full Name").setParent(lh);
lh.setParent(listbox);
}
}
The Result
Reference
http://books.zkoss.org/wiki/ZK_Component_Reference/Data/Listbox
http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/MVC/Model/List_Model
http://books.zkoss.org/wiki/ZK_Developer's_Reference/MVC/View/Renderer/Listbox_Renderer
Download
Files at github
listbox_with_model_and_renderer.zul
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/WebContent/listbox_with_model_and_renderer.zul
Person.java
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/src/test/data/bean/Person.java
ListboxModelRendererComposer.java
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/src/test/listbox/composer/ListboxModelRendererComposer.java
PersonListitemRenderer.java
https://github.com/benbai123/ZK_Practice/blob/master/Components/projects/Components_Practice/src/test/listbox/renderer/PersonListitemRenderer.java
Can you please post a example where we can use same itemrendered to create a cell but its a editable when user click on save button data edited should me saved? Something i will want to use binding in java code.
ReplyDeleteNo problem, it (renderer inline editing) was in my schedule
Deletedone, http://ben-bai.blogspot.tw/2012/12/zk-listbox-inplace-editing-with.html
DeleteThanks Bai Ben. One more thing I have to ask is it possible to add reordering of column with cell while i am using binding in ZUL Page by @bind As example here(Wrote by me edited by Nabil) http://zkfiddle.org/sample/3gibjib/1-Another-new-ZK-fiddle but the position of the Listcell not changing according the listHeader Do you have something about it
ReplyDeleteI posted it to the related thread at stackoverflow: http://stackoverflow.com/questions/14040772/zk-reordering-with-listbox-without-drag-and-drop-event
DeleteSome how can we hide the the logic of if="${each == 1}" and foreach from developer by creating a new component of listbox?
ReplyDeleteI think one way is use item renderer, or you can try customize listhead/listitem with a setter that set a list of listheader/listcell to it and let them render their children by theme self.
DeleteBut these way might break the binding in MVVM.
Hmm Item rendered i dont want to use as it will break binding and lots of java code will be added. i dont want to break binding so we have to dig more to create a custom component like listbox where we can add this logic
ReplyDeleteIn short, I do not think this is a good idea.
DeleteWhy not just use the if approach (since, however, it is the general/native way and works fine, also reasonable enough)? I think it is not make sense to customize listbox for only avoid it.
That will just make the code in zul page looks pretty, but make your application more unstable with several unknown/unexpected issue.
I think you are right let me talk to my head about this, this approach already decrease plenty of line of code as previously i created component for reordering and sorting with getitemrendered ,those component also worked with approach only i have to check with database part only because i am saving user selection in database and if user saved some of this/her selection then we are reordering according to that value. I will share you my demo example in day or two .I tried to use fiddle but if i have 2-3 zul and java files then i dont understand how to manage this thing in fiddle i will share my code with you from sourceforgenet.
ReplyDeleteHi ben bai added a demo war http://zkframeworkhint.blogspot.in/2013/01/zk-listbox-with-column-reordering-in-zul.html
ReplyDeleteHi ben do you have any idea about this http://stackoverflow.com/questions/15083023/zk-modal-window-overlapping-issue
ReplyDeleteNope, seems it works fine at zkfiddle http://zkfiddle.org/sample/333sjqb/1-window-modal-test
DeleteWhat about this http://stackoverflow.com/questions/14961139/is-this-good-approach-to-use-innerclass-in-zk-and-jsf-for-component-variable-bin
ReplyDeleteHow can we show html content inside a label ?
ReplyDeleteadd it by java code:
Deletelabel.setValue("...");
you can also try to use readonly multiline textbox
So it will convert Html code also like if i have test sometthing like Some text after using it .It is showing text without bold and second thing i will want to show text without html tag How can we do these thing in ZK. Like JSF provide escape attribute.
DeleteDo you mean you do not want to output the html code in a label, you want to put some dom element in a label? Why do you want to do this? What is the whole scenario?
DeleteThe scenario is this I have to show data input by user in ckeditor I have to show in textbox or label something like if If I added any bold tag inside any text then when I have to show into a label or textbox it will show that selected text bold rather than showing html tag to user
DeleteI'm confused, the ckeditor can display html result itself, why do you need to use other component to display html result?
DeleteBen actually in my case if user adding a new record then i have to show use zk ckeditor but when user will come again into same page then i have to show all added record by user so when user entering any data i have show editor otherwise label with entered data
DeleteYou can override the client side setValue function of label,
Deletehttp://zkfiddle.org/sample/kcohpg/1-Label-display-dom-with-ckeditor
Hi Ben,
ReplyDeleteHow can we get all the components from a page like i am calling a method and method contain Component class object now from this object how can i got the all components..
@Command("saveCustomization")
public void saveCustomization(@ContextParam(ContextType.VIEW) Component view) {
//From this view object i will want to get all the component list in indivisual ZUl page
}
you can try page#getRoots then get children recursively
Deleteref:
http://www.zkoss.org/javadoc/latest/zk/org/zkoss/zk/ui/Page.html#getRoots()
Right but here is one issue i hav to again go for getChildren multiple time because it giving one component only like If Window contain Borderlayout and Borderlayout contain Vlayout,Center,Hlayout i have to again and again to do getChildren() is there any other method i can call to get all the component of the page
DeleteCurrently there's no such API, you need to retrieve children from root nodes (in a loop or with recursive function) manually, maybe you can make a util function for this task.
DeleteHi Ben i will want to replace + or - image with some other image in this grid demo http://www.zkoss.org/zksandbox/#g16 how can i do this?
ReplyDeleteYou can try to override the background style of
Delete.z-detail .z-detail-img
and
.z-detail.z-detail-expd .z-detail-img
Thanks its working,but its change one image i have to change both image expand as well as collapse .Can you please tell how can i know which css class used by any tag in ZK details about any Class Like Detail class used JS,Jquery,CSS i want to know everything used by a Class
DeleteI think you can use one image for .z-detail .z-detail-img and use another for .z-detail.z-detail-expd .z-detail-img,
Deletee.g.,
<style>
.z-detail .z-detail-img {
background-image: url('/TestProj/images/imgOne.png');
}
.z-detail.z-detail-expd .z-detail-img {
background-image: url('/TestProj/images/imgTwo.png');
background-position: 0px 0px;
}
</style>
I tried same but not worked but your code working can you refer how can i know about this css used in ZK?
DeleteWhat I do is right-click on the expand/collapse icon in Chrome then click 'Inspect element' to view the dom elements and its css style in Chrome console.
DeleteThanks for your help
DeleteAny Idea about this issue http://stackoverflow.com/questions/17398202/zk-ctrl-key-or-hot-key-creating-issue-with-diffrent-browsers
ReplyDeletei'm copy code you to train in eclipse ,but it have one error in file PersonListitemRenderer.java , why?
ReplyDeleteWhat error you are getting and which line?
DeleteThis comment has been removed by the author.
DeleteLine 18 : in file PersonListitemRenderer.java
Deleteerror : The type PersonListitemRenderer must implement the inherited abstract method ListitemRenderer.render(Listitem, Object)
i copy code and create packet same you run on eclipse
parameter in method render just don't have index, method render have 2 parameter is listitem and object. because i delete int index error is none but when run project have UiException .
Deletehelp me please T^T
thank
After 2 hour i emend code. I know version zk is 5.0.7 but code in page use 6
DeleteEND Error !! Thank ha ha ha.
Let us know what ZK Version you are using?
Delete5.0.7 now i upgrade to 6.5.3
Deleterender method is changed in ZK 6,
Deleterender(Listitem, Object) is for ZK5,
render(Listitem, Object, int) is for ZK6
you can implements both method to make your renderer compatible with both ZK5 and ZK6
oh ,thank alot
DeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteAny answer of this question http://forum.zkoss.org/question/90502/how-to-save-window-component-state-in-db/
ReplyDeletejust replied
DeleteCan you help on this http://stackoverflow.com/questions/21309439/clear-date-from-datebox-through-jquery
DeleteSure, it's my pleasure.
DeleteHi, how about adding a listgroup through java code to any of the listbox?
ReplyDeleteI've been trying to do this, but I couldn't find a solution that works.
Thank you!
You need to use GroupsModel to store your data first, please refer to the sample at zkdemo http://www.zkoss.org/zkdemo/listbox/list_group
DeleteYour good knowledge and kindness in playing with all the pieces were very useful.
ReplyDeleteAre you planning to create an On Demand Car Services App? The App Ideas is leading web and Mobile App development. We provide the best IT Services at best rates. Contact us now!