tapestry-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From build...@apache.org
Subject svn commit: r894787 - in /websites/production/tapestry/content: cache/main.pageCache exploring-the-project.html using-beaneditform-to-create-user-forms.html
Date Sun, 19 Jan 2014 22:20:55 GMT
Author: buildbot
Date: Sun Jan 19 22:20:55 2014
New Revision: 894787

Log:
Production update by buildbot for tapestry

Modified:
    websites/production/tapestry/content/cache/main.pageCache
    websites/production/tapestry/content/exploring-the-project.html
    websites/production/tapestry/content/using-beaneditform-to-create-user-forms.html

Modified: websites/production/tapestry/content/cache/main.pageCache
==============================================================================
Binary files - no diff available.

Modified: websites/production/tapestry/content/exploring-the-project.html
==============================================================================
--- websites/production/tapestry/content/exploring-the-project.html (original)
+++ websites/production/tapestry/content/exploring-the-project.html Sun Jan 19 22:20:55 2014
@@ -364,7 +364,7 @@ var footnoteMarkerHighlight = function(i
 
 
 
-<span class="gliffy-container" id="gliffy-container-24346949-4298" data-fullwidth="913"
data-ceoid="24188263" data-filename="Templates and Parameters">
+<span class="gliffy-container" id="gliffy-container-24346949-3268" data-fullwidth="913"
data-ceoid="24188263" data-filename="Templates and Parameters">
 
             
 <span class="gliffy-chrome-container">
@@ -384,11 +384,11 @@ var footnoteMarkerHighlight = function(i
             </span>
 </span>
     
-    <map id="gliffy-map-24346949-5266" name="gliffy-map-24346949-5266"></map>
+    <map id="gliffy-map-24346949-1156" name="gliffy-map-24346949-1156"></map>
 
-    <img class="gliffy-image gliffy-image-border" id="gliffy-image-24346949-4298" width="304"
height="300" data-full-width="913" data-full-height="901" src="https://cwiki.apache.org/confluence/download/attachments/24188263/Templates%20and%20Parameters.png?version=2&amp;modificationDate=1371888025000&amp;api=v2"
usemap="#gliffy-map-24346949-5266">
+    <img class="gliffy-image gliffy-image-border" id="gliffy-image-24346949-3268" width="304"
height="300" data-full-width="913" data-full-height="901" src="https://cwiki.apache.org/confluence/download/attachments/24188263/Templates%20and%20Parameters.png?version=2&amp;modificationDate=1371888025000&amp;api=v2"
usemap="#gliffy-map-24346949-1156">
 
-    <map class="gliffy-dynamic" id="gliffy-dynamic-map-24346949-4298" name="gliffy-dynamic-map-24346949-4298"></map>
+    <map class="gliffy-dynamic" id="gliffy-dynamic-map-24346949-3268" name="gliffy-dynamic-map-24346949-3268"></map>
 </span>
 
 
@@ -401,7 +401,7 @@ var footnoteMarkerHighlight = function(i
     return &quot;A great day to learn Tapestry&quot;;
   }
 ]]></script>
-</div></div><p>Make sure you save changes; then click the refresh link
in the web browser:</p><p><img class="confluence-embedded-image confluence-thumbnail"
src="exploring-the-project.thumbs/app-live-reload.png" data-image-src="/confluence/download/attachments/24188263/app-live-reload.png?version=2&amp;modificationDate=1321974913000&amp;api=v2"></p><div
class="navmenu" style="float:right; width:30%; background:white; margin:3px; padding:3px">
+</div></div><p>Make sure you save changes; then click the refresh link
in the web browser:</p><p><img class="confluence-embedded-image" width="700"
src="https://cwiki.apache.org/confluence/download/attachments/24188263/app-live-reload.png?version=2&amp;modificationDate=1321974913000&amp;api=v2"
data-image-src="/confluence/download/attachments/24188263/app-live-reload.png?version=2&amp;modificationDate=1321974913000&amp;api=v2"></p><div
class="navmenu" style="float:right; width:30%; background:white; margin:3px; padding:3px">
     <div class="aui-message warning shadowed information-macro">
                             <span class="aui-icon icon-warning">Icon</span>
                 <div class="message-content">
