ZK8 Features for MVC - Shadow Elements - Part 1"

From Documentation
Line 81: Line 81:
 
   private Apply panelContent;
 
   private Apply panelContent;
 
</source>
 
</source>
* '''Line 1:''' wire by id using a shadow selector
+
* '''Line 1:''' wire by id using a [https://www.zkoss.org/wiki/ZK_Developer's_Reference/MVC/Controller/Wire_Components#Shadow_Selectors shadow selector]
  
 
=== <apply> with Templates ===
 
=== <apply> with Templates ===

Revision as of 09:07, 25 August 2016

DocumentationSmall Talks2016OctoberZK8 Features for MVC - Shadow Elements - Part 1
ZK8 Features for MVC - Shadow Elements - Part 1

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

WarningTriangle-32x32.png This page is under construction, so we cannot guarantee the accuracy of the content!


Introduction

ZK 8 added several new Features mainly improving Component control when using the MVVM design pattern. The question I sometimes heard since was: (How) Can we benefit from these features in our MVC application ?

To answer the question I'll start with the most prominent features which are:

  • shadow elements
  • form proxies

Let's have a look where they can be used in the MVC world.

If you are missing a feature let us know in the comments section below.

Shadow Elements in MVC

Some of the Shadow Elements LINK ME are more/less beneficial in MVC than others here a short summary

  • <if>
most useful when used with dynamic @load expressions in MVVM
in MVC you can attach/detach components directly (so this is nothing new for MVC)
used statically you can render parts of your UI based on a conditional EL expression <if test="${some.condition}">...</if>
  • <choose>, <when>, <otherwise>
similar to <if> no real benefit for MVC
  • <forEach>
very useful see paragraph below
  • <apply>
helps to compose the UI from ZUL fragments (more efficiently than <include>)
in java you could just call Executions.createComponents(...) LINK ME

Apply

For static UI composition an <include> such as this:

<include src="customerDetails.zul" customerId="123"/>

... can be replaced by an <apply> element:

<apply templateURI="customerDetails.zul" customerId="123"/>

The difference is that an <apply> does less things "under the hood" compared to <include>:

  • it does not create an additional
    in the resulting DOM
-> in fact it does not exist at the client side at all
  • it does not create a new namespace (you have to take care of that yourself if you need)
  • it does not have this automatic behavior of switching between "instant" and "defer" mode like an include
  • it does not create a nested Page object
  • it only supports zul/zhtml templates
  • parameters in the URI (e.g. some.zul?id=abc) are accessible via ${arg.id} variable instead of ${param.id}

Simpy spoken behaves like a call to Executions.createComponents(...).

To save memory the <apply> shadow element is even removed completely from the server side component (shadow) tree when used purely statically. The shadow elements are not removed when used with dynamic parameters. E.g.:

  • in MVVM using the ZKBIND anotations (@load/@init/@ref)
  • in MVC by adding the special attribute dynamicValue="true"

This is required if you want to wire the shadow element into your composer, e.g. to set the templateURI or parameters dynamically. LINK EXAMPLE BELOW

  <div>
    <apply id="panelContent"/>
  </div>
  • Line 2: assign an id in the zul file
  @Wire("::shadow#panelContent")
  private Apply panelContent;

<apply> with Templates

On top of the above <apply> can be used to insert templates at any point of your page. This can be useful when refactoring larger zul files in order to remove duplicate layout structures.

Here a repeated layout only differing by customer object and a label.

<zk>
    <div>
        <div sclass="customerBox">
            <div>Current Customer id: ${sessionScope.currentCustomer.id}</div>
            <div>Current Customer name: ${sessionScope.currentCustomer.name}</div>
        </div>
        <div sclass="customerBox">
            <div>Last Customer id: ${sessionScope.lastCustomer.id}</div>
            <div>Last Customer name: ${sessionScope.lastCustomer.name}</div>
        </div>
    </div>
</zk>

The repeated layout can be avoided by defining a template (customerBox) and apply the same template using different parameters.

<zk>
    <div>
        <apply template="customerBox" customer="${sessionScope.currentCustomer}" label="Current Customer"/>
        <apply template="customerBox" customer="${sessionScope.lastCustomer}"  label="Last Customer"/>
    </div>

    <template name="customerBox">
        <div sclass="customerBox">
            <div>${label} id: ${customer.id}</div>
            <div>${label} name: ${customer.name}</div>
        </div>
    </template>

    <!-- alternatively define the template content in a separate file
    <template name="customerBox" src="/WEB-INF/templates/customerBox.zul"/>
     -->
</zk>

As described above you can also apply the template directly using the templateURI.

        <apply templateURI="/WEB-INF/templates/customerBox.zul" customer="${sessionScope.currentCustomer}" label="Current Customer"/>

Or as a syntax sugar you can define a custom tag inside the page.

<?component name="customerBox" templateURI="/WEB-INF/templates/customerBox.zul"?>
<zk>
    <div>
        <customerBox customer="${sessionScope.currentCustomer}" label="Current Customer"/>
        <customerBox customer="${sessionScope.lastCustomer}"  label="Last Customer"/>
    </div>
</zk>

Finally you can declare the custom element globally in a lang-addon.xml, and omit the <?component ... ?> directive in the page.

    <component>
        <component-name>customerBox</component-name>
        <template-uri>/WEB-INF/templates/customerBox.zul</template-uri>
    </component>

ForEach

https://www.zkoss.org/wiki/ZK_Developer's_Reference/MVC/Controller/Wire_Components#Shadow_Selectors

CollectionTemplate

ZUL Template

Java Based Template

Using ZK8 Form Proxies in MVC

Creating a Simple CRUD Template

Summary

Download

  • The source code for this article can be found on github.

Running the Example

Clone the repository

  git clone [email protected]:zkoss-demo/mvc-shadow.git
  cd mvc-shadow
  git checkout master

The example war file can be built with maven:

   mvn clean package

Execute using jetty:

   mvn jetty:run

Then access the overview page http://localhost:8080/mvc-shadow/


Comments



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