The Trilogy of ZK's MVC Adventure

From Documentation
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
DocumentationSmall Talks2007NovemberThe Trilogy of ZK's MVC Adventure
The Trilogy of ZK's MVC Adventure

Author
Robbie Cheng, Engineer, Potix Corporation
Date
November 29, 2007
Version
Applicable to ZK 3.0.1 Freshly (zk-3.0.1-FL-2007-11-28 and later)


Introduction

MVC(Model-View-Controller) is a famous and good practice for web application development. Thus, we are always looking for the best practice for ZK to realize MVC approach perfectly. Finally, we come up with the idea of composer which allows you to separate view and controller clearly. Let’s review the history of improvement on realizing MVC approach.


The Day Before - Episode I

In the past, we used to teach developers to create a customized component as a controller, and then register related event listeners to invoke the controller as follows.

<!-- mvc1.zul -->
<window id="win" border="normal" width="350px" sizable="true" title="Demo" use="MyWindow">
 <button label="A" onClick="win.onSayA()"/>
 <button label="B" onClick="win.onSayB()"/>
 <button label="C" onClick="win.onSayC()"/>
 <button label="D" onClick="win.onSayD()"/>
 <button label="E" onClick="win.onSayE()"/>
 <separator/>
</window>

Then, creates a customized window component, and defines required event listener in it.

<!-- MyWindow.java -->
public class MyWindow extends Window{
 public void onSayA(){
  appendChild(new Label("A"));
 }
 public void onSayB(){
  appendChild(new Label("B"));
 }
 public void onSayC(){
  appendChild(new Label("C"));
 }
 public void onSayD(){
  appendChild(new Label("D"));
 }
 public void onSayE(){
  appendChild(new Label("E"));
 }
}

Thought it looks like intuitive, there are two drawbacks.

  • The performance is not good since those event listeners defined in ZUL page require additional execution time of BeanShell.
  • Those events are better to be processed in the window component instead of in those scattered-around button components.


Improve the Performance - Episode II

To overcome the above two problems, you can use the forward property to forward those events to the window component without registering event listeners in the ZUL page. If one of these buttons is clicked by the user, a corresponding event will be forwarded to the window component, and the corresponding event listener defined in the MyWindow Java file will be invoked.

<!-- mvc2.zul -->
<window id="win" border="normal" width="350px" sizable="true" title="Demo" use="MyWindow">
 <button label="A" forward="onSayA"/>
 <button label="B" forward="onSayB"/>
 <button label="C" forward="onSayC"/>
 <button label="D" forward="onSayD"/>
 <button label="E" forward="onSayE"/>
 <separator/>
</window>


Though this way looks much better than the former one, but here comes another problem. Is it appropriate to take the view (UI Components) as a controller? The answer depends on user's preference. Instead of making decision for you, ZK always enabled options for you. In the Episode I and II, we've showed you how to mix these two concepts together. And now, we are going to show you how to separate the controller from the view clearly, we come up the idea of composer.


Separate Controller from View - Episode III

To realize the MVC approach more gracefully, we need the help of composer and apply property.


Create a Composer as the Controller
The first job is to create a composer which must extend org.zkoss.zk.ui.util.GenericComposer, and then move those event listeners defined in window component to the composer as follows.
    <!-- MyComposer.java -->
    public class MyComposer extends GenericComposer{ 
     public void onSayA(Event evt){
      evt.getTarget().appendChild(new Label("A"));
     }
     public void onSayB(Event evt){
      evt.getTarget().appendChild(new Label("B"));
     }
     public void onSayC(Event evt){
      evt.getTarget().appendChild(new Label("C"));
     }
     public void onSayD(Event evt){
      evt.getTarget().appendChild(new Label("D"));
     }
     public void onSayE(Event evt){
      evt.getTarget().appendChild(new Label("E"));
     }
    }


Use apply property
Then, apply property is used to attach the composer to the window component. Those evens forwarded to the window component will be processed in the composer. So far, the job of controller is separated from the view clearly.
    <!-- mvc3.zul -->
    <window id="win" border="normal" width="350px" sizable="true" title="MVC Demo" apply="MyComposer">
     <button label="A" forward="onSayA"/>
     <button label="B" forward="onSayB"/>
     <button label="C" forward="onSayC"/>
     <button label="D" forward="onSayD"/>
     <button label="E" forward="onSayE"/>
     <separator/>
    </window>


Summary

So far, we believe this should be the best practice for ZK to realize MVC approach. However, we welcome your comments to make it better. If you come up with any idea, don’t hesitate to leave a comment.


Download the example code here.




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