@@ -409,7 +409,7 @@ var footnoteMarkerHighlight = function(i
 <p>If Live Class Reloading isn't working for you, check the Troubleshooting section
at <a shape="rect" href="class-reloading.html" title="Class Reloading">Class Reloading</a>.</p>
                     </div>
     </div>
-</div><p>This is one of Tapestry's early <em>wow factor</em> features:
changes to your component classes are picked up immediately (a feature we call Live Class
Reloading). No restart. No re-deploy. Make the changes and see them <em>now</em>.
Nothing should slow you down or get in the way of you getting your job done.</p><p>But
... what if you make a mistake? What if you got the name in the template wrong. Give it a
try; in the template, change ${currentTime} to, say, ${currenTime}, and see what you get:</p><p><img
class="confluence-embedded-image confluence-thumbnail" src="exploring-the-project.thumbs/app-error-1.png"
data-image-src="/confluence/download/attachments/24188263/app-error-1.png?version=1&amp;modificationDate=1291068475000&amp;api=v2"></p><p>This
is Tapestry's exception report page. It's quite detailed. It clearly identifies what Tapestry
was doing, and relates the problem to a specific line in the template, which is shown in context.
Tapestry always expands out the ent
 ire stack of exceptions, because it is so common for exceptions to be thrown, caught, and
re-thrown inside other exceptions. In fact, if we scroll down just a little bit, we see more
detail about this exception, plus a little bit of help:</p><p><img class="confluence-embedded-image
confluence-thumbnail" src="exploring-the-project.thumbs/app-error-2.png" data-image-src="/confluence/download/attachments/24188263/app-error-2.png?version=1&amp;modificationDate=1291068475000&amp;api=v2"></p><p>This
is part of Tapestry's way: it not only spells out exactly what it was doing and what went
wrong, but it even helps you find a solution; here it tells you the names of properties you
could have used.</p><p>Tapestry displays the stack trace of the deepest exception,
along with lots of details about the run-time environment: details about the current request,
the HttpSession (if one exists), and even a detailed list of all JVM system properties. Scroll
down to see all this information.</p>    <di
 v class="aui-message hint shadowed information-macro">
+</div><p>This is one of Tapestry's early <em>wow factor</em> features:
changes to your component classes are picked up immediately (a feature we call Live Class
Reloading). No restart. No re-deploy. Make the changes and see them <em>now</em>.
Nothing should slow you down or get in the way of you getting your job done.</p><p>But
... what if you make a mistake? What if you got the name in the template wrong. Give it a
try; in the template, change ${currentTime} to, say, ${currenTime}, and see what you get:</p><p><img
class="confluence-embedded-image" width="700" src="https://cwiki.apache.org/confluence/download/attachments/24188263/app-error-1.png?version=1&amp;modificationDate=1291068475000&amp;api=v2"
data-image-src="/confluence/download/attachments/24188263/app-error-1.png?version=1&amp;modificationDate=1291068475000&amp;api=v2"></p><p>This
is Tapestry's exception report page. It's quite detailed. It clearly identifies what Tapestry
was doing, and relates the problem to a specific 
 line in the template, which is shown in context. Tapestry always expands out the entire stack
of exceptions, because it is so common for exceptions to be thrown, caught, and re-thrown
inside other exceptions. In fact, if we scroll down just a little bit, we see more detail
about this exception, plus a little bit of help:</p><p><img class="confluence-embedded-image"
width="700" src="https://cwiki.apache.org/confluence/download/attachments/24188263/app-error-2.png?version=1&amp;modificationDate=1291068475000&amp;api=v2"
data-image-src="/confluence/download/attachments/24188263/app-error-2.png?version=1&amp;modificationDate=1291068475000&amp;api=v2"></p><p>This
is part of Tapestry's way: it not only spells out exactly what it was doing and what went
wrong, but it even helps you find a solution; here it tells you the names of properties you
could have used.</p><p>Tapestry displays the stack trace of the deepest exception,
along with lots of details about the run-time environment: detail
 s about the current request, the HttpSession (if one exists), and even a detailed list of
all JVM system properties. Scroll down to see all this information.</p>    <div class="aui-message
hint shadowed information-macro">
                             <span class="aui-icon icon-hint">Icon</span>
                 <div class="message-content">
                             <p>This level of detail reflects that the application has
been configured to run in <em>development mode</em> instead of <em>production
mode</em>. In production mode, the exception report would simply be the top level exception
message. However, most production applications go further and customize how Tapestry handles
and reports exceptions.</p>

Modified: websites/production/tapestry/content/using-beaneditform-to-create-user-forms.html
==============================================================================
--- websites/production/tapestry/content/using-beaneditform-to-create-user-forms.html (original)
+++ websites/production/tapestry/content/using-beaneditform-to-create-user-forms.html Sun
Jan 19 22:20:55 2014
@@ -86,23 +86,14 @@ import com.example.tutorial.data.Honorif
 public class Address
 {
   public Honorific honorific;
-
   public String firstName;
-
   public String lastName;
-
   public String street1;
-
   public String street2;
-
   public String city;
-
   public String state;
-
   public String zip;
-
   public String email;
-
   public String phone;
 }
 ]]></script>
