Implementing Data Binding"

From Documentation
m
m
Line 5: Line 5:
  
 
===The Orders View===
 
===The Orders View===
In the Orders View, we present users with all the records of the orders placed.  
+
In the Orders View, we present users with all the records of the orders placed. The upper portion of the view, implemented using a <javadoc>org.zkoss.zul.Listbox</javadoc>, discloses information on the orders placed. When users click on an item in the list, the details pertaining to the products purchased in that order is shown in the grid below. Users could cancel an order by clicking the button "Cancel Selected Order".
  
 
[[Image:ZKEssentials_DataBinding_OrdersView.png]]
 
[[Image:ZKEssentials_DataBinding_OrdersView.png]]
  
 
===How Data Binding and Controller Work Together===
 
===How Data Binding and Controller Work Together===
 +
In the [[http://books.zkoss.org/wiki/ZK_Essentials/Displaying_information_using_the_Listbox/Using_a_ListModel_and_ListitemRenderer previous section]], we looked at how the controller works in the View-Model-Render approach. Using annotated data binding, we no longer need to wrap a data collection with a ZK utility model class and implementing a renderer, therefore, we could simplify the code at the controller class:
 +
 +
<source lang="java" highlight="9,10,11,12,13">
 +
public class DatabindingOrderViewCtrl extends GenericForwardComposer implements OrderCtrl{
 +
 +
private static final String KEY_ORDER_VIEW_CTRL = "KEY_ORDER_VIEW_CTRL";
 +
 +
private Listbox orderLibox;
 +
private Button cancelOrderBtn;
 +
 +
@Override
 +
public void doAfterCompose(Component comp) throws Exception {
 +
super.doAfterCompose(comp);
 +
desktop.setAttribute(KEY_ORDER_VIEW_CTRL, this);
 +
cancelOrderBtn.setDisabled(true);
 +
}
 +
 +
//no more model or renderer code needed
 +
 +
public void onClick$cancelOrderBtn(){
 +
if(orderLibox.getSelectedItem()==null){
 +
return;
 +
}
 +
Order order = (Order) orderLibox.getSelectedItem().getValue();
 +
cancelOrder(order.getId());
 +
}
 +
 +
public void onSelect$orderLibox(){
 +
if(cancelOrderBtn.isDisabled())
 +
cancelOrderBtn.setDisabled(false);
 +
}
 +
 +
private void cancelOrder(Long orderId) {
 +
//1. Do the update using DAO
 +
getOrderDAO().cancelOrder(orderId);
 +
//2. update UI
 +
AnnotateDataBinder binder = (AnnotateDataBinder) page.getAttribute("binder");
 +
binder.loadAll();
 +
}
 +
 +
}
 +
</source>
  
 
<source lang="xml">
 
<source lang="xml">
Line 49: Line 91:
 
</div>
 
</div>
 
</south>
 
</south>
 
</source>
 
 
 
<source lang="java">
 
public class DatabindingOrderViewCtrl extends GenericForwardComposer implements OrderCtrl{
 
 
private static final String KEY_ORDER_VIEW_CTRL = "KEY_ORDER_VIEW_CTRL";
 
 
private Listbox orderLibox;
 
private Button cancelOrderBtn;
 
 
@Override
 
public void doAfterCompose(Component comp) throws Exception {
 
super.doAfterCompose(comp);
 
desktop.setAttribute(KEY_ORDER_VIEW_CTRL, this);
 
cancelOrderBtn.setDisabled(true);
 
}
 
 
public static OrderCtrl getInstance(Desktop desktop) {
 
return (OrderCtrl) desktop.getAttribute(KEY_ORDER_VIEW_CTRL);
 
}
 
 
public List<Order> getOrders(){
 
List<Order> orders = getOrderDAO().findByUser(getCurrentUserId());
 
return orders;
 
}
 
 
private Long getCurrentUserId(){
 
Long userId = UserCredentialManager.getIntance(session).getUser().getId();
 
return userId;
 
}
 
 
private static OrderDAO getOrderDAO(){
 
return new OrderDAO();
 
}
 
 
 
@Override
 
public Order submitNewOrder(List<CartItem> items, String description) {
 
//1. insert a new order, and a bunch of order_item into the DB.
 
Order order = getOrderDAO().createOrder(getCurrentUserId(), items, description);
 
//2. show this new Order at the UI.
 
getOrderModel().add(order);
 
return order;
 
}
 
 
private ListModelList getOrderModel(){
 
return (ListModelList) orderLibox.getModel();
 
}
 
 
public void onClick$cancelOrderBtn(){
 
if(orderLibox.getSelectedItem()==null){
 
return;
 
}
 
Order order = (Order) orderLibox.getSelectedItem().getValue();
 
cancelOrder(order.getId());
 
}
 
public void onSelect$orderLibox(){
 
if(cancelOrderBtn.isDisabled())
 
cancelOrderBtn.setDisabled(false);
 
}
 
 
private void cancelOrder(Long orderId) {
 
//1. Do the update using DAO
 
getOrderDAO().cancelOrder(orderId);
 
//2. update UI
 
AnnotateDataBinder binder = (AnnotateDataBinder) page.getAttribute("binder");
 
binder.loadAll();
 
}
 
 
}
 
 
 
</source>
 
</source>

Revision as of 09:53, 22 October 2010

Implementing Data Binding

In the previous sections, we implemented a "View-Model-Renderer" approach to populate tabular data in components (Grid, Listbox). In this section, we explore how to leverage ZK's convenient annotated data binding to achieve the same end.

The Orders View

In the Orders View, we present users with all the records of the orders placed. The upper portion of the view, implemented using a Listbox, discloses information on the orders placed. When users click on an item in the list, the details pertaining to the products purchased in that order is shown in the grid below. Users could cancel an order by clicking the button "Cancel Selected Order".

ZKEssentials DataBinding OrdersView.png

How Data Binding and Controller Work Together

In the [previous section], we looked at how the controller works in the View-Model-Render approach. Using annotated data binding, we no longer need to wrap a data collection with a ZK utility model class and implementing a renderer, therefore, we could simplify the code at the controller class:

public class DatabindingOrderViewCtrl extends GenericForwardComposer implements OrderCtrl{

	private static final String KEY_ORDER_VIEW_CTRL = "KEY_ORDER_VIEW_CTRL";
	
	private Listbox orderLibox;
	private Button cancelOrderBtn;
	
	@Override
	public void doAfterCompose(Component comp) throws Exception {
		super.doAfterCompose(comp);
		desktop.setAttribute(KEY_ORDER_VIEW_CTRL, this);
		cancelOrderBtn.setDisabled(true);
	}
	
	//no more model or renderer code needed
	
	public void onClick$cancelOrderBtn(){
		if(orderLibox.getSelectedItem()==null){
			return;
		}
		Order order = (Order) orderLibox.getSelectedItem().getValue();
		cancelOrder(order.getId());
	}

	public void onSelect$orderLibox(){
		if(cancelOrderBtn.isDisabled())
			cancelOrderBtn.setDisabled(false);
	}

	private void cancelOrder(Long orderId) {
		//1. Do the update using DAO
		getOrderDAO().cancelOrder(orderId);
		//2. update UI
		AnnotateDataBinder binder = (AnnotateDataBinder) page.getAttribute("binder");
		binder.loadAll();
	}
	
}
<south  size="250px" flex="true" border="0" 
		splittable="true" collapsible="true" style="overflow:scroll">
		<div id="orderArea" style="background:#E6D92C; height:100%" apply="demo.web.ui.ctrl.DatabindingOrderViewCtrl" >
		
		<listbox id="orderLibox" model="@{orderArea$composer.orders}" selectedItem="@{selectedOrder}">
			<listhead>
				<listheader label="info"/>
				<listheader label="description"/>
				<listheader label="Sub Total"/>
			</listhead>
			
			<listitem self="@{each='order'}" value="@{order}">
				<listcell label="@{order, converter='demo.web.ui.OrderInfoTypeConverter'}" />
				<listcell label="@{order.description}" />
				<listcell label="@{order.total}" />
			</listitem>
		</listbox>

		<grid id="orderItemsGrid" model="@{selectedOrder.items}">
			<columns sizable="true">
				<column label="Name"/>
				<column label="Quantity"/>
				<column label="Price"/>
				<column label="Sub Total"/>
		    </columns>
		    <rows>
		    	<row self="@{each='orderItem'}">
		    		<label  value="@{orderItem.name}"/>
					<label value="@{orderItem.quantity}"/>
					<label value="@{orderItem.price}"/>
					<label value="@{orderItem, converter='demo.web.ui.OrderItemSubTotalTypeConverter'}" maxlength="8" />
		    	</row>
		    </rows>
		</grid>
		<button id="cancelOrderBtn" label="Cancel Selected Order"/>
		</div>
	</south>