Composite Components in the MVC"

From Documentation
m
(divided original content into sections; added intro and image)
Line 1: Line 1:
 
{{ZKEssentialsPageHeader}}
 
{{ZKEssentialsPageHeader}}
  
 +
__TOC__
  
First the syntax of the template will be dealt with. It looks incredibly similar to what one observed in the databinding chapter except using a $ instead of an @ and a slightly different syntax. This is because the markup below makes use of EL. EL expressions differ from databinding in the fact that they are only interpreted once, whereas databidning will be re-interpreted whenever it is notified a value has changed. Seeing as the product list will remain relatively constant, we'll use EL here.
+
In this section, we'll see how to use ZK's Composite Component pattern to implement a product order component that consists of a label, a spinner, and a button in the Product View.
  
For more information on EL please visit [[link needed here]]
+
[[Image:ZKEss_ProductOrder.png]]
  
 
+
===Declaring a Composite Component===
<source lang="xml">
 
<template name="model">
 
<row value="${each}">
 
<image height="70px" width="70px" src="${each.imgPath}" />
 
<label value="${each.name}" />
 
<label value="${each.price}" />
 
<label value="${each.quantity}" />
 
<label value="${each.createDate}" />
 
<productOrder maximumQuantity="${each.quantity}" product="${each}" />
 
</row>
 
</template>
 
</source>
 
 
 
The above snippet makes use of template (as spoken about briefly in the previous section) as well as EL.
 
 
 
=The template=
 
 
 
A template is a ZUML fragment that defines how to render data model in its children components and can contain any ZUML element you would like including other templates. In this case the template defines the layout of each row. The row value is assigned as "each" where each refers to a bean provided by the model.
 
 
 
A template is generally used within a Listbox, Grid, Tree and Combobox to describe how repeating items are displayed. For example take the application's case the template is contained within a Grid:
 
 
 
<source lang="xml">
 
<grid id="prodGrid">
 
<columns sizable="true">
 
...
 
</columns>
 
<template name="model">
 
<row value="${each}">
 
<image height="70px" width="70px"
 
src="${each.imgPath}" />
 
<label value="${each.name}" />
 
<label value="${each.price}" />
 
<label value="${each.quantity}" />
 
<label value="${each.createDate}" />
 
<productOrder maximumQuantity="${each.quantity}" product="${each}" />
 
</row>
 
</template>
 
</grid>
 
</source>
 
 
 
Thus the template is outputted for every bean contained in the grid's model. In this case the output is just relatively simple, however, one interesting item in the template is the productOrder control. This is in fact a composite control which is created by developers.
 
 
 
=Composite component=
 
  
 
A composite component is an advanced template that affords developers the ability to extend from any component. A composite component consists of a Java class which extends from a component, in this case the ProductOrder component extends from Cell as it will be placed into a grid row. The Cell will therefore contain multiple components.
 
A composite component is an advanced template that affords developers the ability to extend from any component. A composite component consists of a Java class which extends from a component, in this case the ProductOrder component extends from Cell as it will be placed into a grid row. The Cell will therefore contain multiple components.
Line 82: Line 40:
 
</source>
 
</source>
  
The snippet above shows two things happening, firstly the composite component renders a ZUML fragment which will be contained within itself. Taking a look at the Executions.createComponents function call on line 7 the first parameter is the location of the ZUML fragment, the second parameter is the component which will become the root, in this case itself. The third component is a HashMap containing the parameters to send to the fragment, in this case the maximumQuantity, which is just a simple bean.  
+
===Rendering the Composite Component===
 +
The snippet above shows two things happening, firstly the composite component renders a ZUML fragment which will be contained within itself. Taking a look at the Executions.createComponents function call on line 7, the first parameter is the location of the ZUML fragment, the second parameter is the component which will become the root, in this case itself. The third component is a HashMap containing the parameters to send to the fragment, in this case the maximumQuantity, which is just a simple bean.  
  
 
The fragment is shown below:
 
The fragment is shown below:
Line 96: Line 55:
 
In the above fragment one can see how the maximum quantity, which was passed to the fragment on creation, is accessed and used using EL expressions.  
 
In the above fragment one can see how the maximum quantity, which was passed to the fragment on creation, is accessed and used using EL expressions.  
  
 +
===Wiring Variables and Event Listeners===
 
Finally, within the composite component, variables, components and event listeners need to be wired. This is easy to do using the following method calls in the afterCompose function.
 