@@ -137,7 +128,20 @@ public class CreateAddress
 
 }
 ]]></script>
-</div></div><p>So ... why is the class named "CreateAddress" and not simply
"Create"? Actually, we could have named it "Create", and the application would still work,
but the longer <em>class</em> name is equally valid. Tapestry noticed the redundancy
in the class name (com.example.tutorial.pages.<code><em>address</em></code>.Create<em>Address</em>)
and just stripped out the redundant suffix</p>&lt;style type='text/css'&gt;
+</div></div><p>So ... why is the class named "CreateAddress" and not simply
"Create"? Actually, we could have named it "Create", and the application would still work,
but the longer <em>class</em> name is equally valid. Tapestry noticed the redundancy
in the class name (com.example.tutorial.pages.<code><em>address</em></code>.Create<em>Address</em>)
and just stripped out the redundant suffix. <span style="line-height: 1.4285715;">Tapestry
also checks for redundant prefixes. In addition, the long name, "address/CreateAddress" would
also work.</span></p><p>Eventually, your application will probably have
more entities: perhaps you'll have a "user/Create" page and a "payment/Create" page and an
"account/Create" page. You <em>could</em> have a bunch of different classes all
named Create spread across a number of different packages. That's legal Java, but it isn't
ideal. You may find yourself accidentally editing the Java code for creating an Account when
your really want to be editing th
 e code for creating a Payment.</p><p>Tapestry is encouraging you to use a more
descriptive name: Create<em>Address</em>, not just Create, but it isn't making
you pay the cost (in terms of longer, uglier URLs). The URL to access the page will still
be <a shape="rect" class="external-link" href="http://localhost:8080/tutorial1/address/create"
>http://localhost:8080/tutorial1/address/create</a>.</p><p>And remember,
regardless of the name that Tapestry assigns to your page, the template file is named like
the Java class itself: CreateAddress.tml.</p>    <div class="aui-message hint shadowed
information-macro">
+                            <span class="aui-icon icon-hint">Icon</span>
+                <div class="message-content">
+                            <p>Index pages work in folders as well. A class named com.example.tutorial.pages.address.AddressIndex
would be given the name "address/Index". However, Tapestry has special rules for pages named
"Index" and the rendered URL would be <a shape="rect" class="external-link" href="http://localhost:8080/tutorial1/address/"
>http://localhost:8080/tutorial1/address/</a>. In other words, you can place Index
pages in any folder and Tapestry will build a short URL for that page ... and you <em>don't</em>
have to keep naming the classes Index (it's confusing to have many classes with the same name,
even across multiple packages); instead, you can name each index page after the package that
contains it. Tapestry users a smart <em>convention</em> to keep it all straight
and generate short, to the point URLs.</p>
+                    </div>
+    </div>
+<h1 id="UsingBeanEditFormToCreateUserForms-UsingtheBeanEditFormComponent">Using the
BeanEditForm Component</h1><p>Time to start putting together the logic for this
form. Tapestry has a specific component for client-side Forms: the <a shape="rect" class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html">Form</a>
component, as well as components for form controls, such as <a shape="rect" class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checkbox.html">Checkbox</a>
and <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/TextField.html">TextField</a>.
We'll cover those in a bit more detail later .. instead, we're again going to let Tapestry
do the heavy lifting for us, via the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/coreli
 b/components/BeanEditForm.html">BeanEditForm</a> component.</p><p>Add
