blob: 72f542e1382de078eca2b87cf6855a1f4ed4711d [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<meta name="Author" content="Malcolm Edgar"/>
<meta name="description" lang="en" content="Apache Click Java web application framework"/>
<meta name="keywords" lang="en" content="Apache Click, Click Framework, Java, JEE, J2EE, web application framework, open source"/>
<title>Apache Click</title>
<link rel="stylesheet" type="text/css" href="../help.css"/>
<link rel="stylesheet" type="text/css" href="table.css"/>
<style type="text/css">
li {
margin-bottom: 0.75em;
}
</style>
</head>
<body>
<h1>Introduction</h1>
Click is a simple JEE web application framework for commercial Java developers.
<p>
Click is an open source project, licensed under the
<a href="LICENSE.txt">Apache</a> license.
<p>
Click uses an event based programming model for processing Servlet requests and
<a target='topic' href='velocity/velocity.html'>Velocity</a> for rendering
the response. (Note other template engines such as <a target="_blank" href="http://java.sun.com/products/jsp/">JSP</a>
and <a target="_blank" href="http://freemarker.sourceforge.net/">Freemarker</a> are also supported)
<p>
This framework uses a single servlet, called
<a target="topic" href="click-api/org/apache/click/ClickServlet.html">ClickServlet</a>, to
act as a request dispatcher. When a request arrives ClickServlet creates a
<a target="topic" href="click-api/org/apache/click/Page.html">Page</a> object to
process the request and then uses the page's Velocity template to render the
results.
<p>
Pages provide a simple thread safe programming environment, with a new
page instance created for each servlet request.
<p>
Possibly the best way to see how Click works is to dive right in and look at some
examples:
<ol>
<li><a href="#hello-world">Hello World</a> - the Hello World classic
</li>
<li><a href="#control-listener">Control Listener</a> - a ActionLink control listener example
</li>
<li><a href="#simple-table">Simple Table</a> - a simple Table control example
</li>
<li><a href="#advanced-table">Advanced Table</a> - a more advanced Table example
</li>
<li><a href="#simple-form">Simple Form</a> - a simple Form example
</li>
<li><a href="#advanced-form">Advanced Form</a> - a more advanced Form example
</li>
</ol>
These examples are available online at <a class="external" target="_blank" href="http://www.avoka.com/click-examples/">http://www.avoka.com/click-examples/</a>
under the menu "Intro Examples".
<p>&nbsp;</p>
<a name="hello-world" class="heading"></a><h2>1.&nbsp; Hello World Example</h2>
A Hello World example in Click would look something like this.
<p/>
First we create a <tt>HelloWorld</tt> page class:
<pre class="codeJava">
<span class="kw">package</span> <span class="red">examples.page</span>;
<span class="kw">import</span> java.util.Date;
<span class="kw">import</span> org.apache.click.Page;
<span class="kw">public</span> HelloWorld <span class="kw">extends</span> Page {
<span class="kw">public</span> Date <span class="st">time</span> = <span class="kw">new</span> Date();
}
</pre>
Next we have a page template <span class="blue">hello-world.htm</span>:
<pre class="codeHtml">
&lt;html&gt;
&lt;body&gt;
&lt;h2&gt;Hello World&lt;/h2&gt;
Hello world from Click at <span class="st">$time</span>
&lt;/body&gt;
&lt;/html&gt;
</pre>
Click is smart enough to figure out that the <tt>HelloWorld</tt> page class maps
to the template <span class="blue">hello-world.htm</span>. We only have to inform
Click of the <tt>package</tt> of the HelloWorld class, in this case <tt>examples.page</tt>.
<p/>
We do that through the
<a target='topic' href="configuration.html#application-configuration">click.xml</a>
configuration file which tells Click to map <span class="blue">hello-world.htm</span>
requests to our <tt>examples.page.HelloWorld</tt> page class.
<pre class="codeConfig">
&lt;click-app&gt;
&lt;pages package="<span class="red">examples.page</span>"/&gt;
&lt;/click-app&gt;
</pre>
<p/>
At runtime the ClickSerlvet maps a GET <span class="blue">hello-world.htm</span>
request to our page class <tt>example.page.HelloWorld</tt> and creates a new instance.
The HelloWorld page creates a new public <tt>Date</tt> object, which is automatically
added to the pages model using the fields name <span class="st">time</span>.
<p/>
The page model is then merged with the template which substitutes the
<span class="st">$time</span> parameter with the <tt>Date</tt> object.
Velocity then renders the merged template which looks something like
<table class="htmlExample" cellspacing="12">
<tr>
<td>
<h2 style="margin-top: 0em;">Hello World</h2>
Hello world from Click at Tue May 08 19:37:05 EST 2007
</td>
</tr>
</table>
<p>&nbsp;</p>
<a name="control-listener" class="heading"></a><h2>2.&nbsp; Control Listener Example</h2>
Click includes a library of <a target="topic" href="controls.html">Controls</a> which
provide user interface functionality.
<p/>
One of the commonly used controls is the
<a target="topic" href="click-api/org/apache/click/control/ActionLink.html">ActionLink</a>,
which you can use to have a HTML link call a method on a Page object. For example:
<pre class="codeJava">
<span class="kw">public class</span> ControlListenerPage <span class="kw">extends</span> Page {
<span class="kw">public</span> ActionLink myLink = <span class="kw">new</span> ActionLink();
<span class="kw">public</span> String msg;
<span class="cm">// ----------------------------------------------------------- Constructors
/**
* Create a new Page instance.
*/</span>
<span class="kw">public</span> ControlListenerPage() {
myLink.setListener(<span class="kw">this</span>, <span class="st">"onMyLinkClick"</span>);
}
<span class="cm">// --------------------------------------------------------- Event Handlers</span>
<span class="cm">/**
* Handle the myLink control click event.
*/</span>
<span class="kw">public boolean</span> onMyLinkClick() {
msg = <span class="st">"ControlListenerPage#"</span> + hashCode()
+ <span class="st">" object method &lt;tt&gt;onMyLinkClick()&lt;/tt&gt; invoked."</span>;
<span class="kw">return true</span>;
}
} </pre>
In the Page class we create an ActionLink called <span class="blue">myLink</span>
and define the control's listener to be the page method <tt>onMyLinkClick()</tt>.
When a user clicks on <span class="blue">myLink</span> control it will invoke the
listener method <tt>onMyLinkClick()</tt>.
<p/>
In Click a control listener method can have any name but it must return a boolean value.
The boolean return value specifies whether processing of page events should continue.
This control listener pattern provides a short hand way for wiring up action listener methods
without having to define anonymous inner classes.
<p/>
Back to our example, in the page template we define a HTML link and have the
<span class="blue">myLink</span> control render the link's href attribute:
<pre class="codeHtml">
&lt;html&gt;
&lt;head&gt;
&lt;link type="text/css" rel="stylesheet" href="style.css"&gt;&lt;/link&gt;
&lt;/head&gt;
&lt;body&gt;
Click myLink control &lt;a href="<span class="blue">$myLink.href</span>"&gt;here&lt;/a&gt;.
<span class="red">#if</span> (<span class="blue">$msg</span>)
&lt;div id="msgDiv"&gt; <span class="blue">$msg</span> &lt;/div&gt;
<span class="red">#end</span>
&lt;/body&gt;
&lt;/html&gt;
</pre>
At runtime this page would be rendered as:
<table class="htmlExample" cellspacing="12">
<tr>
<td>
Click myLink control <a href="/click-examples/introduction/control-listener.htm?actionLink=myLink">here</a>.
</td>
</tr>
</table>
When a user clicks on the link the <tt>onMyLinkClick()</tt> method is invoked. This
method then creates <span class="blue">msg</span> model value, which is rendered in the page as:
<table class="htmlExample" cellspacing="12">
<tr>
<td>
Click myLink control <a href="/click-examples/introduction/control-listener.htm?actionLink=myLink">here</a>.
<div class="msgDiv"> ControlListenerPage#12767107 object method <tt>onMyLinkClick()</tt> invoked. </div>
</td>
</tr>
</table>
<p>&nbsp;</p>
<a name="simple-table" class="heading"></a><h2>3.&nbsp; Simple Table Example</h2>
One of the most useful Click controls is the
<a target="topic" href="click-api/org/apache/click/control/Table.html">Table</a>
control.
<p/>
An example usage of the Table control in a customers Page is provided below:
<pre class="codeJava">
<span class="kw">public class</span> SimpleTablePage <span class="kw">extends</span> Page {
<span class="kw">public</span> Table <span class="st">table</span> = <span class="kw">new</span> Table();
<span class="cm">// ------------------------------------------------------------ Constructor</span>
<span class="kw">public</span> SimpleTablePage() {
table.setClass(Table.CLASS_ITS);
table.addColumn(<span class="kw">new</span> Column(<span class="st">"id"</span>));
table.addColumn(<span class="kw">new</span> Column(<span class="st">"name"</span>));
table.addColumn(<span class="kw">new</span> Column(<span class="st">"email"</span>));
table.addColumn(<span class="kw">new</span> Column(<span class="st">"investments"</span>));
}
<span class="cm">// --------------------------------------------------------- Event Handlers</span>
<span class="cm">/**
* @see Page#onRender()
*/</span>
<span class="kw">public void</span> onRender() {
List list = getCustomerService().getCustomersSortedByName(10);
table.setRowList(list);
}
} </pre>
In this Page code example a Table control is declared, we set the table's HTML class,
and then define a number of table <a target="topic" href="click-api/org/apache/click/control/Column.html">Column</a>
objects. In the column definitions we specify the name of the column in the constructor,
which is used for the table column header and also to specify the row object property
to render.
<p/>
The last thing we need to do is populate the table with data. To do this we override the
Page <tt>onRender()</tt> method and set the table row list before it is rendered.
<p/>
In our Page template we simply reference the <span class="blue">$table</span> object
which is rendered when its <tt>toString()</tt> method is called.
<pre class="codeHtml">
&lt;html&gt;
&lt;head&gt;
<span class="blue">$cssImports</span>
&lt;/head&gt;
&lt;body&gt;
<span class="blue">$table</span>
&lt;/body&gt;
&lt;/html&gt;
<span class="blue">$jsImports</span>
</pre>
Note above we also specify the <span class="blue">$cssImports</span> reference so the table can include any
CSS imports or styles in the header, and the <span class="blue">$jsImports</span> reference
any JavaScript imports or scripts at the bottom.
<p/>
At runtime the Table would be rendered in the page as:
<table class="htmlExample" cellspacing="12">
<tr>
<td>
<img src="../images/simple-table.png" border="0"/>
</td>
</tr>
</table>
<p>&nbsp;</p>
<a name="advanced-table" class="heading"></a><h2>4.&nbsp; Advanced Table Example</h2>
The Table control also provides support for:
<ul>
<li>automatic rendering</li>
<li>column formatting and custom rendering</li>
<li>automatic pagination</li>
<li>link control support</li>
</ul>
A more advanced Table example is provided below:
<pre class="codeJava">
<span class="kw">public class</span> CustomerPage <span class="kw">extends</span> Page {
<span class="kw">public</span> Table <span class="st">table</span> = <span class="kw">new</span> Table();
<span class="kw">public</span> PageLink editLink = <span class="kw">new</span> PageLink(<span class="st">"Edit"</span>, EditCustomer.<span class="kw">class</span>);
<span class="kw">public</span> ActionLink deleteLink = <span class="kw">new</span> ActionLink(<span class="st">"Delete"</span>, <span class="kw">this</span>, <span class="st">"onDeleteClick"</span>);
<span class="cm">// ------------------------------------- Constructor</span>
<span class="kw">public</span> CustomersPage() {
table.setClass(Table.<span class="st">CLASS_ITS</span>);
table.setPageSize(10);
table.setShowBanner(<span class="kw">true</span>);
table.setSortable(<span class="kw">true</span>);
table.addColumn(<span class="kw">new</span> Column(<span class="st">"id"</span>));
table.addColumn(<span class="kw">new</span> Column(<span class="st">"name"</span>));
Column column = <span class="kw">new</span> Column(<span class="st">"email"</span>);
column.setAutolink(<span class="kw">true</span>);
column.setTitleProperty(<span class="st">"name"</span>);
table.addColumn(column);
table.addColumn(<span class="kw">new</span> Column(<span class="st">"investments"</span>));
editLink.setImageSrc(<span class="st">"/images/table-edit.png"</span>);
editLink.setTitle(<span class="st">"Edit customer details"</span>);
editLink.setParameter(<span class="st">"referrer"</span>, <span class="st">"/introduction/advanced-table.htm"</span>);
deleteLink.setImageSrc(<span class="st">"/images/table-delete.png"</span>);
deleteLink.setTitle(<span class="st">"Delete customer record"</span>);
deleteLink.setAttribute(<span class="st">"onclick"</span>, <span class="st">"return window.confirm('Are you sure you want to delete this record?');"</span>);
column = <span class="kw">new</span> Column(<span class="st">"Action"</span>);
column.setTextAlign(<span class="st">"center"</span>);
AbstractLink[] links = <span class="kw">new</span> AbstractLink[] { editLink, deleteLink };
column.setDecorator(<span class="kw">new</span> LinkDecorator(table, links, <span class="st">"id"</span>));
column.setSortable(<span class="kw">false</span>);
table.addColumn(column);
}
<span class="cm">// ---------------------------------- Event Handlers</span>
<span class="cm">/**
* Handle the delete row click event.
*/</span>
<span class="kw">public boolean</span> onDeleteClick() {
Integer id = deleteLink.getValueInteger();
getCustomerService().deleteCustomer(id);
<span class="kw">return true</span>;
}
<span class="cm">/**
* @see Page#onRender()
*/</span>
<span class="kw">public void</span> onRender() {
List list = getCustomerService().getCustomersByName();
table.setRowList(list);
}
} </pre>
In this Page code example a Table control is declared and a number of
<a target="topic" href="click-api/org/apache/click/control/Column.html">Column</a>
objects are added. A deleteLink
<a target="topic" href="click-api/org/apache/click/control/ActionLink.html">ActionLink</a>
control is used as a decorator for the "Action" column. This control will invoke the
Page <tt>onDeleteClick()</tt> method when it is clicked. Finally we have the
Page <tt>onRender()</tt> method which is used to populate the Table control with
rows before it is rendered.
<p/>
In our Page template we simply reference the <span class="blue">$table</span> object
which is rendered when its <tt>toString()</tt> method is called.
<pre class="codeHtml">
&lt;html&gt;
&lt;head&gt;
<span class="blue">$cssImports</span>
&lt;/head&gt;
&lt;body&gt;
<span class="blue">$table</span>
&lt;/body&gt;
&lt;/html&gt;
<span class="blue">$jsImports</span>
</pre>
At runtime the Table would be rendered in the page as:
<table class="htmlExample" cellspacing="12">
<tr>
<td>
<img src="../images/advanced-table.png" border="0"/>
</td>
</tr>
</table>
In this example if a user click on the Delete link the <tt>onDeleteClick()</tt>
method will be called on the Page deleting the customer record.
<p>&nbsp;</p>
<a name="simple-form" class="heading"></a><h2>5.&nbsp; Simple Form Example</h2>
The <a target="topic" href="click-api/org/apache/click/control/Form.html">Form</a> and
<a target="topic" href="click-api/org/apache/click/control/Field.html">Field</a> controls
are also some of the most commonly used controls in the Click Framework.
<p/>
The SimpleForm page below provides a demonstration of using these controls.
<p/>
In our example code we have the page's constructor adding a
<a target="topic" href="click-api/org/apache/click/control/TextField.html">TextField</a> field and a
<a target="topic" href="click-api/org/apache/click/control/Submit.html">Submit</a> button to the form.
A page method is also set as a control listener on the form.
Also note in this example the page's public <span class="st">form</span> field is
automatically added to its list of controls.
<pre class="codeJava">
<span class="kw">public class</span> SimpleForm <span class="kw">extends</span> Page {
<span class="kw">public</span> Form <span class="st">form</span> = <span class="kw">new</span> Form();
<span class="kw">public</span> String msg;
<span class="cm">// ------------------------------------------------------------ Constructor</span>
<span class="kw">public</span> SimpleForm() {
form.add(<span class="kw">new</span> TextField(<span class="st">"name"</span>, <span class="kw">true</span>));
form.add(<span class="kw">new</span> Submit(<span class="st">"OK"</span>));
form.setListener(<span class="kw">this</span>, <span class="st">"onSubmit"</span>);
}
<span class="cm">// --------------------------------------------------------- Event Handlers</span>
<span class="cm">/**
* Handle the form submit event.
*/</span>
<span class="kw">public boolean</span> onSubmit() {
<span class="kw">if</span> (form.isValid()) {
msg = <span class="st">"Your name is "</span> + form.getFieldValue(<span class="st">"name"</span>);
}
<span class="kw">return true</span>;
}
}
</pre>
<p/>
Next we have the SimpleForm template <span class="blue">simple-form.htm</span>. The
Click application automatically associates the <tt>simple-form.htm</tt> template with
the <tt>SimpleForm</tt> class.
<pre class="codeHtml">
&lt;html&gt;
&lt;head&gt;
<span class="blue">$cssImports</span>
&lt;/head&gt;
&lt;body&gt;
<span class="blue">$form</span>
<span class="red">#if</span> (<span class="blue">$msg</span>)
&lt;div id="msgDiv"&gt; <span class="blue">$msg</span> &lt;/div&gt;
<span class="red">#end</span>
&lt;/body&gt;
&lt;/html&gt;
<span class="blue">$jsImports</span>
</pre>
When the SimpleForm page is first requested the <span class="blue">$form</span> object will
automatically render itself as:
<table class="htmlExample" cellspacing="12">
<tr>
<td>
<form method="post" name="form" id="form" action="/click-examples/introduction/simple-form.htm">
<input type="hidden" name="form_name" id="form_form_name" value="form"/>
<table class="form" id="form-form">
<tr><td>
<table class="fields" id="form-fields">
<tr class="fields">
<td class="fields" align="left"><label for="form_name">Name</label><span class="required">*</span></td>
<td align="left"><input type="text" name="name" id="form_name" value="" size="20"/></td>
</tr>
</table>
</td></tr>
<tr><td align="left">
<table class="buttons" id="form-buttons">
<tr class="buttons"><td class="buttons"><input type="submit" name="OK" id="form_OK" value="OK"/></td></tr>
</table>
</td></tr>
</table>
</form>
</td>
</tr>
</table>
Say the user does not enter their name and presses the OK button to submit the form.
The ClickServlet creates a new SimpleForm page and processes the form control.
<p/>
The form control processes its fields and determines that it is invalid. The form
then invokes the listener method <tt>onSubmit()</tt>. As the form is not
valid this method simply returns true and the form renders the field validation errors.
<table class="htmlExample" cellspacing="12">
<tr>
<td>
<form method="post" name="form" id="form" action="/click-examples/introduction/simple-form.htm">
<input type="hidden" name="form_name" id="form_form_name" value="form"/>
<table class="form" id="form-form">
<tr><td align="left">
<table class="errors" id="form-errors">
<tr class="errors"><td class="errors" align="left" colspan="2"><a class="error" href="#">You must enter a value for Name</a></td></tr>
</table>
</td></tr>
<tr><td>
<table class="fields" id="form-fields">
<tr class="fields">
<td class="fields" align="left"><label for="form_name" class="error">Name</label><span class="required">*</span></td>
<td align="left"><input type="text" name="name" id="form_name" value="" size="20" class="error"/></td>
</tr>
</table>
</td></tr>
<tr><td align="left">
<table class="buttons" id="form-buttons">
<tr class="buttons"><td class="buttons"><input type="submit" name="OK" id="form_OK" value="OK"/></td></tr>
</table>
</td></tr>
</table>
</form>
</td>
</tr>
</table>
Note the form will automatically maintain the entered state during the
post and validate cycle.
<p/>
Now if the user enters their name and clicks the OK button, the form will be
valid and the <tt>onSubmit()</tt> add a <span class="blue">msg</span> to the Pages
model. This will be rendered as:
<table class="htmlExample" cellspacing="12">
<tr>
<td>
<form method="post" name="form" id="form" action="/click-examples/introduction/simple-form.htm">
<input type="hidden" name="form_name" id="form_form_name" value="form"/>
<table class="form" id="form-form">
<tr><td>
<table class="fields" id="form-fields">
<tr class="fields">
<td class="fields" align="left"><label for="form_name">Name</label><span class="required">*</span></td>
<td align="left"><input type="text" name="name" id="form_name" value="John Masters" size="20"/></td>
</tr>
</table>
</td></tr>
<tr><td align="left">
<table class="buttons" id="form-buttons">
<tr class="buttons"><td class="buttons"><input type="submit" name="OK" id="form_OK" value="OK"/></td></tr>
</table>
</td></tr>
</table>
</form>
<div class="msgDiv"> Your name is John Masters </div>
</td>
</tr>
</table>
<p>&nbsp;</p>
<a name="advanced-form" class="heading"></a><h2>6.&nbsp; Advanced Form Example</h2>
The <tt>AdvancedForm</tt> page below provides a more advanced demonstration
of using Form, Field and FielsSet controls.
<p/>
First we have an <tt>AdvancedForm</tt> class which setups up a
<a href="click-api/org/apache/click/control/Form.html">Form</a>
in its constructor.
The form's investment
<a href="click-api/org/apache/click/control/Select.html">Select</a> list is populated
in the page's <tt>onInit()</tt> method. At this point any page dependencies such
as the CustomerService should be available.
<p/>
Note in this example the page's public <span class="st">form</span> field is
automatically added to its list of controls. The <span class="st">msg</span> field
is added to the page's model.
<pre class="codeJava">
<span class="kw">public class</span> AdvancedForm <span class="kw">extends</span> Page {
<span class="kw">public</span> Form form = <span class="kw">new</span> Form();
<span class="kw">public</span> String msg;
<span class="kw">private</span> Select investmentSelect = <span class="kw">new</span> Select(<span class="st">"investment"</span>);
<span class="cm">// ------------------------------------------------------------ Constructor</span>
<span class="kw">public</span> AdvancedForm() {
FieldSet fieldSet = <span class="kw">new</span> FieldSet(<span class="st">"Customer"</span>);
form.add(fieldSet);
TextField nameField = <span class="kw">new</span> TextField(<span class="st">"name"</span>, <span class="kw">true</span>);
nameField.setMinLength(5);
nameField.setFocus(true);
fieldSet.add(nameField);
fieldSet.add(<span class="kw">new</span> EmailField(<span class="st">"email"</span>, <span class="kw">true</span>));
fieldSet.add(investmentSelect);
fieldSet.add(<span class="kw">new</span> DateField(<span class="st">"dateJoined"</span>, <span class="kw">true</span>));
fieldSet.add(<span class="kw">new</span> Checkbox(<span class="st">"active"</span>));
form.add(<span class="kw">new</span> Submit(<span class="st">"ok"</span>, <span class="st">" OK "</span>, <span class="kw">this</span>, <span class="kw">"onOkClicked"</span>));
form.add(<span class="kw">new</span> Submit(<span class="st">"cancel"</span>, <span class="kw">this</span>, <span class="st">"onCancelClicked"</span>));
}
<span class="cm">// --------------------------------------------------------- Event Handlers
/**
* @see Page#onInit()
*/</span>
<span class="kw">public void</span> onInit() {
CustomerService customerService = getCustomerService();
investmentSelect.add(Option.EMPTY_OPTION);
investmentSelect.addAll(customerService.getInvestmentCatetories());
}
<span class="cm">/**
* Handle the OK button click event.
*
* @return true
*/</span>
<span class="kw">public boolean</span> onOkClicked() {
<span class="kw">if</span> (form.isValid()) {
Customer customer = <span class="kw">new</span> Customer();
form.copyTo(customer);
getCustomerService().saveCustomer(customer);
form.clearValues();
msg = <span class="st">"A new customer record has been created."</span>;
}
<span class="kw">return true</span>;
}
<span class="cm">/**
* Handle the Cancel button click event.
*
* @return false
*/</span>
<span class="kw">public boolean</span> onCancelClicked() {
setRedirect(HomePage.<span class="kw">class</span>);
<span class="kw">return false</span>;
}
}
</pre>
Next we have the AdvancedForm template <span class="blue">advanced-form.htm</span>. The
Click application automatically associates the <tt>advanced-form.htm</tt> template with
the <tt>AdvancedForm</tt> class.
<pre class="codeHtml">
&lt;html&gt;
&lt;head&gt;
<span class="blue">$cssImports</span>
&lt;/head&gt;
&lt;body&gt;
<span class="red">#if</span> (<span class="blue">$msg</span>)
&lt;div id="msgDiv"&gt; <span class="blue">$msg</span> &lt;/div&gt;
<span class="red">#end</span>
<span class="blue">$form</span>
&lt;/body&gt;
&lt;/html&gt;
<span class="blue">$jsImports</span>
</pre>
When the AdvancedForm page is first requested the <span class="blue">$form</span> object will
automatically render itself as:
<table class="htmlExample" cellspacing="12">
<tr>
<td>
<form method="post" name="form" id="form" action="/click-examples/introduction/advanced-form.htm">
<input type="hidden" name="form_name" id="form_form_name" value="form"/>
<table class="form" id="form-form">
<tr><td>
<table class="fields" id="form-fields">
<tr class="fields">
<td class="fields" colspan="2">
<fieldset id="form_Customer">
<legend id="form_Customer-legend">Customer</legend>
<table class="fields" id="form_Customer-fields">
<tr class="fields">
<td class="fields" align="left"><label for="form_name">Name</label><span class="required">*</span></td>
<td align="left"><input type="text" name="name" id="form_name" value="" size="20"/></td>
</tr>
<tr class="fields">
<td class="fields" align="left"><label for="form_email">Email</label><span class="required">*</span></td>
<td align="left"><input type="text" name="email" id="form_email" value="" size="30"/></td>
</tr>
<tr class="fields">
<td class="fields" align="left"><label for="form_investment">Investment</label>&nbsp;</td>
<td align="left"><select name="investment" id="form_investment" size="1"><option selected="selected" value=""></option><option value="Bonds">Bonds</option><option value="Commerical Property">Commerical Property</option><option value="Options">Options</option><option value="Residential Property">Residential Property</option><option value="Stocks">Stocks</option></select></td>
</tr>
<tr class="fields">
<td class="fields" align="left"><label for="dateJoined_field">Date Joined</label><span class="required">*</span></td>
<td align="left"><input type="text" name="dateJoined" id="dateJoined_field" value="" size="20"/></td>
</tr>
<tr class="fields">
<td class="fields" align="left"><label for="form_active">Active</label>&nbsp;</td>
<td align="left"><input type="checkbox" name="active" id="form_active"/></td>
</tr>
</table>
</fieldset>
</td>
</tr>
</table>
</td></tr>
<tr><td align="left">
<table class="buttons" id="form-buttons">
<tr class="buttons"><td class="buttons"><input type="submit" name="ok" id="form_ok" value=" OK "/></td><td class="buttons"><input type="submit" name="cancel" id="form_cancel" value="Cancel"/></td></tr>
</table>
</td></tr>
</table>
</form>
</td>
</tr>
</table>
In this example when the OK button is clicked the <tt>onOkClicked()</tt> method is invoked.
If the form is valid a new customer object is created and the forms field values are copied
to the new object using the Form
<a href="click-api/org/apache/click/control/Form.html#copyTo(java.lang.Object)">copyTo()</a>
method. The customer object is then saved, the form's field values are cleared and an
info message is presented to the user.
<p/>
If the user clicks on the Cancel button the request is redirected to the applications
HomePage.
<h3>6.1&nbsp; Form Layout</h3>
In the example above the Form control automatically renders the form and the fields
HTML markup. This is a great feature for quickly building screens, and the form control
provides a number of layout options. See the Click <a href="examples.html">Examples</a> for an
interactive Form Properties demo.
<p/>
For fine grained page design you can specifically layout form and fields in
your page template. See the <a href="controls.html#template-layout">Template Layout</a>
section and <a href="click-api/org/apache/click/control/Form.html#form-layout">Form</a>
Javadoc for more details.
<p/>
An alternative approach to page template design is using a programmatic approach.
See the <a href="controls.html#programmatic-layout">Programmatic Layout</a> section for more details.
</body>
</html>