Displaying Information from the View Model"

From Documentation
(Created page with "{{ZKEssentialsPageHeader}} To start with the author will now give an overview of what the final ZUL fragment for the MVVM will look like. This section will then teach developers...")
 
m (correct highlight (via JWB))
 
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
#REDIRECT [[ZK Essentials]]
 +
 
{{ZKEssentialsPageHeader}}
 
{{ZKEssentialsPageHeader}}
 +
 +
__TOC__
 +
 +
In this section and the next, we'll implement the Shopping Cart View using the MVVM pattern. <br/>
 +
[[Image:ZKEss_ShoppingCart.png]]
  
 
To start with the author will now give an overview of what the final ZUL fragment for the MVVM will look like. This section will then teach developers how to create this step by step.
 
To start with the author will now give an overview of what the final ZUL fragment for the MVVM will look like. This section will then teach developers how to create this step by step.
Line 28: Line 35:
 
</listitem>
 
</listitem>
 
</template>
 
</template>
<listfoot>
+
...
<listfooter span="2" id="subtotalFooter" label="@load(vm.shoppingCart.totalPrice)">
 
</listfooter>
 
<listfooter>
 
<button id="submitOrderBtn" label="submit"
 
onClick="@command('submitOrder')"
 
disabled="@load(empty vm.cartItems)" />
 
</listfooter>
 
<listfooter>
 
<button id="clearBtn" label="clear"
 
onClick="@command('clearOrders')"
 
disabled="@load(empty vm.cartItems)" />
 
</listfooter>
 
</listfoot>
 
 
</listbox>
 
</listbox>
<vlayout>
+
        ...
<label value="Description" />
 
<textbox id="descTxb" rows="10" width="200px"
 
value="@bind(vm.orderNote)" hflex="true" />
 
<image id="cartItemImage"
 
image="@load(cartItem.product.imgPath)" hflex="true"/>
 
</vlayout>
 
 
</div>
 
</div>
 
</source>
 
</source>
  
=Getting into the basics=
+
===Initializing the BindComposer and ViewModel===
 
 
==Initializing the BindComposer and ViewModel==
 
  
 
The first thing that needs to be done is the initialization of the BindComposer which will manage binding for it's child components. This can be done simply using the familiar apply attribute to the parent control of your choice. In the case of this example the div which contains the listbox was chosen.
 
The first thing that needs to be done is the initialization of the BindComposer which will manage binding for it's child components. This can be done simply using the familiar apply attribute to the parent control of your choice. In the case of this example the div which contains the listbox was chosen.
  
<source lang="xml" high="1">
+
<source lang="xml" highlight="1">
 
<div apply="org.zkoss.bind.BindComposer"
 
<div apply="org.zkoss.bind.BindComposer"
 
viewModel="@id('vm') @init('demo.web.ui.ctrl.ShoppingCartViewModel')">
 
viewModel="@id('vm') @init('demo.web.ui.ctrl.ShoppingCartViewModel')">
Line 69: Line 55:
 
#Assign a name to the instantiated class
 
#Assign a name to the instantiated class
  
In this case @id is used to set the name of the instantiated view model to 'vm' while @init is used to specify the class to instantiate. Having specified a view model class one now needs to create said class.
+
In this case @id is used to set the name of the instantiated view model to 'vm' while @init is used to specify the class to instantiate. Having specified a view model class one now needs to create the said class.
  
==The View Model==
+
===Implementing The View Model===
  
 
In the MVVM pattern a view model is an abstraction of Model. It extracts the necessary data to be displayed on the View from one or more Model classes. Those data are exposed through getter and setter method like JavaBean's property. To create a view model is easy, there is no need to extend from nor implement any other class. A view model is a POJO and exposes its data using getter and setter methods.
 
In the MVVM pattern a view model is an abstraction of Model. It extracts the necessary data to be displayed on the View from one or more Model classes. Those data are exposed through getter and setter method like JavaBean's property. To create a view model is easy, there is no need to extend from nor implement any other class. A view model is a POJO and exposes its data using getter and setter methods.
 
The snippet below shows a basic view model:
 
  
 
<source lang="java">
 
<source lang="java">
 