the following to the CreateAddress template (replacing the "coming soon ..." message):</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader
pdl" style="border-bottom-width: 1px;"><b>CreateAddress.tml (partial)</b></div><div
class="codeContent panelContent pdl">
+<script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[
 &lt;t:beaneditform object=&quot;address&quot;/&gt;
+]]></script>
+</div></div><p>And match that up with a property in the CreateAddress class:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader
pdl" style="border-bottom-width: 1px;"><b>CreateAddress.java (partial)</b></div><div
class="codeContent panelContent pdl">
+<script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[
 @Property
+  private Address address;
+]]></script>
+</div></div><p>When you refresh the page, you'll see the following:</p><p><img
class="confluence-embedded-image" width="700" src="https://cwiki.apache.org/confluence/download/attachments/23340431/create-address-initial.png?version=1&amp;modificationDate=1291927518000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/create-address-initial.png?version=1&amp;modificationDate=1291927518000&amp;api=v2"></p><p>Tapestry's
done quite a bit of work here. It has created a form that includes a field for each property.
Further, its seen that the honorific property is an enumerated type, and presented that as
a drop-down list.</p><p>In addition, Tapestry has converted the property names
("city", "email", "firstName") to user presentable labels ("City", "Email", "First Name").
In fact, these are &lt;label&gt; elements, so clicking a label with the mouse will
move the input cursor into the corresponding field.</p><p>This is an awesome start;
it's a presentable interface, quite
  nice in fact for a few minute's work. But it's far from perfect; let's get started with
some customizations.</p><h1 id="UsingBeanEditFormToCreateUserForms-ChangingFieldOrder">Changing
Field Order</h1><p>The BeanEditForm must guess at the right order to present the
fields; for public fields, they end up in alphabetical order</p>&lt;style type='text/css'&gt;
 .FootnoteMarker, .FootnoteNum a {
   background: transparent url(/confluence/download/resources/com.adaptavist.confluence.footnoteMacros:footnote/gfx/footnote.png)
no-repeat top right;
   padding: 1px 2px 0px 1px;
@@ -209,36 +213,17 @@ var footnoteMarkerHighlight = function(i
             1
     </a>
 </sup>
-<p>.</p><p>&#160;</p><p>Eventually, your application will
probably have more entities: perhaps you'll have a "user/Create" page and a "payment/Create"
page and an "account/Create" page. You <em>could</em> have a bunch of different
classes all named Create spread across a number of different packages. That's legal Java,
but it isn't ideal. You may find yourself accidentally editing the Java code for creating
an Account when your really want to be editing the code for creating a Payment.</p><p>Tapestry
is encouraging you to use a more descriptive name: Create<em>Address</em>, not
just Create, but it isn't making you pay the cost (in terms of longer, uglier URLs). The URL
to access the page will still be <a shape="rect" class="external-link" href="http://localhost:8080/tutorial1/address/create"
>http://localhost:8080/tutorial1/address/create</a>.</p><p>And remember,
regardless of the name that Tapestry assigns to your page, the template file is named like
the Java class itself: CreateA
 ddress.tml.</p>    <div class="aui-message hint shadowed information-macro">
-                            <span class="aui-icon icon-hint">Icon</span>
-                <div class="message-content">
-                            <p>Index pages work in folders as well. A class named com.example.tutorial.pages.address.AddressIndex
would be given the name "address/Index". However, Tapestry has special rules for pages named
"Index" and the rendered URL would be <a shape="rect" class="external-link" href="http://localhost:8080/tutorial1/address/"
>http://localhost:8080/tutorial1/address/</a>. In other words, you can place Index
pages in any folder and Tapestry will build a short URL for that page ... and you <em>don't</em>
have to keep naming the classes Index (it's confusing to have many classes with the same name,
even across multiple packages); instead, you can name each index page after the package that
contains it. Tapestry users a smart <em>convention</em> to keep it all straight
and generate short, to the point URLs.</p>
-                    </div>
-    </div>
-<h1 id="UsingBeanEditFormToCreateUserForms-UsingtheBeanEditFormComponent">Using the
BeanEditForm Component</h1><p>Time to start putting together the logic for this
form. Tapestry has a specific component for client-side Forms: the <a shape="rect" class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html">Form</a>
component, as well as components for form controls, such as <a shape="rect" class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Checkbox.html">Checkbox</a>
and <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/TextField.html">TextField</a>.
We'll cover those in a bit more detail later .. instead, we're again going to let Tapestry
do the heavy lifting for us, via the <a shape="rect" class="external-link" href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/coreli
 b/components/BeanEditForm.html">BeanEditForm</a> component.</p><p>Add
the following to the CreateAddress template (replacing the "coming soon ..." message):</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader
pdl" style="border-bottom-width: 1px;"><b>CreateAddress.tml (partial)</b></div><div
class="codeContent panelContent pdl">
-<script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[
 &lt;t:beaneditform object=&quot;address&quot;/&gt;
-]]></script>
-</div></div><p>And match that up with a property in the CreateAddress class:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader
pdl" style="border-bottom-width: 1px;"><b>CreateAddress.java (partial)</b></div><div
class="codeContent panelContent pdl">
-<script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[
 @Property
-  private Address address;
-]]></script>
-</div></div><p>When you refresh the page, you'll see the following:</p><p><img
class="confluence-embedded-image confluence-thumbnail" src="using-beaneditform-to-create-user-forms.thumbs/create-address-initial.png"
data-image-src="/confluence/download/attachments/23340431/create-address-initial.png?version=1&amp;modificationDate=1291927518000&amp;api=v2"></p><p>Tapestry's
done quite a bit of work here. It has created a form that includes a field for each property.
Further, its seen that the honorific property is an enumerated type, and presented that as
a drop-down list.</p><p>In addition, Tapestry has converted the property names
("city", "email", "firstName") to user presentable labels ("City", "Email", "First Name").
In fact, these are &lt;label&gt; elements, so clicking a label with the mouse will
move the input cursor into the corresponding field.</p><p>This is an awesome start;
it's a presentable interface, quite nice in fact for a few minute's work. But it's far from
perfect; 
 let's get started with some customizations.</p><h1 id="UsingBeanEditFormToCreateUserForms-ChangingFieldOrder">Changing
