ZK composite component Example

Left hugThanks to benbai for helping me in the ZK Forum to complete this example.

This example shows how to create our own component using ZK Composite Component method.

Use case : Why and what is the ZK Composite Component. Well, assume that, in your project, there are similar screens and in each screen at the top , you need a display caption on the left hand side and on the right end corner, you need buttons such as “Save,” Cancel”, “Back”, etc.

Step 1: If you are new to ZK, then setup the Development environment by following this document.

Step 2:
Create a ZK Project and name as CompositeComp

image

image

image

Step 3:
Before creating our own component, let us see what we need to create and how should be our output. Copy the below code and paste in the index.zul file


<window>

<style>

.sectionTitleLabel.z-label {
font-size: 18px;
font-weight: bolder;
color: #0C6BA8;
}

.sectionTitle {
float: left;
padding-left: 20px;
}

.sectionSeperator {
margin-bottom: 18px;
padding-bottom: 0.25em;
margin-left: 20px;
border-bottom: 4px solid #DFDFDF
}

.mybutton.z-button .z-button-cm {
background-image: none;
color: white;
font-weight: bolder;
}

.mybutton.z-button .z-button-tm,.z-button .z-button-bm {
background-image: none;
}

.mybutton.z-button .z-button-cl,.z-button .z-button-cr {
background-image: none;
}

.mybutton.z-button .z-button-tl {
background-image: none;
}

.mybutton.z-button .z-button-bl {
background-image: none;
}

.mybutton.z-button .z-button-tr {
background-image: none;
}

.mybutton.z-button .z-button-br {
background-image: none;
}

.button {
display: inline-block;
zoom: 1; /* zoom and *display = ie7 hack for display:inline-block */
*display: inline;
vertical-align: baseline;
margin: 0 2px;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
font: 14px/100% Arial, Helvetica, sans-serif;
padding: .5em 2em .55em;
text-shadow: 0 1px 1px rgba(0, 0, 0, .3);
-webkit-border-radius: .5em;
-moz-border-radius: .5em;
border-radius: .5em;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
}

.button:hover {
text-decoration: none;
}

.button:active {
position: relative;
top: 1px;
}

.small {
font-size: 11px;
padding: .2em 1em .275em;
}

