Model"
(ZK 6) |
RebeccaLai (talk | contribs) m |
||
(6 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{ZKDevelopersReferencePageHeader}} | {{ZKDevelopersReferencePageHeader}} | ||
− | + | __TOC__ | |
− | The ''model'' is the data an application handles. Depending on the application requirement, it could be anything as long as your controller knows it. Typical objects are POJOs, beans, Spring-managed beans, and | + | The ''model'' is the data an application handles. Depending on the application requirement, it could be anything as long as your controller knows it. Typical objects are POJOs, beans, Spring-managed beans, and DAOs. Examples of manipulating the model in the controller were discussed in the previous sections. |
In this section and subsections, we will focus on the model that ZK components support directly without custom glue logic. For example, implementing <javadoc type="interface">org.zkoss.zul.ListModel</javadoc> to control the display of <javadoc>org.zkoss.zul.Listbox</javadoc> and <javadoc>org.zkoss.zul.Grid</javadoc>, and <javadoc type="interface">org.zkoss.zul.ChartModel</javadoc> to control <javadoc>org.zkoss.zul.Chart</javadoc>. | In this section and subsections, we will focus on the model that ZK components support directly without custom glue logic. For example, implementing <javadoc type="interface">org.zkoss.zul.ListModel</javadoc> to control the display of <javadoc>org.zkoss.zul.Listbox</javadoc> and <javadoc>org.zkoss.zul.Grid</javadoc>, and <javadoc type="interface">org.zkoss.zul.ChartModel</javadoc> to control <javadoc>org.zkoss.zul.Chart</javadoc>. | ||
− | In addition to implementing these models, you could use one of the predefined | + | In addition to implementing these models, you could use one of the predefined implementations such as <javadoc>org.zkoss.zul.SimpleListModel</javadoc> and <javadoc>org.zkoss.zul.SimplePieModel</javadoc>. For detailed description, please refer to the following sections. |
− | + | ||
+ | = Model-Driven Rendering = | ||
+ | Those ZK components (e.g. Listbox, Grid, Tree) that allow you to set <code>model</code> properties support model-driven rendering, which means they create (render) their child components upon a model object (e.g. <code>ListModelList</code>). Hence, you can assign a ListModelList to a Listbox, and it will render its Listitem upon the ListModelList with its renderer. | ||
+ | |||
+ | In this case, you have to control the component's rendering by '''manipulating its model objects'''. If you want to remove a Listitem, don't remove the Listitem object itself. You should remove the corresponding object in the ListModelList (<code>remove()</code>). Then Listbox will remove the Listitem accordingly. The same rule applies to adding, clearing, and replacing. | ||
+ | |||
+ | From one component's perspective, it also follows the MVC pattern: | ||
+ | [[File:model-driven-rendering.jpg | center]] | ||
+ | |||
+ | |||
+ | * '''Component (Controller)''' | ||
+ | ** get data objects from a Model | ||
+ | ** as a data change listener of Model (by invoking <javadoc method="addListDataListener(org.zkoss.zul.event.ListDataListener)" type="interface">org.zkoss.zul.ListModel</javadoc>) | ||
+ | ** handle events from the client e.g. update the selection upon user clicking | ||
+ | * '''ListModel (Model)''' | ||
+ | ** it stores your domain objects (the data could be Car, Person) | ||
+ | ** notify the component for data update when you call its method e.g. <code>add(), remove(), clear()</code> | ||
+ | ** ZK provides various default model implementations for various components, please refer to [https://www.zkoss.org/javadoc/latest/zk/org/zkoss/zul/ListModel.html ListModel], [https://www.zkoss.org/javadoc/latest/zk/org/zkoss/zul/TreeModel.html TreeModel], [http://www.zkoss.org/javadoc/latest/zk/org/zkoss/zul/GroupsModel.html GroupsModel] | ||
+ | * '''Renderer (View)''' | ||
+ | ** render/create child components and insert them into their parent component according to the request from the Component | ||
+ | ** each component has its own built-in renderer | ||
= How to Assign Model to UI = | = How to Assign Model to UI = | ||
Line 15: | Line 35: | ||
== Use Composer to Assign Model == | == Use Composer to Assign Model == | ||
− | A typical way is to use [[ZK Developer's Reference/MVC/Controller/Composer|a composer]] to assign the model. For example, assume the UI component is a grid and we have a method called < | + | A typical way is to use [[ZK Developer's Reference/MVC/Controller/Composer|a composer]] to assign the model. For example, assume the UI component is a grid and we have a method called <code>getFooModel</code> returning the data to show on the grid, then we could implement a composer, say <code>foo.FooComposer</code> as follows: |
<source lang="java"> | <source lang="java"> | ||
Line 32: | Line 52: | ||
</source> | </source> | ||
− | == Use | + | == Use Data Binding == |
− | If you are using [[ZK Developer's Reference/MVVM/Data Binding|data binding]] | + | If you are using [[ZK Developer's Reference/MVVM/Data Binding|data binding]], you can have the data binder to assign the model for you. For example, assume that you have a <code>ListModelList persons</code>, then: |
<source lang="xml"> | <source lang="xml"> | ||
− | <listbox model="@ | + | <listbox model="@init(vm.persons)"> |
− | |||
</source> | </source> | ||
== Use EL Expressions == | == Use EL Expressions == | ||
− | EL is another common way to assign the model. For example, assume you have a variable resolver called < | + | EL is another common way to assign the model. For example, assume you have a variable resolver called <code>foo.FooVariableResolver</code> implementing <javadoc>org.zkoss.xel.VariableResolver</javadoc> as follows. |
<source lang="java"> | <source lang="java"> | ||
Line 59: | Line 78: | ||
<?variable-resolver class="foo.FooVariableResolver"?> | <?variable-resolver class="foo.FooVariableResolver"?> | ||
− | <listbox model="${persons"> | + | <listbox model="${persons}"> |
... | ... | ||
</source> | </source> | ||
Line 88: | Line 107: | ||
'''Notice''' that, since the performance of zscript is not good and the mix of Java code in ZUML is not easy to maintain, it is suggested '''not''' to use this approach in a production system. Please refer to [[ZK Developer's Reference/Performance Tips/Use Compiled Java Codes|Performance Tips]] for more information. | '''Notice''' that, since the performance of zscript is not good and the mix of Java code in ZUML is not easy to maintain, it is suggested '''not''' to use this approach in a production system. Please refer to [[ZK Developer's Reference/Performance Tips/Use Compiled Java Codes|Performance Tips]] for more information. | ||
+ | |||
+ | |||
+ | |||
+ | {{ZKDevelopersReferenceHeadingToc}} | ||
{{ZKDevelopersReferencePageFooter}} | {{ZKDevelopersReferencePageFooter}} |
Latest revision as of 07:33, 29 January 2024
The model is the data an application handles. Depending on the application requirement, it could be anything as long as your controller knows it. Typical objects are POJOs, beans, Spring-managed beans, and DAOs. Examples of manipulating the model in the controller were discussed in the previous sections.
In this section and subsections, we will focus on the model that ZK components support directly without custom glue logic. For example, implementing ListModel to control the display of Listbox and Grid, and ChartModel to control Chart.
In addition to implementing these models, you could use one of the predefined implementations such as SimpleListModel and SimplePieModel. For detailed description, please refer to the following sections.
Model-Driven Rendering
Those ZK components (e.g. Listbox, Grid, Tree) that allow you to set model
properties support model-driven rendering, which means they create (render) their child components upon a model object (e.g. ListModelList
). Hence, you can assign a ListModelList to a Listbox, and it will render its Listitem upon the ListModelList with its renderer.
In this case, you have to control the component's rendering by manipulating its model objects. If you want to remove a Listitem, don't remove the Listitem object itself. You should remove the corresponding object in the ListModelList (remove()
). Then Listbox will remove the Listitem accordingly. The same rule applies to adding, clearing, and replacing.
From one component's perspective, it also follows the MVC pattern:
- Component (Controller)
- get data objects from a Model
- as a data change listener of Model (by invoking ListModel.addListDataListener(ListDataListener))
- handle events from the client e.g. update the selection upon user clicking
- ListModel (Model)
- it stores your domain objects (the data could be Car, Person)
- notify the component for data update when you call its method e.g.
add(), remove(), clear()
- ZK provides various default model implementations for various components, please refer to ListModel, TreeModel, GroupsModel
- Renderer (View)
- render/create child components and insert them into their parent component according to the request from the Component
- each component has its own built-in renderer
How to Assign Model to UI
Depending on the requirements, there are a few ways to assign a model to a UI component.
Use Composer to Assign Model
A typical way is to use a composer to assign the model. For example, assume the UI component is a grid and we have a method called getFooModel
returning the data to show on the grid, then we could implement a composer, say foo.FooComposer
as follows:
public class FooComposer implements Composer {
public void doAfterCompose(Component comp) throws Exception {
((Grid)comp).setModel(getFooModel());
}
}
Then, you could assign it in ZUML as follows:
<grid apply="foo.FooComposer">
...
Use Data Binding
If you are using data binding, you can have the data binder to assign the model for you. For example, assume that you have a ListModelList persons
, then:
<listbox model="@init(vm.persons)">
Use EL Expressions
EL is another common way to assign the model. For example, assume you have a variable resolver called foo.FooVariableResolver
implementing VariableResolver as follows.
public class FooVariableResolver implements VariableResolver {
public Object resolveVariable(String name) {
if ("persons".equals(name)) //found
return getPersons(); //assume this method returns an instance of ListModel
//... you might support more other variables
return null; //not found
}
}
Then, you could specify it in ZUML as follows:
<?variable-resolver class="foo.FooVariableResolver"?>
<listbox model="${persons}">
...
The other approach is to use the function mapper. For example, assume you have an implementation called foo.CustomerListModel
, then you could use it to drive a listbox as follows.
<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c" ?>
<listbox model="${c:new('foo.CustomerListModel')}"/>
Use zscript
If you are building a prototype, you could use zscript to assign the model directly. For example,
<zk>
<zscript>
ListModel infos = new ListModelArray(
new String[][] {
{"Apple", "10kg"},
{"Orange", "20kg"},
{"Mango", "12kg"}
});
</zscript>
<listbox model="${infos}"/>
</zk>
Notice that, since the performance of zscript is not good and the mix of Java code in ZUML is not easy to maintain, it is suggested not to use this approach in a production system. Please refer to Performance Tips for more information.