Field Order</h1><p>The BeanEditForm must guess at the right order to present the
fields; for public fields, they end up in alphabetical order</p>
-<sup id="FootnoteMarker2">
-    <a shape="rect" class="FootnoteMarker" name="FootnoteMarker2" href="#Footnote2" onclick="footnoteHighlight(&quot;2&quot;,true);"
alt="Footnote: Click here to display the footnote" title="Footnote: Click here to display
the footnote">
-            2
-    </a>
-</sup>
 <p>.</p><p>&#160;</p><p>A better order for these fields
is the order in which they are defined in the Address class:</p><ul><li>honorific</li><li>firstName</li><li>lastName</li><li>street1</li><li>street2</li><li>city</li><li>state</li><li>zip</li><li>email</li><li>phone</li></ul><p>We
can accomplish this by using the <code>reorder</code> parameter of the BeanEditForm
component, which is a comma separated list of property (or public field) names:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader
pdl" style="border-bottom-width: 1px;"><b>CreateAddress.tml (partial)</b></div><div
class="codeContent panelContent pdl">
 <script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[
 &lt;t:beaneditform object=&quot;address&quot;
     reorder=&quot;honorific,firstName,lastName,street1,street2,city,state,zip,email,phone&quot;
/&gt;
 ]]></script>
-</div></div><p><img class="confluence-embedded-image confluence-thumbnail"
src="using-beaneditform-to-create-user-forms.thumbs/create-address-reordered.png" data-image-src="/confluence/download/attachments/23340431/create-address-reordered.png?version=1&amp;modificationDate=1291928238000&amp;api=v2"></p><h3
id="UsingBeanEditFormToCreateUserForms-Customizinglabels">Customizing labels</h3><p>Tapestry
makes it pretty easy to customize the labels used on the fields. It's just a matter of creating
a <em>message catalog</em> for the page.</p><p>In Tapestry, every
page and component may have its own message catalog. This is a standard Java properties file,
and it is named the same as the page or component class, with a ".properties" extension. A
message catalog consists of a series of lines, each line is a message key and a message value
separated with an equals sign.</p><p>All it takes is to create a message entry
with a particular name: the name of the property suffixed with "-label". As
  elsewhere, Tapestry is forgiving of case.</p><div class="preformatted panel" style="border-width:
1px;"><div class="preformattedHeader panelHeader" style="border-bottom-width: 1px;"><b>src/main/resources/com/example/tutorial/pages/address/CreateAddress.properties</b></div><div
class="preformattedContent panelContent">
+</div></div><p><img class="confluence-embedded-image" width="700" src="https://cwiki.apache.org/confluence/download/attachments/23340431/create-address-reordered.png?version=1&amp;modificationDate=1291928238000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/create-address-reordered.png?version=1&amp;modificationDate=1291928238000&amp;api=v2"></p><h3
id="UsingBeanEditFormToCreateUserForms-Customizinglabels">Customizing labels</h3><p>Tapestry
makes it pretty easy to customize the labels used on the fields. It's just a matter of creating
a <em>message catalog</em> for the page.</p><p>In Tapestry, every
page and component may have its own message catalog. This is a standard Java properties file,
and it is named the same as the page or component class, with a ".properties" extension. A
message catalog consists of a series of lines, each line is a message key and a message value
separated with an equals sign.</p><p>All it takes is to create a message entry
with a pa
 rticular name: the name of the property suffixed with "-label". As elsewhere, Tapestry is