.blue {
color: #d9eef7;
border: solid 1px #0076a3;
background: #0095cd;
background: -webkit-gradient(linear, left top, left bottom, from(#00adee),
to(#0078a5) );
background: -moz-linear-gradient(top, #00adee, #0078a5);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee',
endColorstr='#0078a5' );
}

.blue:hover {
background: #007ead;
background: -webkit-gradient(linear, left top, left bottom, from(#0095cc),
to(#00678e) );
background: -moz-linear-gradient(top, #0095cc, #00678e);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0095cc',
endColorstr='#00678e' );
}

.blue:active {
color: #80bed6;
background: -webkit-gradient(linear, left top, left bottom, from(#0078a5),
to(#00adee) );
background: -moz-linear-gradient(top, #0078a5, #00adee);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0078a5',
endColorstr='#00adee' );
}

</style>
<div width="96%">
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label value="Registration" sclass="sectionTitleLabel" />
<separator />
</div>
</span>
<div style="float:right;margin-top:6px;">
<button mold="trendy" label="Cancel" sclass="mybutton button blue small " />
<button mold="trendy" label="Save" sclass="mybutton button blue small"/>
</div>
<div style="clear: both;"></div>
<div sclass="sectionSeperator"></div>
</div>
</window>

Now let us run the index.zul and the following is the output.
image

So as per our use case, we need to write the same set of code in each zul file to achieve the output. Instead of writing whole bunch of code again and again, let us create our component with necessary attributes.

Step 4:
First let us create the zul file called “header.zul” as shown in the figure.


image

image


Here is the content of the header.zul file



<div width="96%">

<style>

.sectionTitleLabel.z-label { font-size: 18px; font-weight:
bolder; color: #0C6BA8; }

.sectionTitle { float: left; padding-left: 20px; }

.sectionSeperator { margin-bottom: 18px; padding-bottom: 0.25em;
margin-left: 20px; border-bottom: 4px solid #DFDFDF }

.mybutton.z-button .z-button-cm { background-image: none; color:
white; font-weight: bolder; }

.mybutton.z-button .z-button-tm,.z-button .z-button-bm {
background-image: none; }

.mybutton.z-button .z-button-cl,.z-button .z-button-cr {
background-image: none; }

.mybutton.z-button .z-button-tl { background-image: none; }

.mybutton.z-button .z-button-bl { background-image: none; }

.mybutton.z-button .z-button-tr { background-image: none; }

.mybutton.z-button .z-button-br { background-image: none; }

.button { display: inline-block; zoom: 1; /* zoom and *display =
ie7 hack for display:inline-block */ *display: inline;
vertical-align: baseline; margin: 0 2px; outline: none; cursor:
pointer; text-align: center; text-decoration: none; font:
14px/100% Arial, Helvetica, sans-serif; padding: .5em 2em .55em;
text-shadow: 0 1px 1px rgba(0, 0, 0, .3); -webkit-border-radius:
.5em; -moz-border-radius: .5em; border-radius: .5em;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .2);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, .2); box-shadow: 0 1px
2px rgba(0, 0, 0, .2); }

.button:hover { text-decoration: none; }

.button:active { position: relative; top: 1px; }

.small { font-size: 11px; padding: .2em 1em .275em; }

.blue { color: #d9eef7; border: solid 1px #0076a3; background:
#0095cd; background: -webkit-gradient(linear, left top, left
bottom, from(#00adee), to(#0078a5) ); background:
-moz-linear-gradient(top, #00adee, #0078a5); filter:
progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee',
endColorstr='#0078a5' ); }

.blue:hover { background: #007ead; background:
-webkit-gradient(linear, left top, left bottom, from(#0095cc),
to(#00678e) ); background: -moz-linear-gradient(top, #0095cc,
#00678e); filter:
progid:DXImageTransform.Microsoft.gradient(startColorstr='#0095cc',
endColorstr='#00678e' ); }

.blue:active { color: #80bed6; background:
-webkit-gradient(linear, left top, left bottom, from(#0078a5),
to(#00adee) ); background: -moz-linear-gradient(top, #0078a5,
#00adee); filter:
progid:DXImageTransform.Microsoft.gradient(startColorstr='#0078a5',
endColorstr='#00adee' ); }

</style>
<span width="100%">
<div sclass="sectionTitle">
<separator />
<label id="lcaption" sclass="sectionTitleLabel" />
<separator />
</div>
</span>
<div id="buttonsDiv" style="float:right;margin-top:6px;">

</div>
<div style="clear: both;"></div>
<div sclass="sectionSeperator"></div>
</div>



As you can see, now we have removed the label caption (Left hand side) and also we have removed the buttons on the right hand side. We will pass what will be caption and what will be buttons to be display from the client zul file.

Step 5:
Next we will create the java class to support our own component. Create a class called “Header.java” in the package org.zkoss.zul.


package org.zkoss.zul;

import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.IdSpace;
import org.zkoss.zk.ui.ext.AfterCompose;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;

public class Header extends Div implements IdSpace, AfterCompose {

/**
*
*/
private static final long serialVersionUID = 1L;

@Wire
private Label lcaption;

@Wire
private Div buttonsDiv;

private String _buttons;

public Header() {
Executions.createComponents("header.zul", this, null);
Selectors.wireComponents(this, this, false);
Selectors.wireEventListeners(this, this);
}

@Override
public void afterCompose() {
createButtons();

}

public void createButtons() {
buttonsDiv.getChildren().clear();
for (String btn : _buttons.split(",")) {
Button button = new Button(btn.trim());
button.addForward("onClick", this, "onButtonsClick", btn.trim());
button.setParent(buttonsDiv);
button.setMold("trendy");
button.setSclass("mybutton button blue small");
Space space = new Space();
space.setSpacing("3px");
space.setParent(buttonsDiv);

}
}

public void setButtons(String buttons) {
_buttons = buttons;
}

public String getLcaption() {
return lcaption.getValue();
}

public void setLcaption(String lcaption) {
this.lcaption.setValue(lcaption);
}

}

As you can see, we have only two attributes such as What caption has to display in the left and how many buttons to be display on the right hand side. In the aftercompose, we are creating the buttons and also we are registering the event for those buttons.

That’s all, Now we are ready to use our own component.

Step 6:
Now we will use this newly created component in our index.zul file . Here is the simplified code of index.zul

<?page title="Auto Generated index.zul"?>
<!-- Composite component -->
<?component name="header" class="org.zkoss.zul.Header" ?>
<window apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('org.zkoss.zul.CompositeTestVM')">
<header lcaption="Registration" buttons="Cancel,Save" onButtonsClick="@command('buttonsClick')"></header>
</window>

And also using MVVM, we will handle button click event as follows



package org.zkoss.zul;

import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.zk.ui.event.ForwardEvent;

public class CompositeTestVM {

@Command
public void buttonsClick(
@ContextParam(ContextType.TRIGGER_EVENT) ForwardEvent event) {
Messagebox.show(" Button Clicked " + event.getData() + " " + event.getOrigin().getTarget() + " " + ((Button) event.getOrigin().getTarget()).getLabel());
}
}

Now you can run the index.zul to get the same output as follows
image


You can download the source here