Technologies Used
1. ZK 6.5 CE VersionReference
- http://www.zkoss.org/zkdemo/listbox/dual_listbox
- http://forum.zkoss.org/question/42954/listbox-refresh/
Project Name and Structure
Concepts used in this example
- We have used List box to display two column listing.
- We also used the "emptyMessage" attribute is used to show a message when listbox contains no items.
- In ZK, the controller is responsible for controlling ZK components and listening to events triggered by user interaction.
We can create a such controller class by simply extending org.zkoss.zk.SelectorComposer. - We also used Annotation in the composer using ZK Select Composer.
- MVC Developer reference
- We are using Listbox Template concept to display the data.
Step 1:
If you are new ZK, then you can setup the Development environment by downloading this document.Step 2:
Let us create the Project in eclipse. Click File -> New -> ZK Project . Let us name the project as MVCListBoxMoveUpDown.Step 3:
Now let us add the domain class Questions.java as follows. Note: We will create a package called "zkmvc" and then we will create our class "Questions" in that.package zkmvc;
public class Questions {
private Integer questionOrder;
private String questionName;
public Questions() {
}
public Questions(Integer questionOrder, String questionName) {
this.questionOrder = questionOrder;
this.questionName = questionName;
}
public Integer getQuestionOrder() {
return questionOrder;
}
public void setQuestionOrder(Integer questionOrder) {
this.questionOrder = questionOrder;
}
public String getQuestionName() {
return questionName;
}
public void setQuestionName(String questionName) {
this.questionName = questionName;
}
}
Step 4:
We then define a service class to perform the business logic (QuestionService.java) shown below:.package zkmvc;
import java.util.List;
public interface QuestionService {
/**
* Retrieve all questions in the catalog.
*
* @return all questions
*/
public List<Questions> findAll();
}
Step 5:
Next we create our implementation class for the above interface. For simplicity, it uses a static list object as the data model.package zkmvc;
import java.util.LinkedList;
import java.util.List;
import org.zkoss.zul.Messagebox;
public class QuestionsServiceImpl implements QuestionService {
// data model
private List<Questions> questionsList = new LinkedList<Questions>();
private static int id = 1;
// initialize book data
public QuestionsServiceImpl() {
questionsList.add(new Questions(1, "What was your childhood nickname?"));
questionsList.add(new Questions(2, "In what city did you meet your spouse/significant other?"));
questionsList.add(new Questions(3, "What is the middle name of your oldest child?"));
questionsList.add(new Questions(4, "What is the name of the place your wedding reception was held?"));
questionsList.add(new Questions(5, "What year did you graduate from High School?"));
questionsList.add(new Questions(6, "What was the make and model of your first car?"));
questionsList.add(new Questions(7, "What is the name of the company of your first job?"));
}
public List<Questions> findAll() {
return questionsList;
}
}
Step 6:
Now we will add our listing zul file as follows<window title="Questions List" border="normal"
apply="zkmvc.QuestionsListController">
<hlayout >
<listbox id="questionListbox" width="1000px"
emptyMessage="No Question found in the result">
<listhead>
<listheader label="Question Order" width="20%" />
<listheader label="Question" width="80%"/>
</listhead>
<template name="model">
<listitem>
<listcell label="${each.questionOrder}"></listcell>
<listcell label="${each.questionName}"></listcell>
</listitem>
</template>
</listbox>
<vbox >
<image style="cursor:pointer" id="upBtn"
src="${imgPath}/uparrow_g.png" />
<image style="cursor:pointer" id="downBtn"
src="${imgPath}/downarrow_g.png" />
</vbox>
</hlayout>
</window>
Step 7:
Next we will add our MVC Controller for the above zul file which will take of Move up and Move down.package zkmvc;
import java.util.List;
import java.util.Set;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.AbstractListModel;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Messagebox;
/**
* To simplify the implementation of the controller part of UI, ZK provides
* several skeleton implementations. For example, SelectorComposer, as one of
* the most popular skeletons, wires components, variables and event listeners
* automatically based on Java annotations you specify.
*/
public class QuestionsListController extends SelectorComposer<Component> {
private static final long serialVersionUID = 1L;
/**
* In SelectorComposer, when you specify a @Wire annotation on a field or
* setter method, the SelectorComposer will automatically find the component
* and assign it to the field or pass it into the setter method.
**/
@Wire
private Listbox questionListbox;
private ListModelList<Questions> questionList;
private QuestionService questionService = new QuestionsServiceImpl();
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
List<Questions> result = questionService.findAll();
questionList = new ListModelList<Questions>(result);
questionListbox.setModel(questionList);
}
@Listen("onClick = #downBtn")
public void down() {
int selectedOrder;
int nextOrder;
Set<Questions> selected = questionList.getSelection();
//If no item is selected, then do nothing
if (selected.isEmpty())
return;
//If selected item is in the last i.e index is eq to size of the list, then do nothing
int index = questionList.indexOf(selected.iterator().next());
if (index == questionList.size() - 1 || index < 0)
return;
//Store the currently selected item
Questions selectedItem = questionList.get(index);
//Take the next item
Questions nextItem = questionList.get(index + 1);
//Get the order for the currrently selected Item
selectedOrder = selectedItem.getQuestionOrder();
//Get the order for the next item of the selected item
nextOrder = nextItem.getQuestionOrder();
//Swap the order - In the real world, you can make a DB Call to do this
selectedItem.setQuestionOrder(nextOrder);
nextItem.setQuestionOrder(selectedOrder);
//Since we changed the order of the next item, we need to refresh the ZUL
questionList.set(questionList.indexOf(nextItem), nextItem);
//Remove the selected item from the list
questionList.remove(selectedItem);
// Add the selected item to the list in the next idex position
questionList.add(++index, selectedItem);
// Very Important, select the same item once we move down
questionList.addToSelection(selectedItem);
}
@Listen("onClick = #upBtn")
public void up() {
int selectedOrder;
int nextOrder;
Set<Questions> selected = questionList.getSelection();
if (selected.isEmpty())
return;
int index = questionList.indexOf(selected.iterator().next());
if (index == 0 || index < 0)
return;
Questions selectedItem = questionList.get(index);
Questions nextItem = questionList.get(index - 1);
selectedOrder = selectedItem.getQuestionOrder();
nextOrder = nextItem.getQuestionOrder();
selectedItem.setQuestionOrder(nextOrder);
nextItem.setQuestionOrder(selectedOrder);
questionList.set(questionList.indexOf(nextItem), nextItem);
questionList.remove(selectedItem);
questionList.add(--index, selectedItem);
questionList.addToSelection(selectedItem);
}
}