forgiving of case.</p><div class="preformatted panel" style="border-width: 1px;"><div
class="preformattedHeader panelHeader" style="border-bottom-width: 1px;"><b>src/main/resources/com/example/tutorial/pages/address/CreateAddress.properties</b></div><div
class="preformattedContent panelContent">
 <pre>street1-label=Street 1
 street2-label=Street 2
 email-label=E-Mail
 zip-label=Zip Code
 phone-label=Phone Number</pre>
-</div></div><p>Since this is a <em>new</em> file (and not a
change to an existing file), you may have to restart Jetty to force Tapestry to pick up the
change.</p><p><img class="confluence-embedded-image confluence-content-image-border"
height="446" width="760" src="https://cwiki.apache.org/confluence/download/attachments/23340431/address-v3.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/address-v3.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"><br
clear="none"> Create Address form with field labels corrected</p><p>We can
also customize the options in the drop down list. All we have to do is add some more entries
to the message catalog matching the enum names to the desired labels. Update CreateAddress.properties
and add:</p><div class="preformatted panel" style="border-width: 1px;"><div
class="preformattedContent panelContent">
+</div></div><p>Since this is a <em>new</em> file (and not a
change to an existing file), you may have to restart Jetty to force Tapestry to pick up the
change.</p><p><img class="confluence-embedded-image confluence-content-image-border"
width="700" src="https://cwiki.apache.org/confluence/download/attachments/23340431/address-v3.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/address-v3.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"><br
clear="none"> Create Address form with field labels corrected</p><p>We can
also customize the options in the drop down list. All we have to do is add some more entries
to the message catalog matching the enum names to the desired labels. Update CreateAddress.properties
and add:</p><div class="preformatted panel" style="border-width: 1px;"><div
class="preformattedContent panelContent">
 <pre>MR=Mr.
 MRS=Mrs.
 DR=Dr.
@@ -246,7 +231,7 @@ DR=Dr.
 </div></div><p>Notice that we don't have to include an option for MISS,
because that is converted to "Miss" anyway. You might just want to include it for sake of
consistency ... the point is, each option label is searched for separately.</p><p>Lastly,
the default label on the submit button is "Create/Update" (BeanEditForm doesn't know how it
is being used). Let's change that to "Create Address".</p><p>That button is a
component within the BeanEditForm component. It's not a property, so we can't just put a message
into the message catalog, the way we can with the fields. Fortunately, the BeanEditForm component
includes a parameter expressly for re-labeling the button. Simply change the CreateAddress
component template:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
 <script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[
 &lt;t:beaneditform submitlabel=&quot;Create Address&quot; object=&quot;address&quot;/&gt;
 ]]></script>
-</div></div><p>The default for the submitlabel parameter is "Create/Update",
but here we're overriding that default to a specific value.</p><p>The final result
shows the reformatting and relabeling:</p><p><img class="confluence-embedded-image
confluence-content-image-border" src="https://cwiki.apache.org/confluence/download/attachments/23340431/address-v5.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/address-v5.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"><br
clear="none"> Create Address form with proper labels</p><p>Before continuing
on to validation, a side note about message catalogs. Message catalogs are not just for re-labeling
fields and options; we'll see in later chapters how message catalogs are used in the context
of localization and internationalization.</p><p>Instead of putting the label for
the submit button directly inside the template, we're going to provide a reference to the
lab
 el; the actual label will go in the message catalog.</p><p>In Tapestry, when
binding a parameter, the value you provide may include a prefix. The prefix guides Tapestry
in how to interpret the rest of the the parameter value ... is it the name of a property?
The id of a component? A message key? Most fields have a default prefix, usually "prop:",
that is used when you fail to provide one (this helps to make the templates as terse as possible).</p><p>Here
we want to reference a message from the catalog, so we use the "message:" prefix:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent
pdl">
+</div></div><p>The default for the submitlabel parameter is "Create/Update",
but here we're overriding that default to a specific value.</p><p>The final result
shows the reformatting and relabeling:</p><p><img class="confluence-embedded-image
confluence-content-image-border" width="700" src="https://cwiki.apache.org/confluence/download/attachments/23340431/address-v5.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/address-v5.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"><br
clear="none"> Create Address form with proper labels</p><p>Before continuing
on to validation, a side note about message catalogs. Message catalogs are not just for re-labeling
fields and options; we'll see in later chapters how message catalogs are used in the context
of localization and internationalization.</p><p>Instead of putting the label for
the submit button directly inside the template, we're going to provide a referenc
 e to the label; the actual label will go in the message catalog.</p><p>In Tapestry,
