ZK8 Features for MVC - Shadow Elements - Part 2"

From Documentation
Line 133: Line 133:
 
=== Dynamic Templates ===
 
=== Dynamic Templates ===
  
Things become interesting when rendering each item differently (e.g. based on a condition or property). For such cases the <apply> element can be nested inside the <forEach>.
+
Things become interesting when rendering items differently (e.g. based on a condition or property). For such cases the <apply> element can be nested inside the <forEach>.
 +
 
 +
<source lang="xml" high="">
 +
<!-- named inline templates -->
 +
<forEach items="${someCollectionOfConfigElements}" var="configElement">
 +
    <apply template="${configElement.editable ? 'editable' : 'readonly'}">
 +
        <template name="editable">
 +
            <textbox value=${configElement.name}" forward="onChange=onChangeConfigElementName(${configElement})"/>
 +
        </template>
 +
        <template name="readonly">
 +
            <label value=${configElement.name}"/>
 +
        </template>
 +
    </apply>
 +
</forEach>
 +
 
 +
<!-- named external templates -->
 +
<forEach items="${someCollectionOfConfigElements}" var="configElement">
 +
    <apply template="${configElement.editable ? 'editable' : 'readonly'}">
 +
        <template name="editable" src="configElementEditor.zul"/>
 +
        <template name="readonly" src="configElementView.zul"/>
 +
    </apply>
 +
</forEach>
 +
 
 +
<!-- refer to external template directly -->
 +
<forEach items="${someCollectionOfConfigElements}" var="configElement">
 +
    <apply templateURI="${configElement.editable ? 'configElementEditor.zul' : 'configElementView.zul'}"/>
 +
</forEach>
 +
 
 +
</source>
  
 
=== control from java code (MVC) ===
 
=== control from java code (MVC) ===

Revision as of 11:04, 11 January 2017

DocumentationSmall Talks2017MarchZK8 Features for MVC - Shadow Elements - Part 2
ZK8 Features for MVC - Shadow Elements - Part 2

Author
Robert Wenzel, Engineer, Potix Corporation
Date
December 2016
Version
ZK 8.0

Introduction

In continuation of the previous article LINK ME I'll focus this time on the shadow element <forEach>.

Some background

The intention behind <forEach> are similar to those of the <apply> shadow element. Several historically evolved mechanisms to repeat UI components with their own specific behavior and limitations needed a unified abstraction to become more versatile and layout neutral (no additional DOM elements) at the same time.

Let's look at what's been there before:

(1) forEach-attribute

<div forEach="${someCollection}">
    <label value="${each.label}"/>
<div>
  • repeats the component as well
  • limited to static layouts at zul parse time

(2) ListModel

<listbox model="${someListModel}">
    <template name="model">
        <listitem label="${each.label}"/>
    </template>
</listbox>
  • allows replacing the whole Model => re-render all elements
  • allows adding/removing single elements => re-render only affected elements
  • supported only by specific components (grid/listbox/combobox/tabbox ...)

(3) children-binding restricted to MVVM

<div children="@init(someListModel)">
    <template name="children">
        <label value="${each.label}"/>
    </template>
</div>
  • repeats contained template
  • allows replacing the whole Model => re-render all elements
  • (before ZK 8) didn't update adding/removing single elements => needed to re-render all elements
  • requires MVVM / BindComposer

The examples above behave quite differently, each with its own limitations. All require a component: the special forEach-attribute repeats the element itself while the model- and children-binding repeat the inner template.

The new <forEach> shadow element allows static and dynamic UI composition. When used in combination with a ListModel implementation also single item updates (add/remove) result only in UI updates to the affected elements. This will improve the overall performance by saving network traffic and avoiding updates to existing DOM elements in the browser which saves render time. As with other shadow elements this works without adding additional container components. ZK will keep track of the individual positions in the component tree and DOM tree.

<forEach> usages

Here what the above examples (1, 3) will look like using <forEach> (<listbox> could be done in the same way but it is still more useful when binding the model-attribute to track the selected listitems in the ListModel as well)

<forEach items="${someCollection}">
    <div>
        <label value="${each.label}"/>
    <div>
</forEach>

<div>
    <forEach items="${someListModel}">
        <label value="${each.label}"/>
    </forEach>
</div>

By adding the shadow element you are now free to decide which component should be repeated by nesting accordingly.

<forEach> also supports multiple children (even a variable number of children/item) as in the example below. For "readonly" items there are 2 children while there will be 2 additional buttons otherwise.

<forEach items="${someListModel}">
    <label value="${each.label}"/>
    <button label="details" />
    <if test="${!each.readonly}">
        <button label="edit" />
        <button label="delete" />
    </if>
</forEach>

static usage (index, array, collection)

As other shadow elements the <forEach> can be used with a static EL expression (${some.expression}) resolving to a java Array or Collection (not implementing ListModel). In this case the shadow element will be removed after initial rendering to save the server side memory. The resulting component tree will only contain the actually generated components. To prevent the removal of the shadow element you can add dynamicValue="true" to preserve the shadow tree in order to manipulate it later.

dynamic usage (ListModel)

When using a dynamic bind expression (@load / @init) or a static EL resolving into a ListModel implementation the shadow element will remain in the shadow tree. Especially when used with a ListModel it will listen to changes in the ListModel and reflect the updates automatically. This allows convenient usage of the built-in ListModel implementations (e.g. ListModelList)

http://zkfiddle.org/sample/2cjibpn/1-ForEach-with-ListModel

Adding templates

The content of a <forEach> element will implicitly become an anonymous template, hence the following examples are equivalent and produce the same result, and shadow/component tree.

<forEach items="${someCollection}">
    <div>
        <label value="${each.label}"/>
    <div>
</forEach>

<forEach items="${someCollection}">
    <template>
        <div>
            <label value="${each.label}"/>
        <div>
    <template>
</forEach>

<forEach items="${someCollection}">
    <template name="">
        <div>
            <label value="${each.label}"/>
        <div>
    <template>
</forEach>

Since this is just typing overhead and doesn't add any value the <template> can be omitted (however it's not wrong to write it out explicitly if you prefer).

Dynamic Templates

Things become interesting when rendering items differently (e.g. based on a condition or property). For such cases the <apply> element can be nested inside the <forEach>.

<!-- named inline templates -->
<forEach items="${someCollectionOfConfigElements}" var="configElement">
    <apply template="${configElement.editable ? 'editable' : 'readonly'}">
        <template name="editable">
            <textbox value=${configElement.name}" forward="onChange=onChangeConfigElementName(${configElement})"/>
        </template>
        <template name="readonly">
            <label value=${configElement.name}"/>
        </template>
    </apply>
</forEach>

<!-- named external templates -->
<forEach items="${someCollectionOfConfigElements}" var="configElement">
    <apply template="${configElement.editable ? 'editable' : 'readonly'}">
        <template name="editable" src="configElementEditor.zul"/>
        <template name="readonly" src="configElementView.zul"/>
    </apply>
</forEach>

<!-- refer to external template directly -->
<forEach items="${someCollectionOfConfigElements}" var="configElement">
    <apply templateURI="${configElement.editable ? 'configElementEditor.zul' : 'configElementView.zul'}"/>
</forEach>

control from java code (MVC)

Summary

Comments



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