Forms Explained (1)

On submit, Form does client-side validation that the TextFields satisfy @NotNull and
@Size(max=10). If it passes validation, then...

Form sends a component event request. It's an HTTP POST with a URL similar to
http://thehost/jumpstart/examples/input/forms1.names and this is how the server reacts:

Tapestry activates the page examples/input/forms1, and notifies the component names, which is a Form.

Form "bubbles up" a series of events: prepareForSubmit, validate, success (or failure), etc.

This page has handlers for two events: onValidateFromNames() and onSuccess().

Before onValidateFromNames() is triggered, Tapestry validates the TextFields satisfy @NotNull and @Size(max=10).

If onValidateFromNames() records an error, then the next event from the form will be failure, not success.

onSuccess() returns a page object, Page2.
Tapestry generates a page render request to Page2, and redirects the browser to it.

We don't have an onFailure(), so Tapestry will return the current page, complete with error messages.

Q: Why would Tapestry redirect the browser to Page2 instead of just rendering and returning Page2?
A: Tapestry uses the Post/Redirect/Get pattern.
The benefit of Post/Redirect/Get is that when the next page shows, its URL will NOT be the URL that triggered the event.
Instead, it will be a URL that is safe to reload, or bookmark, or return to with the Back button.
The cost is 2 trips to the server, but it's worth it.

Q: Why do we use the long method name onValidateFromNames() instead of just onValidate()?
A; To distinguish between validate bubbled up from Form and validate bubbled up from each TextField
(firstName and lastName). We explore this more in the example The Validate Event.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- We need a doctype to allow us to use special characters like &nbsp;
We use a "strict" DTD to make IE follow the alignment rules. -->
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<body class="container">
<h3>Forms Explained (1)</h3>
Here is a blow-by-blow explanation of the previous example.
<div class="eg">
<t:form t:id="names" class="form-horizontal">
<div class="form-group">
<t:label for="firstName" class="col-sm-2"/>
<div class="col-sm-4">
<t:textfield t:id="firstName"/>
</div>
</div>
<div class="form-group">
<t:label for="lastName" class="col-sm-2"/>
<div class="col-sm-4">
<t:textfield t:id="lastName"/>
</div>
</div>
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<t:submit/>
</div>
</div>
</t:form>
</div>
On submit, Form does <em>client-side validation</em> that the TextFields satisfy <code>@NotNull</code> and
<code>@Size(max=10)</code>. If it passes validation, then...<br/><br/>
Form sends a <strong>component event request</strong>. It's an HTTP POST with a URL similar to
<code>http://thehost/jumpstart/examples/input/forms1.names</code> and this is how the server reacts:<br/><br/>
<ul>
<li>Tapestry activates the page <em>examples/input/forms1</em>, and notifies the component <em>names</em>, which is a Form.</li>
<li>Form "bubbles up" a series of events: <em>prepareForSubmit</em>, <em>validate</em>, <em>success</em> (or <em>failure</em>), etc.</li>
<li>This page has handlers for two events: <code>onValidateFromNames()</code> and <code>onSuccess()</code>.</li>
<li>Before <code>onValidateFromNames()</code> is triggered, Tapestry validates the TextFields satisfy <code>@NotNull</code> and <code>@Size(max=10)</code>.</li>
<li>If <code>onValidateFromNames()</code> records an error, then the next event from the form will be <em>failure</em>, not <em>success</em>.</li>
<li><code>onSuccess()</code> returns a page object, <code>Page2</code>.
Tapestry generates a <strong>page render request</strong> to Page2, and redirects the browser to it.</li>
<li>We don't have an <code>onFailure()</code>, so Tapestry will return the current page, complete with error messages.</li>
</ul>
Q: Why would Tapestry <strong>redirect</strong> the browser to Page2 instead of just rendering and returning Page2?<br/>
A: Tapestry uses the <a href="http://en.wikipedia.org/wiki/Post/Redirect/Get">Post/Redirect/Get</a> pattern.
The benefit of Post/Redirect/Get is that when the next page shows, its URL will NOT be the URL that triggered the event.
Instead, it will be a URL that is safe to reload, or bookmark, or return to with the Back button.
The cost is 2 trips to the server, but it's worth it.<br/><br/>
Q: Why do we use the long method name <code>onValidateFromNames()</code> instead of just <code>onValidate()</code>? <br/>
A; To distinguish between <em>validate</em> bubbled up from Form and <em>validate</em> bubbled up from each TextField
(firstName and lastName). We explore this more in the example The Validate Event.<br/><br/>
References:
<a href="http://getbootstrap.com/css/#forms-horizontal">.form-horizontal</a>,
<a href="http://getbootstrap.com/css/#grid">.col-</a>,
<a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/Form.html">Form</a>,
<a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/TextField.html">TextField</a>,
<a href="http://tapestry.apache.org/5.4/apidocs/org/apache/tapestry5/corelib/components/Submit.html">Submit</a>,
<a href="http://tapestry.apache.org/forms-and-validation.html">Forms and Validation</a>,
<a href="http://tapestry.apache.org/bean-validation.html">Bean Validation</a>,
<a href="http://tapestry.apache.org/page-navigation.html">Page Navigation</a>,
<a href="http://tapestry.apache.org/component-events.html">Component Events</a>.<br/><br/>
<t:pagelink t:page="Index">Home</t:pagelink><br/><br/>
<t:tabgroup>
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/input/FormsExplained1.tml"/>
<t:sourcecodetab src="/web/src/main/java/jumpstart/web/pages/examples/input/FormsExplained1.java"/>
<t:sourcecodetab src="/web/src/main/resources/META-INF/assets/css/examples/plain.css"/>
</t:tabgroup>
</body>
</html>