when binding a parameter, the value you provide may include a prefix. The prefix guides Tapestry
in how to interpret the rest of the the parameter value ... is it the name of a property?
The id of a component? A message key? Most fields have a default prefix, usually "prop:",
that is used when you fail to provide one (this helps to make the templates as terse as possible).</p><p>Here
we want to reference a message from the catalog, so we use the "message:" prefix:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent panelContent
pdl">
 <script class="theme: Default; brush: xml; gutter: false" type="syntaxhighlighter"><![CDATA[
 &lt;t:beaneditform object=&quot;address&quot; submitlabel=&quot;message:submit-label&quot;
     reorder=&quot;honorific,firstName,lastName,street1,street2,city,state,zip,email,phone&quot;
/&gt;
 ]]></script>
@@ -267,10 +252,10 @@ DR=Dr.
 <script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[
 @Validate(&quot;required,regexp=^\\d{5}(-\\d{4})?$&quot;)
   public String zip;
 ]]></script>
-</div></div><p>Let's give it a try; restart the application and enter an
"abc" for the zip code.</p><p><img class="confluence-embedded-image confluence-content-image-border"
height="482" width="760" src="https://cwiki.apache.org/confluence/download/attachments/23340431/address-v7.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/address-v7.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"><br
clear="none"> Regexp validation</p><p>This is what you'll see after typing
"abc" and tabbing out of the field, then tabbing back in. It's a little hard to capture all
the animation effects in a still photo.</p><p>In any case, that's the right validation
behavior, but it's the wrong message. Your users are not going to know or care about regular
expressions.</p><p>Fortunately, it's easy to customize validation messages. All
we need to know is the name of the property ("zip") and the name of the validator ("regexp").

 We can then put an entry into the CreateAddress message catalog:</p><div class="preformatted
panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
+</div></div><p>Let's give it a try; restart the application and enter an
"abc" for the zip code.</p><p><img class="confluence-embedded-image confluence-content-image-border"
width="700" src="https://cwiki.apache.org/confluence/download/attachments/23340431/address-v7.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/address-v7.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"><br
clear="none"> Regexp validation</p><p>This is what you'll see after typing
"abc" and tabbing out of the field, then tabbing back in. It's a little hard to capture all
the animation effects in a still photo.</p><p>In any case, that's the right validation
behavior, but it's the wrong message. Your users are not going to know or care about regular
expressions.</p><p>Fortunately, it's easy to customize validation messages. All
we need to know is the name of the property ("zip") and the name of the validator ("regexp").
We can then p
 ut an entry into the CreateAddress message catalog:</p><div class="preformatted
panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
 <pre>zip-regexp-message=Zip Codes are five or nine digits.  Example: 02134 or 90125-1655.
 </pre>
-</div></div><p>Refresh the page and submit again:</p><p><img
class="confluence-embedded-image confluence-content-image-border" height="482" width="760"
src="https://cwiki.apache.org/confluence/download/attachments/23340431/address-v8.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/address-v8.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"></p><p>Regexp
validation with corrected message</p><p>This trick isn't limited to just the regexp
validator, it works equally well with <em>any</em> validator.</p><p>Let's
go one step further. Turns out, we can move the regexp pattern to the message catalog as well.
If you only provide the name of the validator in the @Validate annotation, Tapestry will search
the containing page's message catalog of the constraint value, as well as the validation message.
The constraint value for the regexp validator is the regular expression to match against.</p><div
class="code p
 anel pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
+</div></div><p>Refresh the page and submit again:</p><p><img
class="confluence-embedded-image confluence-content-image-border" width="700" src="https://cwiki.apache.org/confluence/download/attachments/23340431/address-v8.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"
data-image-src="/confluence/download/attachments/23340431/address-v8.png?version=1&amp;modificationDate=1286782418000&amp;api=v2"></p><p>Regexp
validation with corrected message</p><p>This trick isn't limited to just the regexp
validator, it works equally well with <em>any</em> validator.</p><p>Let's
go one step further. Turns out, we can move the regexp pattern to the message catalog as well.
If you only provide the name of the validator in the @Validate annotation, Tapestry will search
the containing page's message catalog of the constraint value, as well as the validation message.
The constraint value for the regexp validator is the regular expression to match against.</p><div
class="code panel pdl" sty
 le="border-width: 1px;"><div class="codeContent panelContent pdl">
 <script class="theme: Default; brush: java; gutter: false" type="syntaxhighlighter"><![CDATA[
 @Validate(&quot;required,regexp&quot;)
   public String zip;
 ]]></script>
