Implementing ZK MVC"

From Documentation
m (correct highlight (via JWB))
 
(10 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 +
#REDIRECT [[ZK Essentials]]
 +
 
{{ZKEssentialsPageHeader}}
 
{{ZKEssentialsPageHeader}}
  
The MVC is developers' favorite pattern as it neatly separates various application layers in a clear manner. ZK fosters this process by allowing UI declaration to be done using an XML declarative language. It should be noted, however, that we can create Swing programmatic UIs using Richlets.
+
__TOC__
 +
 
 +
MVC is many developers' favorite pattern as it neatly separates various application layers in a clear manner. ZK fulfills the View component of MVC by allowing UI declaration to be done using an XML declarative language called ZUL.  In ZK the Model and Controller components revolve around <javadoc>org.zkoss.zk.ui.select.SelectorComposer</javadoc> and are tied to the View by the ZUL "apply" attribute.  The <javadoc>org.zkoss.zk.ui.select.SelectorComposer</javadoc> is a utility class which adds auto-wire functionality to provide access to UI objects (the View) from Java code (the Model and Controller) with very little effort
 +
 
 +
Let’s see a demonstration of how to add this functionality into the Login page.
  
ZK MVC revolves around two key items, the <javadoc>org.zkoss.zk.ui.util.GenericForwardComposer</javadoc> and the apply attribute. The <javadoc>org.zkoss.zk.ui.util.GenericForwardComposer</javadoc> is a utility class which adds auto-wire functionality to provide access to UI objects from Java code without any effort. Let’s see the demonstration of how to add  this functionality into the login page.
+
'''Note'''
 +
In ZK, the View component may also be fulfilled programmatically in Java code, in a manner very similar to Java Swing, by using <javadoc>org.zkoss.zk.ui.Richlet</javadoc> . {{Template:Help Request}} Need a Richlet example also.
  
  
===Creating a controller (GenericForwardComposed) & applying it===
+
===Creating and Applying a Controller (SelectorComposer)===
  
  
First, we need to create a controller class named LoginViewCtrl which extends from the <javadoc>org.zkoss.zk.ui.util.GenericForwardComposer</javadoc>, this is a trivial matter in Java.
+
First, we need to create a controller class named LoginViewCtrl which extends from the <javadoc>org.zkoss.zk.ui.select.SelectorComposer</javadoc>.  In Java code this is done as follows.
  
 
<source lang="java">
 
<source lang="java">
public class LoginViewCtrl extends GenericForwardComposer
+
public class LoginViewCtrl extends SelectorComposer<Window>
</source >
+
</source>
 +
 
 +
SelectorComposer requires a Control Type. In this example we used Window as the Control Type and thus the root component we will apply to the composer will be a Window. Developers can use any <javadoc>org.zkoss.zk.ui.Component</javadoc> as SelectorComposer's Control Type allowing the controller to work with any component as the root.
 
   
 
   
To create this class, we need to link it to our ZUL file. This has to be done by indicating the apply attribute.   
+
To create this class, we need to link it to our ZUL file. This has to be done by indicating the "apply" attribute with the extension of SelectorComposer we created above.   
  
<source lang="xml" high="4">
+
<source lang="xml" highlight="4">
 
<?page title="ZK Store - Login"?>
 
<?page title="ZK Store - Login"?>
<window id="loginWin" border="normal" width="300px"  
+
<window id="loginWin" border="normal" width="300px"
 
title="You are using: ${desktop.webApp.version}"
 
title="You are using: ${desktop.webApp.version}"
apply="demo.web.ui.ctrl.LoginViewCtrl">
+
apply="demo.web.ui.ctrl.LoginViewCtrl" mode="overlapped"
+
position="center,center">
 
<grid>
 
<grid>
 
<rows>
 
<rows>
<row> Name: <textbox id="nameTxb"/></row>
+
<row>
<row> Password:<textbox id="passwordTxb" type="password"/></row>
+
Name:
 +
<textbox id="nameTxb" />
 +
</row>
 +
<row>
 +
Password:
 +
<textbox id="passwordTxb" type="password" />
 +
</row>
 
</rows>
 
</rows>
 
</grid>
 
</grid>
<button id="confirmBtn" label="confirm"/>
+
<button id="confirmBtn" label="confirm" />
<label id="mesgLbl"/>
+
<label id="mesgLbl" />
 
</window>
 
</window>
</source >
+
</source>
  
As demonstrated in the code above, we set the apply attributes value to a full class name with path. In this case, it would be <mp>demo.web.ui.ctrl.LoginViewCtrl</mp>.
+
As demonstrated in the code above, we set the apply attributes value to a full class name with path. For the above this class would be <mp>demo.web.ui.ctrl.LoginViewCtrl</mp>.
  
===Auto-wiring components and events ===
+
===Auto-Wiring Components and Events ===
  
When the <javadoc>org.zkoss.zk.ui.util.GenericForwardComposer</javadoc> is applied, we can declare the components within the class as private variables which will be auto wired with the equivalent ZUL components.
+
When the <javadoc>org.zkoss.zk.ui.select.SelectorComposer</javadoc> is applied, we can declare the components within the class as private variables which will be auto wired with the equivalent ZUL components when the annotation @Wire is present.
  
<syntax lang="java" high="13,14,15">
+
<syntax lang="java" highlight="3,4,6,7">
import org.zkoss.zul.Label;
+
public class LoginViewCtrl extends SelectorComposer<Window> {
import org.zkoss.zul.Textbox;
+
 
+
@Wire
import demo.model.bean.User;
+
private Textbox nameTxb, passwordTxb;
import demo.web.UserCredentialManager;
+
 
+
@Wire
/**
 
* @author Ian Tsai
 
*
 
*/
 
public class LoginViewCtrl extends GenericForwardComposer {
 
 
 
private Textbox nameTxb;
 
private Textbox passwordTxb;
 
 
private Label mesgLbl;
 
private Label mesgLbl;
 
}
 
}
 
</syntax>
 
</syntax>
  
You can now access the UI components on the server-side and interact with them. All the wiring and communication is taken care of by ZK automatically.
+
You can now access the UI components on the server-side and interact with them. All the wiring and communication is taken care of by ZK automatically. There are many more advanced @Wire  options for more infomation on those please [[ZK_Developer's_Reference/MVC/Controller/Wire_Components | click here]].
  
The next step is to enable the capturing of events. In this specific case we need to capture the <mp>onClick</mp> event of the button <mp>confirmBtn</mp>. To do so, we need to create a method with a specific signature. In this case, we can use the event name followed by a $ and the component ID. The method signature is as follows:
+
The next step is to enable the capturing of events. In this specific case we need to capture the <mp>onClick</mp> event of the button <mp>confirmBtn</mp>. To do so, we need to create a method with a specific annotation. In this case, we can use the event name followed by a an = then a # to dictate that the component ID will come next then the component ID. The method is as follows:
  
 
<syntax lang="java">
 
<syntax lang="java">
public void onClick$confirmBtn()
+
@Listen("onClick=#confirmBtn")
 +
public void confirm() {
 +
doLogin();
 +
}
 
</syntax>
 
</syntax>
  
Notice that the method does not take any parameters, however, if necessary, the method can take an <javadoc>org.zkoss.zk.ui.event.Event</javadoc> object as a parameter or the subsequent subclass which is applicable to the context.
+
Notice that the method does not take any parameters, however, if necessary, the method can take an <javadoc>org.zkoss.zk.ui.event.Event</javadoc> object as a parameter or the subsequent subclass which is applicable to the context. The @Listen annotation takes a selector string, for more information on how to construct selectors please refer to [[ZK_Developer's_Reference/MVC/Controller/Wire_Event_Listeners | here]].
  
Lastly, we need to consider that people coming to the login.zul page may already be logged in just as our use case indicates. Therefore, we need to set up a mechanism that checks whether that is the case before loading the UI. This is done by overriding the <javadoc>org.zkoss.zk.ui.util.GenericForwardComposer</javadoc> method <javadoc method="doAfterCompose(org.zkoss.zk.ui.Component)">org.zkoss.zk.ui.util.GenericForwardComposer</javadoc> which would be called when the events and components are wired. Thus, if you override this method, please make sure to call the super method. At this stage, your <javadoc method="doAfterCompose(org.zkoss.zk.ui.Component)" class="false">org.zkoss.zk.ui.util.GenericForwardComposer</javadoc> method should look like this:
+
===The doAfterCompose Method===
 +
Lastly, we need to consider that people coming to the login.zul page may already be logged in just as our use case indicates. Therefore, we need to set up a mechanism that checks whether that is the case before loading the UI. This is done by overriding the <javadoc>org.zkoss.zk.ui.select.SelectorComposer</javadoc> method <javadoc method="doAfterCompose(org.zkoss.zk.ui.Component)">org.zkoss.zk.ui.select.SelectorComposer</javadoc> which would be called when the events and components are wired. Thus, if you override this method, please make sure to call the super method. At this stage, your <javadoc method="doAfterCompose(org.zkoss.zk.ui.Component)" class="false">org.zkoss.zk.ui.select.SelectorComposer</javadoc> method should look like this:
  
 
<syntax lang="java">
 
<syntax lang="java">
public void doAfterCompose(Component comp) throws Exception {
+
@Override
 +
public void doAfterCompose(Window comp) throws Exception {
 
super.doAfterCompose(comp);
 
super.doAfterCompose(comp);
  

Latest revision as of 12:32, 19 January 2022

Redirect to:

Stop.png This article is out of date, please refer to http://books.zkoss.org/zkessentials-book/master/ for more up to date information.


MVC is many developers' favorite pattern as it neatly separates various application layers in a clear manner. ZK fulfills the View component of MVC by allowing UI declaration to be done using an XML declarative language called ZUL. In ZK the Model and Controller components revolve around SelectorComposer and are tied to the View by the ZUL "apply" attribute. The SelectorComposer is a utility class which adds auto-wire functionality to provide access to UI objects (the View) from Java code (the Model and Controller) with very little effort

Let’s see a demonstration of how to add this functionality into the Login page.

Note

In ZK, the View component may also be fulfilled programmatically in Java code, in a manner very similar to Java Swing, by using Richlet .

InfoButton-32x32.png ZK Folks ! Help me !

Need a Richlet example also.


Creating and Applying a Controller (SelectorComposer)

First, we need to create a controller class named LoginViewCtrl which extends from the SelectorComposer. In Java code this is done as follows.

public class LoginViewCtrl extends SelectorComposer<Window>

SelectorComposer requires a Control Type. In this example we used Window as the Control Type and thus the root component we will apply to the composer will be a Window. Developers can use any Component as SelectorComposer's Control Type allowing the controller to work with any component as the root.

To create this class, we need to link it to our ZUL file. This has to be done by indicating the "apply" attribute with the extension of SelectorComposer we created above.

<?page title="ZK Store - Login"?>
<window id="loginWin" border="normal" width="300px"
	title="You are using: ${desktop.webApp.version}"
	apply="demo.web.ui.ctrl.LoginViewCtrl" mode="overlapped"
	position="center,center">
	<grid>
		<rows>
			<row>
				Name:
				<textbox id="nameTxb" />
			</row>
			<row>
				Password:
				<textbox id="passwordTxb" type="password" />
			</row>
		</rows>
	</grid>
	<button id="confirmBtn" label="confirm" />
	<label id="mesgLbl" />
</window>

As demonstrated in the code above, we set the apply attributes value to a full class name with path. For the above this class would be demo.web.ui.ctrl.LoginViewCtrl.

Auto-Wiring Components and Events

When the SelectorComposer is applied, we can declare the components within the class as private variables which will be auto wired with the equivalent ZUL components when the annotation @Wire is present.

<syntax lang="java" highlight="3,4,6,7"> public class LoginViewCtrl extends SelectorComposer<Window> {

@Wire private Textbox nameTxb, passwordTxb;

@Wire private Label mesgLbl; } </syntax>

You can now access the UI components on the server-side and interact with them. All the wiring and communication is taken care of by ZK automatically. There are many more advanced @Wire options for more infomation on those please click here.

The next step is to enable the capturing of events. In this specific case we need to capture the onClick event of the button confirmBtn. To do so, we need to create a method with a specific annotation. In this case, we can use the event name followed by a an = then a # to dictate that the component ID will come next then the component ID. The method is as follows:

<syntax lang="java"> @Listen("onClick=#confirmBtn") public void confirm() { doLogin(); } </syntax>

Notice that the method does not take any parameters, however, if necessary, the method can take an Event object as a parameter or the subsequent subclass which is applicable to the context. The @Listen annotation takes a selector string, for more information on how to construct selectors please refer to here.

The doAfterCompose Method

Lastly, we need to consider that people coming to the login.zul page may already be logged in just as our use case indicates. Therefore, we need to set up a mechanism that checks whether that is the case before loading the UI. This is done by overriding the SelectorComposer method SelectorComposer.doAfterCompose(Component) which would be called when the events and components are wired. Thus, if you override this method, please make sure to call the super method. At this stage, your doAfterCompose(Component) method should look like this:

<syntax lang="java"> @Override public void doAfterCompose(Window comp) throws Exception { super.doAfterCompose(comp);

//to be implemented, let’s check for a login } </syntax>

Now we have the insights of what advantages ZK provides us with by wiring the components, events, and data automatically. We need to move on to deal with our goal of implementing a user management system to check credentials and redirect it according to our use case. The next section walks you through how user credentials is implemented using a session.



Last Update : 2022/01/19

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