public class ShoppingCartViewModel {
 
public class ShoppingCartViewModel {
+
...
}
 
</source>
 
  
==Making Use of the View Model, Loading Data==
 
 
For loading & saving data ZK's MVVM pattern provides two general commands, @load and @bind. @load command will only load data and any change to the data from the UI will not be saved to the bean. @bind on the other hand provides both loading and saving of the bean so any changes to the values driven by the UI will be reflected server-side.
 
 
With this in mind it is time to start loading the data into the shopping cart. First thing to be done is load the model and selected item. This is easily done by creating getters and/or setters serverside for the appropriate properties and accessing them in the UI. For the model and selected item the following getters and setters are created:
 
 
<source lang="java">
 
public class ShoppingCartViewModel {
 
 
 
private CartItem selectedItem;
 
private CartItem selectedItem;
  
Line 109: Line 82:
 
return UserUtils.getShoppingCart();
 
return UserUtils.getShoppingCart();
 
}
 
}
 +
        ...
 
}
 
}
 
</source>
 
</source>
  
Having implemented the appropriate getters and setters the UI can be updated:
 
  
<source lang="xml">
+
===Binding Data to View Model===
 +
 
 +
For loading & saving data ZK's MVVM pattern provides two general commands, @load and @bind. @load command will only load data and any change to the data from the UI will not be saved to the bean. @bind on the other hand provides both loading and saving of the bean so any changes to the values driven by the UI will be reflected server-side.
 +
 
 +
With this in mind it is time to start loading the data into the shopping cart. First thing to be done is load the model and selected item. This is easily done by accessing the getters and setters we implemented for the View Model:
 +
 
 
<source lang="xml">
 
<source lang="xml">
 
<div apply="org.zkoss.bind.BindComposer"
 
<div apply="org.zkoss.bind.BindComposer"
Line 131: Line 109:
 
It is now possible to implement a template as outlined in previous sections to create each Listitem. Using databinding the resulting template is extremely simple.
 
It is now possible to implement a template as outlined in previous sections to create each Listitem. Using databinding the resulting template is extremely simple.
  
<source lang="xml" high="6">
+
<source lang="xml" highlight="12">
<template name="model" var="cartItem">
+
<listbox id="shoppingCartListbox"
<listitem>
+
model="@load(vm.cartItems)"
<listcell label="@load(cartItem.product.name)" />
+
selectedItem="@bind(vm.selectedItem)">
<listcell label="@load(cartItem.product.price)" />
+
<listhead sizable="true">
<listcell label="@load(cartItem.amount)" />
+
...
<listcell label="@load(cartItem.product.price * cartItem.amount)" style="word-wrap: word-break" />
+
</listhead>
 
+
<template name="model" var="cartItem">
...
+
<listitem>
</listitem>
+
<listcell label="@load(cartItem.product.name)" />
</template>
+
<listcell label="@load(cartItem.product.price)" />
 +
<listcell label="@load(cartItem.amount)" />
 +
<listcell label="@load(cartItem.product.price * cartItem.amount)" style="word-wrap: word-break" />
 +
<listcell>
 +
<button image="/image/DeleteCross-16x16.png" onClick="@command('deleteOrder', cartItem=cartItem)" />
 +
</listcell>
 +
</listitem>
 +
</template>
 +
                ...
 +
</listbox>
 
</source>
 
</source>
  

Latest revision as of 12:29, 19 January 2022

Redirect to:

Stop.png This article is out of date, please refer to http://books.zkoss.org/zkessentials-book/master/ for more up to date information.


In this section and the next, we'll implement the Shopping Cart View using the MVVM pattern.
ZKEss ShoppingCart.png

To start with the author will now give an overview of what the final ZUL fragment for the MVVM will look like. This section will then teach developers how to create this step by step.