@@ -278,19 +263,7 @@ DR=Dr.
 <pre>zip-regexp=^\\d{5}(-\\d{4})?$
 zip-regexp-message=Zip Codes are five or nine digits.  Example: 02134 or 90125-1655.
 </pre>
-</div></div><p>After a restart you'll see the ... the same behavior. But
when we start creating more complicated regular expressions, it'll be much, much nicer to
put them in the message catalog rather than inside the annotation value. And inside the message
catalog, you can change and tweak the regular expressions without having to restart the application
each time.</p><p>We could go a bit further here, adding more regular expression
validation for phone numbers and e-mail addresses. We're also far from done in terms of further
customizations of the BeanEditForm component.</p><p>By now you are likely curious
about what happens <em>after</em> the form submits successfully (without validation
errors), so that's what we'll focus on next.</p><hr><p>&#160;</p><table
class="Footnotes" style="width: 100%; border:none;" cellspacing="0" cellpadding="0" summary="This
table contains one or more notes for references made elsewhere on the page."><caption
class="accessibility">Footnotes</caption
 ><thead class="accessibility"><tr class="accessibility"><th colspan="1"
rowspan="1" class="accessibility" id="footnote-th1">Reference</th><th colspan="1"
rowspan="1" class="accessibility" id="footnote-th2">Notes</th></tr></thead><tbody><tr
name="Footnote1"><td colspan="1" rowspan="1" valign="top" class="FootnoteNum" headings="footnote-th1">
-        <a shape="rect" id="FootnoteNum1" href="#FootnoteMarker1" onclick="footnoteMarkerHighlight(&quot;1&quot;);"
onmouseover="footnoteHighlight(&quot;1&quot;,false);" alt="Footnote: Click to return
to reference in text" title="Footnote: Click to return to reference in text">
-            1
-        </a>
-      </td><td colspan="1" rowspan="1" valign="top" class="Footnote" id="Footnote1"
width="100%" headings="footnote-th2">
-          Tapestry also checks for redundant prefixes. In addition, the long name, "address/CreateAddress"
is also valid.
-      </td></tr><tr name="Footnote2"><td colspan="1" rowspan="1" valign="top"
class="FootnoteNum" headings="footnote-th1">
-        <a shape="rect" id="FootnoteNum2" href="#FootnoteMarker2" onclick="footnoteMarkerHighlight(&quot;2&quot;);"
onmouseover="footnoteHighlight(&quot;2&quot;,false);" alt="Footnote: Click to return
to reference in text" title="Footnote: Click to return to reference in text">
-            2
-        </a>
-      </td><td colspan="1" rowspan="1" valign="top" class="Footnote" id="Footnote2"
width="100%" headings="footnote-th2">
-          For standard JavaBeans properties, the BeanEditForm default is in the order in
which the getter methods are defined in the class (it uses line number information, if available).
-      </td></tr></tbody></table><style type="text/css">/*<![CDATA[*/
+</div></div><p>After a restart you'll see the ... the same behavior. But
when we start creating more complicated regular expressions, it'll be much, much nicer to
put them in the message catalog rather than inside the annotation value. And inside the message
catalog, you can change and tweak the regular expressions without having to restart the application
each time.</p><p>We could go a bit further here, adding more regular expression
validation for phone numbers and e-mail addresses. We're also far from done in terms of further
customizations of the BeanEditForm component.</p><p>By now you are likely curious
about what happens <em>after</em> the form submits successfully (without validation
errors), so that's what we'll focus on next.</p><hr><p>&#160;</p><style
type="text/css">/*<![CDATA[*/
 table.ScrollbarTable  {border: none;padding: 3px;width: 100%;padding: 3px;margin: 0px;background-color:
#f0f0f0}
 table.ScrollbarTable td.ScrollbarPrevIcon {text-align: center;width: 16px;border: none;}
 table.ScrollbarTable td.ScrollbarPrevName {text-align: left;border: none;}



Mime
View raw message