Listbox Template"
Line 1: | Line 1: | ||
{{ZKDevelopersReferencePageHeader}} | {{ZKDevelopersReferencePageHeader}} | ||
+ | |||
+ | __TOC__ | ||
The template used to control the rendering of each item must be named <code>model</code> and declared right inside the <code>listbox</code> element. For example, | The template used to control the rendering of each item must be named <code>model</code> and declared right inside the <code>listbox</code> element. For example, | ||
Line 18: | Line 20: | ||
</source> | </source> | ||
− | + | The template's name is important because users are allowed to associate multiple templates to one component, and <code>listbox</code>'s default renderer looks only for the template called <code>model</code>. | |
− | When the template is rendered, a variable called <code>each</code> is assigned with the data being rendered. Thus, you could retrieve the information to render with EL expressions, such as <code>${each[0]}</code> or <code>${each.name}</code>, if it is a bean with a setter called <code>name</code>. | + | When the template is rendered, a variable called <code>each</code> is assigned with the data being rendered. Thus, you could retrieve the information to render with EL expressions, such as <code>${each[0]}</code>, if it is an array, or <code>${each.name}</code>, if it is a bean with a setter called <code>name</code>. |
− | Notice that, if <code>value="${each}"</code> is not specified to the <code>listitem</code> element (<javadoc method="setValue(java.lang.Object)">org.zkoss.zul.Listitem</javadoc>) in the template, | + | Notice that, if <code>value="${each}"</code> is not specified to the <code>listitem</code> element (<javadoc method="setValue(java.lang.Object)">org.zkoss.zul.Listitem</javadoc>) in the template, the data being rendered will be assigned to the component's value, such that you could conveniently retrieve back the data when necessary. |
The <code>$composer.fruits</code> expression, in this example, is expected to return a two-dimensional array<ref>Of course, it can be anything you like. Just make sure it matches the EL expressions specified in the template.</ref>. It is provided by the <code>foo.FruitProvider</code> composer such as follows<ref>Here we use <javadoc>org.zkoss.zk.ui.select.SelectorComposer</javadoc> for simplicity. There are several ways to implement a composer, such as wiring a Spring-managed bean. For more information, please refer to [[ZK Developer's Reference/MVC/Controller/Composer|the Composer section]]</ref>. | The <code>$composer.fruits</code> expression, in this example, is expected to return a two-dimensional array<ref>Of course, it can be anything you like. Just make sure it matches the EL expressions specified in the template.</ref>. It is provided by the <code>foo.FruitProvider</code> composer such as follows<ref>Here we use <javadoc>org.zkoss.zk.ui.select.SelectorComposer</javadoc> for simplicity. There are several ways to implement a composer, such as wiring a Spring-managed bean. For more information, please refer to [[ZK Developer's Reference/MVC/Controller/Composer|the Composer section]]</ref>. | ||
Line 42: | Line 44: | ||
[[File:St201107-listbox.png]] | [[File:St201107-listbox.png]] | ||
+ | ==The forEachStatus variable== | ||
+ | There is a variable called [[ZUML Reference/EL Expressions/Implicit Objects/forEachStatus|forEachStatus]] providing the information of the iteration. It is an instance of <javadoc type="interface">org.zkoss.zk.ui.util.ForEachStatus</javadoc>. For example, you could retrieve the iteration's index by use of <code>${forEachStatus.index}</code>. | ||
<blockquote> | <blockquote> | ||
Line 81: | Line 85: | ||
[[File:St201107-listbox-in-listbox.png]] | [[File:St201107-listbox-in-listbox.png]] | ||
− | === | + | ===How to retrieve the outer template's data in the inner template=== |
− | |||
− | == | + | Although [[ZUML Reference/EL Expressions/Implicit Objects/forEachStatus|forEachStatus]] has an API called <javadoc method="getPrevious()" type="interface">org.zkoss.zk.ui.util.ForEachStatus</javadoc>, it always returns null<ref>On the other hand, it returns the previous iteration information when using with [[ZUML Reference/ZUML/Attributes/forEach|the forEach attribute]]</ref>. It is because the template is rendered on demand. When ZK is rendering the inner template, the previous iteration has already gone. There is no way to retrieve the iteration information of the outer template. |
− | + | ||
+ | Rather, you have to traverse the component tree or use [[ZUML Reference/ZUML/Elements/custom-attributes|the custom-attributes element]. | ||
+ | |||
+ | Here is an example of traversing the component tree to retrieve the data in the outer template. As shown at line 9 below, you could retrieve the data by traversing the component tree. Notice that, each data is, by default, stored in the component's value property (<javadoc method="getValue()">org.zkoss.zul.Listitem</javadoc>). | ||
<source lang="xml" high="9"> | <source lang="xml" high="9"> | ||
Line 107: | Line 113: | ||
</source> | </source> | ||
− | It is tedious and somehow error prone. Alternatively, you can store the information into a custom attribute. | + | If the component tree is deep, It is tedious and somehow error prone. Alternatively, you can store the information into a custom attribute and then retrieve it later, as shown at line 4 and 10 below. |
<source lang="xml" high="4,10"> | <source lang="xml" high="4,10"> | ||
Line 130: | Line 136: | ||
</source> | </source> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
=Template for GroupsModel= | =Template for GroupsModel= | ||
Revision as of 10:13, 13 February 2012
The template used to control the rendering of each item must be named model
and declared right inside the listbox
element. For example,
<listbox model="${$composer.fruits}" apply="foo.FruitProvider">
<listhead>
<listheader label="Name" sort="auto"/>
<listheader label="Weight" sort="auto"/>
</listhead>
<template name="model">
<listitem>
<listcell label="${each[0]}"/>
<listcell label="${each[1]}"/>
</listitem>
</template>
</listbox>
The template's name is important because users are allowed to associate multiple templates to one component, and listbox
's default renderer looks only for the template called model
.
When the template is rendered, a variable called each
is assigned with the data being rendered. Thus, you could retrieve the information to render with EL expressions, such as ${each[0]}
, if it is an array, or ${each.name}
, if it is a bean with a setter called name
.
Notice that, if value="${each}"
is not specified to the listitem
element (Listitem.setValue(Object)) in the template, the data being rendered will be assigned to the component's value, such that you could conveniently retrieve back the data when necessary.
The $composer.fruits
expression, in this example, is expected to return a two-dimensional array[1]. It is provided by the foo.FruitProvider
composer such as follows[2].
public class FruitProvider extends org.zkoss.zk.ui.select.SelectorComposer {
public String[][] fruits = new ListModelArray(
new String[][] {
{"Apple", "10kg"},
{"Orange", "20kg"},
{"Mango", "12kg"}
});
public String[][] getFruits() {
return fruits;
}
}
The forEachStatus variable
There is a variable called forEachStatus providing the information of the iteration. It is an instance of ForEachStatus. For example, you could retrieve the iteration's index by use of ${forEachStatus.index}
.
- ↑ Of course, it can be anything you like. Just make sure it matches the EL expressions specified in the template.
- ↑ Here we use SelectorComposer for simplicity. There are several ways to implement a composer, such as wiring a Spring-managed bean. For more information, please refer to the Composer section
Nested Listboxes
The template can be applied recursively. Here is an example of a listbox-in-listbox:
<zk>
<zscript><![CDATA[
ListModel quarters = new ListModelArray(new String[] {"Q1", "Q2", "Q3", "Q4"});
Map months = new HashMap();
months.put("Q1", new ListModelArray(new String[] {"Jan", "Feb", "Mar"}));
months.put("Q2", new ListModelArray(new String[] {"Apr", "May", "Jun"}));
months.put("Q3", new ListModelArray(new String[] {"Jul", "Aug", "Sep"}));
months.put("Q4", new ListModelArray(new String[] {"Oct", "Nov", "Dec"}));
ListModel qs = (quarters);
]]></zscript>
<listbox model="${quarters}">
<template name="model">
<listitem>
<listcell>${each}</listcell>
<listcell>
<listbox model="${months[each]}">
<template name="model">
<listitem label="${each}"/>
</template>
</listbox>
</listcell>
</listitem>
</template>
</listbox>
</zk>
How to retrieve the outer template's data in the inner template
Although forEachStatus has an API called ForEachStatus.getPrevious(), it always returns null[1]. It is because the template is rendered on demand. When ZK is rendering the inner template, the previous iteration has already gone. There is no way to retrieve the iteration information of the outer template.
Rather, you have to traverse the component tree or use [[ZUML Reference/ZUML/Elements/custom-attributes|the custom-attributes element].
Here is an example of traversing the component tree to retrieve the data in the outer template. As shown at line 9 below, you could retrieve the data by traversing the component tree. Notice that, each data is, by default, stored in the component's value property (Listitem.getValue()).
<listbox model="${quarters}">
<template name="model">
<listitem>
<listcell>
<listbox model="${months[each]}">
<template name="model">
<listitem>
<listcell label="${forEachStatus.index}" />
<listcell>${self.parent.parent.parent.parent.parent.value}</listcell>
<listcell>${each}</listcell>
</listitem>
</template>
</listbox>
</listcell>
</listitem>
</template>
</listbox>
If the component tree is deep, It is tedious and somehow error prone. Alternatively, you can store the information into a custom attribute and then retrieve it later, as shown at line 4 and 10 below.
<listbox model="${quarters}">
<template name="model">
<listitem>
<custom-attributes master="${each}"/>
<listcell>
<listbox model="${months[each]}">
<template name="model">
<listitem>
<listcell label="${forEachStatus.index}" />
<listcell>${master}</listcell>
<listcell>${each}</listcell>
</listitem>
</template>
</listbox>
</listcell>
</listitem>
</template>
</listbox>
Template for GroupsModel
When used with GroupsModel, listboxes will use the template called model:grouping for rendering the grouping object. If it is not defined, it will look for the template called model instead (i.e., the same template is used for rendering the grouping and non-grouping objects).
<listbox mode="${fooGroupsModel}">
<template name="model:group">
<listgroup open="${groupingInfo.open}" label="${each}"/>
</template>
<template name="model">
<listitem>....</listitem>
</template>
<template name="model:groupfoot">
<listgroupfoot>....</listgroupfoot>
</template>
<listbox>
- Note the groupingInfo is used to get the information of the grouping data. Please refer to GroupingInfo
Version History
Version | Date | Content |
---|---|---|
6.0.0 | July 2011 | The template feature was introduced. |
6.0.0 | January 2012 | The GroupingInfo statement was introduced. |
- ↑ On the other hand, it returns the previous iteration information when using with the forEach attribute