<div apply="org.zkoss.bind.BindComposer"
	viewModel="@id('vm') @init('demo.web.ui.ctrl.ShoppingCartViewModel')">

	<listbox id="shoppingCartListbox"
		model="@load(vm.cartItems)"
		selectedItem="@bind(vm.selectedItem)">
		<listhead sizable="true">
			<listheader label="Name" />
			<listheader label="Price" />
			<listheader label="Amount" />
			<listheader label="subTotal" />
			<listheader align="center" />
		</listhead>
		<template name="model" var="cartItem">
			<listitem>
				<listcell label="@load(cartItem.product.name)" />
				<listcell label="@load(cartItem.product.price)" />
				<listcell label="@load(cartItem.amount)" />
				<listcell label="@load(cartItem.product.price * cartItem.amount)" style="word-wrap: word-break" />
				<listcell>
					<button image="/image/DeleteCross-16x16.png" onClick="@command('deleteOrder', cartItem=cartItem)" />
				</listcell>
			</listitem>
		</template>
		...
	</listbox>
        ...
</div>

Initializing the BindComposer and ViewModel

The first thing that needs to be done is the initialization of the BindComposer which will manage binding for it's child components. This can be done simply using the familiar apply attribute to the parent control of your choice. In the case of this example the div which contains the listbox was chosen.

<div apply="org.zkoss.bind.BindComposer"
	viewModel="@id('vm') @init('demo.web.ui.ctrl.ShoppingCartViewModel')">

Line 2 in the above snippet assigns a value to a viewModel property. This property is used for two things

  1. Tell the binder which ViewModel class to instantiate
  2. Assign a name to the instantiated class

In this case @id is used to set the name of the instantiated view model to 'vm' while @init is used to specify the class to instantiate. Having specified a view model class one now needs to create the said class.

Implementing The View Model

In the MVVM pattern a view model is an abstraction of Model. It extracts the necessary data to be displayed on the View from one or more Model classes. Those data are exposed through getter and setter method like JavaBean's property. To create a view model is easy, there is no need to extend from nor implement any other class. A view model is a POJO and exposes its data using getter and setter methods.

public class ShoppingCartViewModel {
	...

	private CartItem selectedItem;

	public CartItem getSelectedItem() {
		return selectedItem;
	}

	public void setSelectedItem(CartItem selectedItem) {
		this.selectedItem = selectedItem;
	}

	public List<CartItem> getCartItems() {
		return UserUtils.getShoppingCart().getItems();
	}
	
	public ShoppingCart getShoppingCart() {
		return UserUtils.getShoppingCart();
	}
        ...
}


Binding Data to View Model

For loading & saving data ZK's MVVM pattern provides two general commands, @load and @bind. @load command will only load data and any change to the data from the UI will not be saved to the bean. @bind on the other hand provides both loading and saving of the bean so any changes to the values driven by the UI will be reflected server-side.

With this in mind it is time to start loading the data into the shopping cart. First thing to be done is load the model and selected item. This is easily done by accessing the getters and setters we implemented for the View Model:

<div apply="org.zkoss.bind.BindComposer"
	viewModel="@id('vm') @init('demo.web.ui.ctrl.ShoppingCartViewModel')">

	<listbox id="shoppingCartListbox"
		model="@load(vm.cartItems)"
		selectedItem="@bind(vm.selectedItem)">

			...

	</listbox>
</div>

It is now possible to implement a template as outlined in previous sections to create each Listitem. Using databinding the resulting template is extremely simple.

	<listbox id="shoppingCartListbox"
		model="@load(vm.cartItems)"
		selectedItem="@bind(vm.selectedItem)">
		<listhead sizable="true">
			...
		</listhead>
		<template name="model" var="cartItem">
			<listitem>
				<listcell label="@load(cartItem.product.name)" />
				<listcell label="@load(cartItem.product.price)" />
				<listcell label="@load(cartItem.amount)" />
				<listcell label="@load(cartItem.product.price * cartItem.amount)" style="word-wrap: word-break" />
				<listcell>
					<button image="/image/DeleteCross-16x16.png" onClick="@command('deleteOrder', cartItem=cartItem)" />
				</listcell>
			</listitem>
		</template>
                ...
	</listbox>

Line 6 brings about an intersting use case as instead of just specifying a bean's property it specifies an equation. The binder is capable of handling expressions. There are many more expressions available for more information please click here link needed.

This takes care of basic loading and saving functionality, but what about actions such as clicking buttons? The next section introduces how to give commands based on component actions.



Last Update : 2022/01/19

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.