Finally, within the composite component, variables, components and event listeners need to be wired. This is easy to do using the following method calls in the afterCompose function.
  
Line 104: Line 64:
 
<source>
 
<source>
  
 +
===Using the Composite Component===
 
Having built the component it now needs to be registered with ZK, this is easily done by putting a directive at the top of the ZUL file you want to use it in. In the case of this application it is present in index.zul.
 
Having built the component it now needs to be registered with ZK, this is easily done by putting a directive at the top of the ZUL file you want to use it in. In the case of this application it is present in index.zul.
  
Line 111: Line 72:
  
 
The directive specifies a name for the component which can be referenced in the ZUL file and the appropriate class which drives the functionality. The component can now be used as follows:
 
The directive specifies a name for the component which can be referenced in the ZUL file and the appropriate class which drives the functionality. The component can now be used as follows:
 
  
 
<source lang="xml" high="13">
 
<source lang="xml" high="13">

Revision as of 22:24, 12 February 2012

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, we'll see how to use ZK's Composite Component pattern to implement a product order component that consists of a label, a spinner, and a button in the Product View.

ZKEss ProductOrder.png

Declaring a Composite Component

A composite component is an advanced template that affords developers the ability to extend from any component. A composite component consists of a Java class which extends from a component, in this case the ProductOrder component extends from Cell as it will be placed into a grid row. The Cell will therefore contain multiple components.

ProductOrder also implements IdSpace and AfterCompose; these two interfaces enable the component to take on additional behaviours. By implementing AfterCompose, when the composite component is created it enbables developers to perform actions such as wiring of variables or registering event listeners. In the case of the ProductOrder the snippet below shows the afterCompose method:

public class ProductOrder extends Cell implements IdSpace, AfterCompose {

	...

	public void afterCompose() {
		// 1. Render the ZUML fragment
		Executions.createComponents("/WEB-INF/composite/productorder.zul",
				this, new HashMap<String, Object>() {
					private static final long serialVersionUID = 7141348964577773718L;

					{
						put("maximumQuantity", getMaximumQuantity());
					}
				});

		// 2. Wire variables, components and event listeners (optional)
		Selectors.wireVariables(this, this, null);
		Selectors.wireComponents(this, this, false);
		Selectors.wireEventListeners(this, this);
	}

	...

}

Rendering the Composite Component

The snippet above shows two things happening, firstly the composite component renders a ZUML fragment which will be contained within itself. Taking a look at the Executions.createComponents function call on line 7, the first parameter is the location of the ZUML fragment, the second parameter is the component which will become the root, in this case itself. The third component is a HashMap containing the parameters to send to the fragment, in this case the maximumQuantity, which is just a simple bean.

The fragment is shown below:

<zk>
	<spinner id="spnQuantity" constraint="min 1 max ${arg.maximumQuantity}" value="1"/>
	<button id="btnAdd" label="add" image="/image/ShoppingCart-16x16.png" />
	<label id="lblError" />
</zk>

In the above fragment one can see how the maximum quantity, which was passed to the fragment on creation, is accessed and used using EL expressions.

Wiring Variables and Event Listeners

Finally, within the composite component, variables, components and event listeners need to be wired. This is easy to do using the following method calls in the afterCompose function.

Selectors.wireVariables(this, this, null);
Selectors.wireComponents(this, this, false);
Selectors.wireEventListeners(this, this);
<source>

===Using the Composite Component===
Having built the component it now needs to be registered with ZK, this is easily done by putting a directive at the top of the ZUL file you want to use it in. In the case of this application it is present in index.zul.

<source lang="xml">
<?component name="productOrder" class="demo.web.ui.ctrl.ProductOrder" ?>

The directive specifies a name for the component which can be referenced in the ZUL file and the appropriate class which drives the functionality. The component can now be used as follows:

<grid id="prodGrid">
	<columns sizable="true">
		...
	</columns>
	<template name="model">
		<row value="${each}">
			<image height="70px" width="70px"
				src="${each.imgPath}" />
			<label value="${each.name}" />
			<label value="${each.price}" />
			<label value="${each.quantity}" />
			<label value="${each.createDate}" />
			<productOrder maximumQuantity="${each.quantity}" product="${each}" />
		</row>
	</template>
</grid>

For more information on the composite component please consult the Developer's reference

This concludes this section of the document, the data is displayed correctly. The adding of products is discussed in the last chapter as it deals with communication between MVC and MVVM thus is a topic best introduced after MVVM. If you are interested you can take a look now.



Last Update : 2012/02/12

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