Modified: websites/production/tapestry/content/component-parameters.html
==============================================================================
--- websites/production/tapestry/content/component-parameters.html (original)
+++ websites/production/tapestry/content/component-parameters.html Mon May 21
05:20:56 2018
@@ -86,11 +86,13 @@
+
+
<h3>Related Articles</h3>
<ul class="content-by-label"><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="component-parameters.html">Component
Parameters</a>
@@ -99,7 +101,7 @@
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="component-templates.html">Component
Templates</a>
@@ -108,25 +110,25 @@
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="templating-and-markup-faq.html">Templating
and Markup FAQ</a>
+ <a href="component-classes.html">Component Classes</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="component-classes.html">Component Classes</a>
+ <a href="templating-and-markup-faq.html">Templating
and Markup FAQ</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="page-and-component-classes-faq.html">Page
And Component Classes FAQ</a>
@@ -135,34 +137,34 @@
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="enum-parameter-recipe.html">Enum Parameter
Recipe</a>
+ <a
href="supporting-informal-parameters.html">Supporting Informal Parameters</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="supporting-informal-parameters.html">Supporting Informal Parameters</a>
+ <a href="default-parameter.html">Default Parameter</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="default-parameter.html">Default Parameter</a>
+ <a href="enum-parameter-recipe.html">Enum Parameter
Recipe</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="component-cheat-sheet.html">Component Cheat
Sheet</a>
@@ -174,21 +176,21 @@
<p>In the following example, <code>page</code> is a parameter of the
<code>pagelink</code> component. The page parameter tells the pagelink
component which page to go to when the user clicks on the rendered
hyperlink:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<t:pagelink page="Index">Go Home</t:pagelink>
</html></pre>
</div></div><p>A component may have any number of parameters. Each parameter
has a specific name, a specific Java type (which may be a primitive value), and
may be <em>optional</em> or <em>required</em>.</p><p>Within a component class,
parameters are declared by using the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Parameter.html">Parameter</a>
annotation on a private field, as we'll see below.</p><p><span
class="confluence-anchor-link"
id="ComponentParameters-bindingparameters"></span></p><h1
id="ComponentParameters-ParameterBindings">Parameter Bindings</h1><p>In
Tapestry, a parameter is not a slot into which data is pushed: it is a
<em>connection</em> between a field of the component (marked with the
@Parameter annotation) and a property or resource of the component's container.
(Components can be nested, so the container can be either the page or another
component.)</p><div class="navmenu" style="float:right; backgr
ound:white; margin:3px; padding:3px">
<div class="panel" style="border-width: 1px;"><div class="panelHeader"
style="border-bottom-width: 1px;"><b>Contents</b></div><div
class="panelContent">
<style type="text/css">/*<![CDATA[*/
-div.rbtoc1523334077379 {padding: 0px;}
-div.rbtoc1523334077379 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1523334077379 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1526880002508 {padding: 0px;}
+div.rbtoc1526880002508 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1526880002508 li {margin-left: 0px;padding-left: 0px;}
-/*]]>*/</style><div class="toc-macro rbtoc1523334077379">
+/*]]>*/</style><div class="toc-macro rbtoc1526880002508">
<ul class="toc-indentation"><li><a
href="#ComponentParameters-ParameterBindings">Parameter Bindings</a></li><li><a
href="#ComponentParameters-BindingExpressions">Binding
Expressions</a></li><li><a
href="#ComponentParameters-@Parameterannotation">@Parameter
annotation</a></li><li><a
href="#ComponentParameters-Don'tusethe${...}syntax!">Don't use the ${...}
syntax!</a></li><li><a href="#ComponentParameters-InformalParameters">Informal
Parameters</a></li><li><a
href="#ComponentParameters-ParametersAreBi-Directional">Parameters Are
Bi-Directional</a></li><li><a
href="#ComponentParameters-InheritedParameterBindings">Inherited Parameter
Bindings</a></li><li><a
href="#ComponentParameters-ComputedParameterBindingDefaults">Computed Parameter
Binding Defaults</a></li><li><a
href="#ComponentParameters-UnboundParameters">Unbound Parameters</a></li><li><a
href="#ComponentParameters-ParameterTypeCoercion">Parameter Type
Coercion</a></li><li><a href="#ComponentParameters-ParameterNames">
Parameter Names</a></li><li><a
href="#ComponentParameters-DeterminingifBound">Determining if
Bound</a></li><li><a
href="#ComponentParameters-PublishingParameters">Publishing
Parameters</a></li></ul>
</div>
</div></div></div> <p>The connection between a component and a property
(or resource) of its container is called a <em>binding</em>. The binding is
two-way: the component can read the bound property by reading its parameter
field. Likewise, a component that updates its parameter field will update the
bound property.</p><p>This is important in a lot of cases; for example a
TextField component can read <em>and update</em> the property bound to its
value parameter. It reads the value when rendering, but updates the value when
the form is submitted.</p><p>The component listed below is a looping component;
it renders its body a number of times, defined by its <code>start</code> and
<code>end</code> parameters (which set the boundaries of the loop). The
component can update a <code>result</code> parameter bound to a property of its
container; it will automatically count up or down depending on whether
<code>start</code> or <code>end</code> is larger.</p><div class="code panel
pdl" st
yle="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">package org.example.app.components;
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">package
org.example.app.components;
import org.apache.tapestry5.annotations.AfterRender;
import org.apache.tapestry5.annotations.Parameter;
@@ -241,38 +243,38 @@ public class Count
}
</pre>
</div></div><p>The name of the parameter is the same as field name (except
with leading "_" and "$" characters, if any, removed). Here, the parameter
names are "start", "end" and "result".</p><p>The component above can be
referenced in another component or page <a
href="component-templates.html">template</a>, and its parameters
<em>bound</em>:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html t:type="layout"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><html t:type="layout"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<p> Merry Christmas: <t:count end="3"> Ho! </t:count>
</p>
</html>
</pre>
</div></div><p>The end attribute is used to <em>bind</em> the end parameter of
the Count component. Here, it is being bound to the string value "3", which is
automatically <a href="type-coercion.html">coerced</a> by Tapestry into the
int value, 3.</p><p>Any number of parameters may be bound this
way.</p><p>Component parameters may also be bound using the @<a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Component.html">Component</a>
annotation inside the component class. (Where conflicts occur, the parameters
bound using the Component annotation will take precedence over parameter
bindings in the template.)</p><p><span class="confluence-anchor-link"
id="ComponentParameters-binding-expressions"></span></p><h1
id="ComponentParameters-BindingExpressions">Binding Expressions</h1><p>The
value inside the template, "3" in the previous example, is a <em>binding
expression</em>.</p><p>By placing a prefix in front of the value, you c
an change how Tapestry interprets the remainder of the expression (the part
after the colon):</p><div class="table-wrap"><table
class="confluenceTable"><tbody><tr><th colspan="1" rowspan="1"
class="confluenceTh"><p><strong>Prefix</strong></p></th><th colspan="1"
rowspan="1"
class="confluenceTh"><p><strong>Description</strong></p></th></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>asset:</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>The relative path to an asset file (which
must exist)</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>block:</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>The id of a block within the
template</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>component:</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>The id of another component within the same
template</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>context:</p></td><td colspan="1" rowspan="1
" class="confluenceTd"><p>Context asset: path from context
root</p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>literal:</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>A literal string</p></td></tr><tr><td colspan="1"
rowspan="1" class="confluenceTd"><p>nullfieldstrategy:</p></td><td colspan="1"
rowspan="1" class="confluenceTd"><p>Used to locate a pre-defined <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/NullFieldStrategy.html">NullFieldStrategy</a></p></td></tr><tr><td
colspan="1" rowspan="1" class="confluenceTd"><p>message:</p></td><td
colspan="1" rowspan="1" class="confluenceTd"><p>Retrieves a string from the
component's <a href="localization.html">message
catalog</a></p></td></tr><tr><td colspan="1" rowspan="1"
class="confluenceTd"><p>prop:</p></td><td colspan="1" rowspan="1"
class="confluenceTd"><p>A <a href="property-expressions.html">property
expression</a> to read or update</p></td></tr><tr
><td colspan="1" rowspan="1" class="confluenceTd"><p>symbol:</p></td><td
>colspan="1" rowspan="1" class="confluenceTd"><p>Used to read one of your <a
>href="symbols.html">symbols</a></p></td></tr><tr><td colspan="1" rowspan="1"
>class="confluenceTd"><p>translate:</p></td><td colspan="1" rowspan="1"
>class="confluenceTd"><p>The name of a configured
>translator</p></td></tr><tr><td colspan="1" rowspan="1"
>class="confluenceTd"><p>validate:</p></td><td colspan="1" rowspan="1"
>class="confluenceTd"><p>A <em>validator specification</em> used to create
>some number of field validators</p></td></tr><tr><td colspan="1" rowspan="1"
>class="confluenceTd"><p>var:</p></td><td colspan="1" rowspan="1"
>class="confluenceTd"><p>Allows a render variable of the component to be read
>or updated</p></td></tr></tbody></table></div><p>Most of these binding
>prefixes allow parameters to be bound to read-only values; for instance a
>parameter bound to "message:some-key" will see the message for "some-key"
>from its con
tainer's message catalog in the field. If the component tries to update the
parameter (by setting the value of the field), a runtime exception will be
thrown to indicate that the value is read-only.</p><p>Only prop: and var:
binding prefixes are updateable (but you must <em>not</em> use the ${..} syntax
here; see the <a href="component-parameters.html">warning
below</a>).</p><p>Each parameter has a default prefix, defined by the
component, that is used when the prefix is not provided. The most common are
"literal:" and "prop:".</p><p>A <em>special prefix</em>, "inherit:", is used to
support <a href="component-parameters.html">Inherited Parameter
Bindings</a>.</p><h3 id="ComponentParameters-RenderVariables:Bindings">Render
Variables: Bindings</h3><p>Components can have any number of <em>render
variables</em>. Render variables are named values with no specific type (they
are ultimately stored in a Map). Render variables are useful for holding simple
values, such as loop indices, tha
t need to be passed from one component to another.</p><p>For example, the
following template code:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><ul>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><ul>
<li t:type="loop" source="1..10" value="index">${index}</li>
</ul>
</pre>
</div></div><p>and the following Java code:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">@Property
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">@Property
private int index;
</pre>
</div></div><p>... could be rewritten as just:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><ul>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><ul>
<li t:type="loop" source="1..10"
value="var:index">${var:index}</li>
</ul>
</pre>
</div></div><p>In other words, you don't have to define a property in the Java
code. The disadvantage is that render variables don't work with the property
expression syntax, so you can pass around a render variable's <em>value</em>
but you can't reference any of the value's properties.</p><p>Render variables
are automatically cleared when a component finishes rendering.</p><p>Render
variable names are case insensitive.</p><h3
id="ComponentParameters-Property:Bindings">Property: Bindings</h3><p>Main
Article: <a href="property-expressions.html">Property
Expressions</a></p><p>The "prop:" binding prefix indicates a property
expression binding.</p><p>Property expressions are used to link a parameter of
a component to a property of its container. Property expressions can navigate a
series of properties and/or invoke methods, as well as several other useful
patterns.</p><p>The default binding prefix in most cases is "prop:", which is
why it is usually omitted.</p><h3 id="ComponentParamet
ers-Validate:Bindings">Validate: Bindings</h3><p>Main Article: <a
href="forms-and-validation.html">Forms and Validation</a></p><p>The "validate:"
binding prefix is highly specialized. It allows a short string to be used to
create and configure the objects that perform input validation for form control
components, such as TextField and Checkbox.</p><p>The string is a
comma-separated list of <em>validator types</em>. These are short aliases for
objects that perform the validation. In many cases, the validation is
configurable in some way: for example, a validator that enforces a minimum
string length needs to know what that minimum string length is. Such values are
specified after an equals sign.</p><p>For example:
<code>validate:required,minLength=5</code> would presumably enforce that a
field requires a value, and with at least five characters.</p><h3
id="ComponentParameters-Translate:Bindings">Translate: Bindings</h3><p>The
"translate:" binding prefix is also related to input vali
dation. It is the name of a configured <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/Translator.html">Translator</a>,
responsible for converting between server-side and client-side representations
of data (for instance, between client-side strings and server-side numeric
values).</p><p>The list of available translators is configured by the <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/TranslatorSource.html">TranslatorSource</a>
service.</p><h3 id="ComponentParameters-Asset:Bindings">Asset:
Bindings</h3><p>Main Article: <a href="assets.html">Assets</a></p><p>Assets
bindings are used to specify <a href="component-parameters.html">Component
Parameters</a>, static content served by Tapestry. By default, assets are
located relative to the component class in your packaged application or module.
This can be overridden by prefixing the path with "context:", in which case,
the path
is a context path from the root of the web application context. Because
accessing context assets is relatively common, a separate "context:" binding
prefix for that purpose exists (described below).</p><h3
id="ComponentParameters-Context:Bindings">Context: Bindings</h3><p>Main
Article: <a href="assets.html">Assets</a></p><p>Context bindings are like
asset bindings, but the path is <em>always</em> relative to the root of the web
application context. This is intended for use inside templates, i.e.:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent
panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"> <img src="${context:images/icon.png}"/>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"> <img
src="${context:images/icon.png}"/>
</pre>
</div></div><p>Tapestry will adjust the URL of the image so that it is
processed by Tapestry, not the servlet container. It will gain a URL that
includes the application's version number, it will have a far-future expires
header, and (if the client supports it) its content will be compressed before
being sent to the client.</p><h1
id="ComponentParameters-@Parameterannotation">@Parameter annotation</h1><h3
id="ComponentParameters-RequiredParameters">Required
Parameters</h3><p>Parameters that are required <strong>must</strong> be bound.
A runtime exception occurs if a component has unbound required
parameters.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class Component{
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class Component{
@Parameter(required = true)
private String parameter;
}</pre>
</div></div><div class="confluence-information-macro
confluence-information-macro-tip"><span class="aui-icon aui-icon-small
aui-iconfont-approve confluence-information-macro-icon"></span><div
class="confluence-information-macro-body"><p>Sometimes a parameter is marked as
required, but may still be omitted if the underlying value is provided by some
other means. This is the case, for example, with the Select component's value
parameter, which may have its underlying value set by <a
href="using-select-with-a-list.html">contributing a ValueEncoderSource</a>. Be
sure to read the component's parameter documentation carefully. Required simply
enables checks that the parameter is bound, it does not mean that you must
supply the binding in the template (or @Component
annotation).</p></div></div><h3
id="ComponentParameters-OptionalParameters">Optional
Parameters</h3><p>Parameters are optional unless they are marked as
required.</p><p>You may set a default value for optional parameters using
the <code>value</code> element of the @Parameter annotation. In the Count
component above, the start parameter has a default value of 1. That value is
used unless the start parameter is bound, in which case, the bound value
supersedes the default.</p><h3
id="ComponentParameters-ParameterBindingDefaults">Parameter Binding
Defaults</h3><p>The @Parameter annotation's <code>value</code> element can be
used to specify a <em>binding expression</em> that will be the default binding
for the parameter if otherwise left unbound. Typically, this is the name of a
property that that will compute the value on the fly.</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">@Parameter(value="defaultMessage") // or, equivalently,
@Parameter("defaultMessage")
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default"
data-theme="Default">@Parameter(value="defaultMessage") // or, equivalently,
@Parameter("defaultMessage")
private String message;
@Parameter(required=true)
@@ -284,19 +286,19 @@ public String getDefaultMessage(){ 
</pre>
</div></div><p>As elsewhere, you may use a prefix on the value. A common
prefix to use is the "message:" prefix, to access a localized message.</p><h3
id="ComponentParameters-ParameterCaching">Parameter Caching</h3><p>Reading a
parameter value can be marginally expensive (because of type coercion).
Therefore, it makes sense to cache the parameter value, at least while the
component is actively rendering itself.</p><p>In rare cases, it is desirable to
defeat the caching; this can be done by setting the cache() attribute of the
@Parameter annotation to false.</p><p><span class="confluence-anchor-link"
id="ComponentParameters-dontUseSyntax"></span></p><h1
id="ComponentParameters-Don'tusethe${...}syntax!">Don't use the ${...}
syntax!</h1><p>Main Article: <a
href="component-templates.html">Expansions</a></p><p>You generally should
<em>not</em> use the Template Expansion syntax, ${...}, within component
parameter bindings. Doing so results in the property inside the braces being
converte
d to an (immutable) string, and will therefore result in a runtime exception
if your component needs to update the value (whenever the default or explicit
binding prefix is <code>prop:</code> or <code>var:</code>, since such component
parameters are <em>two-way</em> bindings).</p><div
class="sectionColumnWrapper"><div class="sectionMacro"><div
class="sectionMacroRow"><div class="columnMacro"><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>This is right</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:textfield t:id="color" value="color"/>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><t:textfield
t:id="color" value="color"/>
</pre>
</div></div></div><div class="columnMacro"><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>This is wrong</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:textfield t:id="color" value="${color}"/>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><t:textfield
t:id="color" value="${color}"/>
</pre>
</div></div></div></div></div></div><p>The general rule is, only use the
${...} syntax in non-Tapestry-controlled locations in your template, such as in
attributes of ordinary HTML elements and in plain-text areas of your
template.</p><div class="sectionColumnWrapper"><div class="sectionMacro"><div
class="sectionMacroRow"><div class="columnMacro"><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>This is right</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><img src="${context:images/banner.png}"/>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><img
src="${context:images/banner.png}"/>
</pre>
</div></div></div><div class="columnMacro"><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>This is wrong</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><img src="context:images/banner.png"/>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><img
src="context:images/banner.png"/>
</pre>
</div></div></div></div></div></div><h1
id="ComponentParameters-InformalParameters">Informal Parameters</h1><p>Main
Article: <a href="supporting-informal-parameters.html">Supporting Informal
Parameters</a></p><p>Many components support <em>informal parameters</em>,
additional parameters beyond the formally defined parameters. Informal
parameters will be rendered into the output as additional attributes on the tag
rendered by the component. Generally speaking, components that have a 1:1
relationship with a particular HTML tag (such as <TextField> and
<input> will support informal parameters.</p><p>Only components whose
class is annotated with @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/SupportsInformalParameters.html">SupportsInformalParameters</a>
will support informal parameters. Tapestry silently drops informal parameters
that are specified for components that do not have this
annotation.</p><p>Informal
parameters are often used to set the CSS class of an element, or to specify
client-side event handlers.</p><p>The default binding prefix for informal
parameters depends on <em>where</em> the parameter binding is specified. If the
parameter is bound inside a Java class, within the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Component.html">Component</a>
annotation, then the default binding prefix is "prop:". If the parameter is
bound inside the component template, then the default binding prefix is
"literal:". This reflects the fact that a parameter specified in the Java
class, using the annotation, is most likely a computed value, whereas a value
in the template should simply be copied, as is, into the result HTML
stream.</p><p>Informal parameters (if supported) are always rendered into the
output <em>unless</em> they are bound to a property whose value is null. If the
bound property is null then the parameter will <em
>not</em> be present at all in the rendered output.</p><p>If your component
>should render informal parameters, just inject the <a class="external-link"
>href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ComponentResources.html">ComponentResources</a>
> for your component and invoke the <code>renderInformalParameters()</code>
>method. See <a href="supporting-informal-parameters.html">Supporting
>Informal Parameters</a> for an example of how to do this.</p><h1
>id="ComponentParameters-ParametersAreBi-Directional">Parameters Are
>Bi-Directional</h1><p>Parameters are not simply variables; each parameter
>represents a connection, or <em>binding</em>, between a component and a
>property of its container. When using the prop: binding prefix, the component
>can force changes <em>into</em> a property of its container, just by
>assigning a value to its own instance variable.</p><div class="code panel
>pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:layout
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><t:layout
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<p> Countdown:
<t:count start="5" end="1" result="index">
${index} ...
@@ -305,10 +307,10 @@ public String getDefaultMessage(){ 
</t:layout>
</pre>
</div></div><p>Because the Count component updates its result parameter (the
<code>result</code> field), the index property of the containing component is
updated. Inside the Count's body, we output the current value of the index
property, using the expansion <code>${index</code>}. The resulting output will
look something like:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"> <p> Countdown: 5 ... 4 ... 3 ... 2 ... 1 ...
</p>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"> <p> Countdown: 5
... 4 ... 3 ... 2 ... 1 ... </p>
</pre>
</div></div><p>(Though the whitespace will be quite different.)</p><p>The
relevant part is that components can read fixed values, or <em>live</em>
properties of their container, and can <em>change</em> properties of their
container as well.</p><h1
id="ComponentParameters-InheritedParameterBindings">Inherited Parameter
Bindings</h1><p>A special prefix, "inherit:" is used to identify the name of a
parameter of the containing component. If the parameter is bound in the
containing component, then it will be bound to the same value in the embedded
component.</p><p>If the parameter is not bound in the containing component,
then it will not be bound in the embedded component (and so, the embedded
component may use a default binding).</p><p>Inherited bindings are useful for
complex components; they are often used when an inner component has a default
value for a parameter, and the outer component wants to make it possible to
override that default.</p><div class="code panel pdl" style="borde
r-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>Index.tml</b></div><div class="codeContent
panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<body>
<div t:type="layout" t:menuTitle="literal:The Title">
...
@@ -317,7 +319,7 @@ public String getDefaultMessage(){ 
</html>
</pre>
</div></div><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>Layout.tml</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:container
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><t:container
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<div t:type="title" t:title="inherit:menuTitle"></div>
@@ -326,7 +328,7 @@ public String getDefaultMessage(){ 
</t:container>
</pre>
</div></div><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>Title.java</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">package org.example.app.components;
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">package
org.example.app.components;
import org.apache.tapestry5.annotations.Parameter;
@@ -338,7 +340,7 @@ public class Title {
}
</pre>
</div></div><h1
id="ComponentParameters-ComputedParameterBindingDefaults">Computed Parameter
Binding Defaults</h1><p>In <em>rare</em> cases, you may want to compute the
binding to be used as a parameter default. In this case, you will provide a
<em>default binding method</em>, a method that takes no parameters. The
returned value is used to bind the parameter. The return value may be a <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/Binding.html">Binding</a>
instance, or it may be a simple value (which is more often the
case).</p><p>The method name is "default" plus the capitalized name of the
parameter.</p><p>Using this approach, the previous example may be rewritten
as:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> @Parameter
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> @Parameter
private String message;
@Parameter(required=true)
@@ -361,7 +363,7 @@ public class Title {
}
</pre>
</div></div><p>In this example, a property expression, "basicMessage", is used
to access the message dynamically.</p><p>Alternately, the previous example may
be written even more succinctly as:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> @Parameter
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> @Parameter
private String message;
@Parameter(required=true)
@@ -376,7 +378,7 @@ public class Title {
}
</pre>
</div></div><p>This form is more like using the "literal:" binding prefix,
except that the literal value is computed by the defaultMessage()
method.</p><p>Obviously, this is a lot more work than simply specifying a
default value as part of the @Parameter annotation. In the few real cases where
this is approach is used, the default binding method will usually deduce a
proper binding, typically in terms of the component's id. For example, the
TextField component will deduce a value parameter that binds to a property of
its container with the same name.</p><p>A default binding method will
<em>only</em> be invoked if the @Parameter annotation does not provide a
default value.</p><h1 id="ComponentParameters-UnboundParameters">Unbound
Parameters</h1><p>If a parameter is not bound (and is optional), then the value
may be read or <em>updated</em> at any time.</p><p>Updates to unbound
parameters cause no side effects. In the first example, the value parameter of
the Count component is not bo
und, and this is perfectly valid.</p><p>Note: updates to such fields are
temporary; when the component <em>finishes rendering</em>, the field will
revert to its default value.</p><h1
id="ComponentParameters-ParameterTypeCoercion">Parameter Type
Coercion</h1><p>Main Article: <a
href="parameter-type-coercion.html">Parameter Type Coercion</a></p><p>Tapestry
includes a mechanism for <span class="confluence-link">coercing types
automatically</span>. Most often, this is used to convert literal strings into
appropriate values, but in many cases, more complex conversions will occur.
This mechanism is used for component parameters, such as when an outer
component passes a literal string to an inner component that is expecting an
integer.</p><p>You can easily <a href="type-coercion.html">contribute new
coercions</a> for your own purposes.</p><h1
id="ComponentParameters-ParameterNames">Parameter Names</h1><p>By default,
Tapestry converts from the field name to the parameter name, by str
ipping off leading "$" and "_" characters.</p><p>This can be overridden using
the name() attribute of the @Parameter annotation.</p><h1
id="ComponentParameters-DeterminingifBound">Determining if Bound</h1><p>In rare
cases, you may want to take different behaviors based on whether a parameter is
bound or not. This can be accomplished by querying the component's resources,
which can be <a href="injection.html">injected</a> into the component using
the @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ioc/annotations/Inject.html">Inject</a>
annotation:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class MyComponent
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class MyComponent
{
@Parameter
private int myParam;
@@ -395,18 +397,18 @@ public class Title {
}
</pre>
</div></div><p>The above sketch illustrates the approach. Because the
parameter type is a primitive type, int, it is hard to distinguish between no
binding, and binding explicitly to the value 0.</p><p>The @Inject annotation
will inject the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ComponentResources.html">ComponentResources</a>
for the component. These resources are the linkage between the Java class you
provide, and the infrastructure Tapestry builds around your class. In any case,
once the resources are injected, they can be queried.</p><h1
id="ComponentParameters-PublishingParameters">Publishing
Parameters</h1><p>Often when creating new components from existing components,
you want to expose some of the functionality of the embedded component, in the
form of exposing parameters of the embedded components as parameters of the
outer component.</p><p>In Tapestry 5.0, you would define a parameter of the
outer component, and use t
he "inherit:" binding prefix to connect the inner component's parameter to the
outer component's parameter. This is somewhat clumsy, as it involves creating
an otherwise unused field just for the parameter; in practice it also leads to
duplication of the documentation of the parameter.</p><p>In Tapestry 5.1 and
later, you may use the publishParameters attribute of the @<a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Component.html">Component</a>
annotation. List one or more parameters separated by commas: those parameters
of the inner/embedded component become parameters of the outer component. You
should <strong>not</strong> define a parameter field in the outer
component.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>ContainerComponent.tml</b></div><div class="codeContent panelContent
pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:container
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><t:container
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<t:pageLink t:id="link">Page Link</t:pageLink>
</t:container>
</pre>
</div></div><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>ContainerComponent.java</b></div><div class="codeContent panelContent
pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class ContainerComponent{
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class
ContainerComponent{
@Component(id="link", publishParameters="page")
private PageLink link;
}
</pre>
</div></div><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>Index.tml</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:ContainerComponent t:id="Container"
t:page="About" />
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><t:ContainerComponent
t:id="Container" t:page="About" />
</pre>
</div></div><p>There are still cases where you want to use the "inherit:"
binding prefix. For example, if you have several components that need to share
a parameter, then you must do it the Tapestry 5.0 way: a true parameter on the
outer component, and "inherit:" bindings on the embedded components. You can
follow a similar pattern to rename a parameter in the outer
component.</p><p></p></div>
</div>
Modified: websites/production/tapestry/content/configuration.html
==============================================================================
--- websites/production/tapestry/content/configuration.html (original)
+++ websites/production/tapestry/content/configuration.html Mon May 21 05:20:56
2018
@@ -86,56 +86,58 @@
+
+
<h3>Related Articles</h3>
<ul class="content-by-label"><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="application-module-class-cheat-sheet.html">Application Module Class Cheat
Sheet</a>
+ <a href="response-compression.html">Response
Compression</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="ioc-cookbook-service-configurations.html">IoC cookbook - Service
Configurations</a>
+ <a href="symbols.html">Symbols</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="symbols.html">Symbols</a>
+ <a
href="application-module-class-cheat-sheet.html">Application Module Class Cheat
Sheet</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="tapestry-ioc-configuration.html">Tapestry
IoC Configuration</a>
+ <a
href="ioc-cookbook-service-configurations.html">IoC cookbook - Service
Configurations</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="response-compression.html">Response
Compression</a>
+ <a href="tapestry-ioc-configuration.html">Tapestry
IoC Configuration</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="configuration.html">Configuration</a>
@@ -147,14 +149,14 @@
<h1 id="Configuration-ConfiguringTapestry">Configuring Tapestry</h1><p>This
page discusses all the ways in which Tapestry can be configured. Tapestry
applications are configured almost entirely using Java, with very little XML at
all.</p><p><strong>Contents</strong></p><p><style type="text/css">/*<![CDATA[*/
-div.rbtoc1523334097249 {padding: 0px;}
-div.rbtoc1523334097249 ul {list-style: disc;margin-left: 0px;}
-div.rbtoc1523334097249 li {margin-left: 0px;padding-left: 0px;}
+div.rbtoc1526880003330 {padding: 0px;}
+div.rbtoc1526880003330 ul {list-style: disc;margin-left: 0px;}
+div.rbtoc1526880003330 li {margin-left: 0px;padding-left: 0px;}
-/*]]>*/</style></p><div class="toc-macro rbtoc1523334097249">
+/*]]>*/</style></p><div class="toc-macro rbtoc1526880003330">
<ul class="toc-indentation"><li><a
href="#Configuration-XMLconfiguration(web.xml)">XML configuration
(web.xml)</a></li><li><a
href="#Configuration-YourApplication'sModuleClass">Your Application's Module
Class</a></li><li><a
href="#Configuration-ConfigurationSymbolNames">Configuration Symbol
Names</a></li><li><a
href="#Configuration-SettingComponentParameterDefaults">Setting Component
Parameter Defaults</a></li><li><a
href="#Configuration-ConfiguringIgnoredPaths">Configuring Ignored
Paths</a></li><li><a
href="#Configuration-ConfiguringContentTypeMapping">Configuring Content Type
Mapping</a></li><li><a href="#Configuration-SettingExecutionModes">Setting
Execution Modes</a></li><li><a
href="#Configuration-SegregatingApplicationsIntoFolders">Segregating
Applications Into Folders</a></li></ul>
</div><h2 id="Configuration-XMLconfiguration(web.xml)">XML configuration
(web.xml)</h2><p>Tapestry runs on top of the standard Java Servlet API. To the
servlet container, such as Tomcat, Tapestry appears as a <em>servlet
filter</em>. This gives Tapestry great flexibility in matching URLs without
requiring lots of XML configuration.</p><p>Although most configuration is done
with Java, a small but necessary amount of configuration occurs inside the
servlet deployment descriptor, WEB-INF/web.xml. Most of the configuration is
boilerplate, nearly the same for all applications.</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>web.xml (partial)</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><!DOCTYPE web-app
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
@@ -179,7 +181,7 @@ div.rbtoc1523334097249 li {margin-left:
<p>The Tapestry filter matches all the requests that apply to Tapestry, and
passes the rest off to the servlet container. In situations where there would
be a naming conflict, actual files inside the web application take precedence
over Tapestry pages.</p>
<p>Tapestry recognizes the <em>root URL</em>, where the servlet path is simply
"/", and renders the application page "Index", if it exists.</p></div>The
application-specific part, the <code>tapestry.app-package</code> context
parameter, provides your application's root package name. Tapestry uses this to
locate your page and component classes. It expects page classes in the
<code>pages</code> sub-package and components in the <code>components</code>
sub-package. In the example above, page classes will be stored in the
<code>org.example.myapp.pages</code> package (or in sub-packages below).
Likewise, component classes will be stored in the
<code>org.example.myapp.components</code> package.<p>By convention, the filter
name (<code>filter-name</code>) is almost always "app", but you can use any
name you want. Tapestry uses this to determine what <em>module class</em> name
to look for (see below).</p><h2
id="Configuration-YourApplication'sModuleClass">Your Application's Module
Class</h2>
<p>Main Article: <a href="tapestry-ioc-configuration.html">Tapestry IoC
Configuration</a></p><p>Most other configuration occurs inside your
application's module class. The application module class will often define new
services, provide overrides of services, or make contributions to service
configurations.</p><p>Tapestry looks for your application module class in the
services package (under the root package) of your application. It capitalizes
the <filter-name> and appends "Module". In the previous example, because
the filter name was "app" and the application's root package name is
"org.example.myapp", the module class would be
org.example.myapp.services.AppModule.</p><p>If such a class exists, it is added
to the IoC Registry. It is not an error for your application to not have a
module class, though any non-trivial application will have one.</p><p>Your
application module class (usually AppModule.java) will typically override some
of Tapestry's default, or "factory", symbol
s, by contributing overrides to the ApplicationDefaults service configuration.
For example:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>AppModule.java</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class AppModule
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class AppModule
{
public static void
contributeApplicationDefaults(MappedConfiguration<String,String>
configuration)
{
@@ -440,16 +442,16 @@ div.rbtoc1523334097249 li {margin-left:
<div class="param-body">Some components, notably Grid, Pallete and Zone,
have default parameter values specified in terms of symbols. This means you can
use these symbols to modify the defaults for all instances of such components
in your application. For example, you can set the default rows per page for all
Grid instances by adding this to
the <code>contributeApplicationDefaults</code> method in your
application's module class (typically AppModule.java):
<code>configuration.add(ComponentParameterConstants.GRID_ROWS_PER_PAGE,
"15");</code></div>
</div><p>See the complete list of such constants at <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/ComponentParameterConstants.html">ComponentParameterConstants</a>.</p><h2
id="Configuration-ConfiguringIgnoredPaths">Configuring Ignored
Paths</h2><p>You may sometimes need to use Tapestry in concert with other
servlets. This can cause problems, since Tapestry (being a servlet filter) may
see URLs intended for another servlet and attempt to process them.</p><p>The
Servlet API does not provide Tapestry with any clues about what other servlets
are available in the web application. Instead, you must configure Tapestry to
ignore paths intended for other servlets.</p><p>The IgnoredPathsFilter service
is the method for this kind of configuration. Its configuration is an unordered
collection of regular expression patterns. A request whose path matches any of
these patterns is <strong>not</strong> processed by Tapestry.</p><p>For
example, say yo
u are using <a class="external-link" href="http://getahead.org/dwr/"
rel="nofollow">Direct Web Remoting</a>. You'll likely have the servlet path
/dwr mapped to the Direct Web Remoting servlet.</p><p>You contribution would
look like:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> public static void
contributeIgnoredPathsFilter(Configuration<String> configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static void
contributeIgnoredPathsFilter(Configuration<String> configuration)
{
configuration.add("/dwr/.*");
}
</pre>
</div></div><p>The regular expression matches any path that begins with
"/dwr/".</p><p>The regular expressions provided in the configuration are always
compiled with case insensitivity enabled.</p><p>Also note that actual files in
your web application (images, stylesheets, etc.) are always ignored by
Tapestry.</p><h2 id="Configuration-ConfiguringContentTypeMapping">Configuring
Content Type Mapping</h2><p>The mapping from file type (by extension) to
content type is typically done as part of your servlet-containers
configuration. Alternately, you may contribute to the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/internal/services/ResourceStreamer.html">ResourceStreamer</a>
service's configuration. This is a mapped configuration; it maps file
extensions (such as "css" or "js") to content types ("text/css" or
"text/javascript") respectively.</p><h2
id="Configuration-SettingExecutionModes">Setting Execution
Modes</h2><p>Starting with Tap
estry 5.2.4, we can specify an <em>execution mode</em> by loading specific
Tapestry Modules through a JVM System property. All modules declared in this
way will be loaded after the AppModule of your application. This feature is
very useful for defining a different environment for Production and Development
modes, for example.</p><p>This JVM System property, named
tapestry.execution-mode, is a comma-separated list of mode names. You can
declare this property in a number of different ways:</p><p>1. Add the parameter
to your JVM command line:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">-Dtapestry.execution-mode=uat jetty:run
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default"
data-theme="Default">-Dtapestry.execution-mode=uat jetty:run
</pre>
</div></div><p>2. Add the parameter to the Jetty plugin:</p><div class="code
panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>pom.xml</b></div><div class="codeContent
panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><plugin>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.16</version>
@@ -467,7 +469,7 @@ div.rbtoc1523334097249 li {margin-left:
</plugin>
</pre>
</div></div><p>3. Add the parameter to the Surefire plugin for your
test:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>pom.xml</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><plugin>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.8.1</version>
@@ -479,7 +481,7 @@ div.rbtoc1523334097249 li {margin-left:
</plugin>
</pre>
</div></div><p>For each mode declared in your JVM System Property,
TapestryFilter checks for a parameter in your web.xml, named
tapestry.TheModeName-modules, with TheModeName being the name of the desired
mode. Its value will be a comma-separated list of modules.</p><p>If the
tapestry.execution-mode is not declared, Tapestry will automatically look for
the tapestry.production-modules parameter, because “production” is
the default tapestry.execution-mode value.</p><p>The example below defines two
different execution modes in your web.xml file: production (the default value)
and uat (for "user acceptance testing"). For each mode, we list the modules we
want to load. If we use JVM System property declared in the example above, the
UatModeModule module will be loaded.</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>web.xml</b></div><div class="codeContent
panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><context-param>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><context-param>
<param-name>tapestry.production-modules</param-name>
<param-value>com.example.myapp.services.ProductionModeModule</param-value>
</context-param>
@@ -494,7 +496,7 @@ div.rbtoc1523334097249 li {margin-left:
</context-param>
</pre>
</div></div><p>Execution mode itself may be a comma separated list:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent
panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">-Dtapestry.execution-mode=uat,integration jetty:run
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default"
data-theme="Default">-Dtapestry.execution-mode=uat,integration jetty:run
</pre>
</div></div><h2 id="Configuration-SegregatingApplicationsIntoFolders"><span
style="color: rgb(83,145,38);">Segregating Applications Into
Folders</span></h2><p>In many cases where Tapestry is being adopted into an
existing web application (possibly written in Tapestry 4 or some other
framework), it is nice to segregate the Tapestry application into its own
folder, to avoid conflicts with the existing application or servlets.</p>
@@ -504,13 +506,13 @@ div.rbtoc1523334097249 li {margin-left:
<div class="param-body">Support for application folders was added in
release 5.3.</div>
</div><p>Setting this up is in two parts:</p><ul><li>Modifying the
configuration of the <code><url-pattern></code> for the Tapestry filter
to match the specified folder.</li><li>Identifying the folder name using a
Tapestry symbol value contribution.</li></ul><p>So, if you wanted to run the
Tapestry application inside folder <code>t5app</code>, you would modify your
<code>web.xml</code> indicate the use of the folder:</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"> <filter-mapping>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"> <filter-mapping>
<filter-name>app</filter-name>
<url-pattern>/t5app/*</url-pattern>
</filter-mapping>
</pre>
</div></div><p>... and in your AppModule, you would inform Tapestry about the
mapping change:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class AppModule
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class AppModule
{
@Contribute(SymbolProvider.class)
@ApplicationDefaults
Modified: websites/production/tapestry/content/enum-parameter-recipe.html
==============================================================================
--- websites/production/tapestry/content/enum-parameter-recipe.html (original)
+++ websites/production/tapestry/content/enum-parameter-recipe.html Mon May 21
05:20:56 2018
@@ -86,38 +86,40 @@
+
+
<h3>Related Articles</h3>
<ul class="content-by-label"><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="enum-parameter-recipe.html">Enum Parameter
Recipe</a>
+ <a
href="supporting-informal-parameters.html">Supporting Informal Parameters</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="supporting-informal-parameters.html">Supporting Informal Parameters</a>
+ <a href="default-parameter.html">Default Parameter</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="default-parameter.html">Default Parameter</a>
+ <a href="enum-parameter-recipe.html">Enum Parameter
Recipe</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="component-parameters.html">Component
Parameters</a>
@@ -129,7 +131,7 @@
<h1 id="EnumParameterRecipe-EnumComponentParameter">Enum Component
Parameter</h1><p>It's not uncommon to create a component that has a bit of
complex behavior that you want to be able to easily control, and an enumerated
type (a Java enum) seems like the right approach.</p><p>Our example comes from
Tapestry's Select component, which has a blankOption parameter that has an enum
type.</p><p>Let's start with the enum type itself:</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>BlankOption.java</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public enum BlankOption
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public enum BlankOption
{
/** Always include the blank option, even if the underlying property is
required. */
ALWAYS,
@@ -142,7 +144,7 @@
}
</pre>
</div></div><p>Next, we define the parameter:</p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>Select.java (partial)</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> /**
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> /**
* Controls whether an additional blank option is provided. The blank
option precedes all other options and is never
* selected. The value for the blank option is always the empty string,
the label may be the blank string; the
* label is from the blankLabel parameter (and is often also the empty
string).
@@ -151,7 +153,7 @@
private BlankOption blankOption;
</pre>
</div></div><p>Note the use of literal as the default prefix; this allows us
to use the name of the option in our template, e.g. <code><t:select
blankoption="never" .../></code>. Without the default prefix setting,
"never" would be interpreted as a property expression (and you'd see an error
when you loaded the page).</p><p>The final piece of the puzzle is to inform
Tapestry how to convert from a string, such as "never", to a BlankOption
value.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>TapestryModule.java (partial)</b></div><div class="codeContent
panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> public static void
contributeTypeCoercer(Configuration<CoercionTuple> configuration)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public static void
contributeTypeCoercer(Configuration<CoercionTuple> configuration)
{
. . .
Modified: websites/production/tapestry/content/environmental-services.html
==============================================================================
--- websites/production/tapestry/content/environmental-services.html (original)
+++ websites/production/tapestry/content/environmental-services.html Mon May 21
05:20:56 2018
@@ -81,7 +81,7 @@
<p>Environmental services represent yet another, distinct form of
injection.</p>
<p>Unlike service injection (injection via a service implementation's
constructor) or normal component injection (directly into component fields, via
the @Inject annotation) where the injected value is always the same, with
environmental services, the injected value is very late bound and
dynamic.</p></div><strong>Environmental services</strong> provide a conduit of
communication between two components (usually a component and the components it
encloses). The first component pushes an object of a certain type into the
<em>environment</em>, and then the second component can access that object
merely by defining an annotated property of the same type.<p>An example of how
this works is Tapestry's built-in <em>form support</em>. The <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/Form.html">Form</a>
component creates an object of type <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/t
apestry5/services/FormSupport.html">FormSupport</a> and pushes it into the
environment. Then, the enclosed form components can use that FormSupport object
to participate in both the rendering of the Form and the Form's eventual
submission. This is how control names and client-side ids are determined, how
fields register callbacks so that they can process their part of the
submission, and how fields hook themselves to client-side validation.</p><h1
id="EnvironmentalServices-Usingthe@Environmentalannotation">Using the
@Environmental annotation</h1><p>The @<a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/annotations/Environmental.html">Environmental</a>
annotation, when used in a component class, causes the associated field to be
replaced at runtime with a read-only value obtained from an Environment service
provided by an enclosing component.</p><p>A very common Environmental is <a
class="external-link" href="http://tapestry.apache.org/c
urrent/apidocs/org/apache/tapestry5/services/javascript/JavaScriptSupport.html">JavaScriptSupport</a>,
used when generating <a href="ajax-javascript.html">client-side
JavaScript</a>.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> @Inject @Path("${tapestry.scriptaculous}/dragdrop.js")
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> @Inject
@Path("${tapestry.scriptaculous}/dragdrop.js")
private Asset dragDropLibrary;
@Environmental
@@ -94,7 +94,7 @@
</pre>
</div></div><p>Environmental services are, by their nature, per-thread (and
therefore per-request).</p><p>Accessing an environmental field causes a lookup,
by type, against the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/Environment.html">Environment</a>
service.</p><p>Normally, an environmental of the specified type must be
available in the Environment, or an exception is thrown when accessing the
field. However, if the value of the Environmental annotation's value is false,
then the environmental value is optional.</p><h1
id="EnvironmentalServices-Placingavalueintheenvironment">Placing a value in the
environment</h1><p>The Environment service has push() and pop() methods to put
a value in the Environment, and discard it.</p><p>For example, say you were
building a tab-based menu system and you needed to allow an outer TabGroup
component to communicate with inner Tab components, to control various aspects
of presentation.<
/p><p>The relevant information could be exposed as an interface,
TabModel.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>TabGroup.java</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class TabGroup
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class TabGroup
{
@Inject
private Environment environment;
@@ -122,7 +122,7 @@ public class Tab
}
</pre>
</div></div><p>Notice that when pushing a value into the Environment, you
identify its type as well as the instance. Environment maintains a number of
stacks, one for each type. Thus, pushing a TabModel into the environment won't
disturb the RenderSupport or other environmentals already there.</p><p>What's
important here is that the code that pushes a environmental onto a stack should
also pop it off.</p><p>The enclosed class, Tab, has full access to whatever
object was pushed onto the stack by the TabGroup.</p><p>The reason why
Environment is a stack is so that a component can, when it makes sense, easily
replace or intercept access to an Environmental.</p><h1
id="EnvironmentalServices-FundamentalEnvironmentals">Fundamental
Environmentals</h1><p>Not all environmentals are pushed into the Environment by
components.</p><p>A number of environmentals are initialized as part of page
rendering, even before the first component starts to render. This
initialization is accomplished with <a
class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/MarkupRendererFilter.html">MarkupRendererFilter</a>
contributions to the <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/services/MarkupRenderer.html">MarkupRenderer</a>
service.</p><h1
id="EnvironmentalServices-AccessingEnvironmentalsinServices">Accessing
Environmentals in Services</h1><p>The Environmental annotation only works
inside components.</p><p>To access an Environmental inside a service
implementation, you must inject the Environment service and obtain values from
it using the peek() method.</p><p>If this is something that will occur
frequently, it is possible to create a service implementation that is "backed"
by the Environment. For example, RenderSupport is accessible as a normal
injection, because a service is built for it in TapestryModule:</p><div
class="code panel pdl" style="border-width: 1px;"><div class="codeContent
panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;"> public RenderSupport
buildRenderSupport(EnvironmentalShadowBuilder builder)
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default"> public RenderSupport
buildRenderSupport(EnvironmentalShadowBuilder builder)
{
return builder.build(RenderSupport.class);
}
Modified: websites/production/tapestry/content/error-page-recipe.html
==============================================================================
--- websites/production/tapestry/content/error-page-recipe.html (original)
+++ websites/production/tapestry/content/error-page-recipe.html Mon May 21
05:20:56 2018
@@ -86,20 +86,31 @@
+
+
<h3>Related Articles</h3>
<ul class="content-by-label"><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a href="error-page-recipe.html">Error Page Recipe</a>
+ <a href="runtime-exceptions.html">Runtime
Exceptions</a>
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
+
+ <div class="details">
+ <a
href="overriding-exception-reporting.html">Overriding Exception Reporting</a>
+
+
+ </div>
+ </li><li>
+ <div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
<a href="specific-errors-faq.html">Specific Errors
FAQ</a>
@@ -108,10 +119,10 @@
</div>
</li><li>
<div>
- <span class="icon aui-icon aui-icon-small
aui-iconfont-page-default" title="Page">Page:</span> </div>
+ <span class="icon aui-icon content-type-page"
title="Page">Page:</span> </div>
<div class="details">
- <a
href="overriding-exception-reporting.html">Overriding Exception Reporting</a>
+ <a href="error-page-recipe.html">Error Page Recipe</a>
</div>
@@ -120,7 +131,7 @@
<p>Simply upgrade your application web.xml to the 2.4 version (or newer), and
make a couple of changes:</p><div class="code panel pdl" style="border-width:
1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>web.xml</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><?xml version="1.0" encoding="UTF-8"?>
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><?xml version="1.0"
encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
@@ -151,7 +162,7 @@
</web-app>
</pre>
</div></div><p>Tapestry's filter must be marked as a handler for both standard
requests and errors. That's accomplished with the
<code><dispatcher></code> elements inside the
<code><filter-mapping></code> section.</p><p>You must then map error
codes to Tapestry URLs. In this case, the 404 error is send to the
<code>/error404</code> resource, which is really the "Error404" Tapestry
page.</p><p>We'll create a simple Error404 page, one that displays a message
and (in development mode) displays the details about the incoming
request.</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>Error404.tml</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><html
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_4.xsd">
<head>
<title>Resource not found.</title>
@@ -170,7 +181,7 @@
</body>
</html></pre>
</div></div><p>The page simply makes the request and productionMode properties
available:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeHeader panelHeader pdl" style="border-bottom-width:
1px;"><b>Error404.java</b></div><div class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">package com.example.newapp.pages;
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">package
com.example.newapp.pages;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.annotations.Property;
Modified: websites/production/tapestry/content/extending-the-if-component.html
==============================================================================
--- websites/production/tapestry/content/extending-the-if-component.html
(original)
+++ websites/production/tapestry/content/extending-the-if-component.html Mon
May 21 05:20:56 2018
@@ -78,7 +78,7 @@
<div id="content">
<div id="ConfluenceContent"><h1
id="ExtendingtheIfComponent-ExtendingtheIfComponent">Extending the If
Component</h1><p>The <a class="external-link"
href="http://tapestry.apache.org/current/apidocs/org/apache/tapestry5/corelib/components/If.html">If</a>
component can be made very flexible; its main parameter, <code>test</code>,
does not <em>have</em> to be bound to a boolean value, it merely has to be
bound to a value that can be <a
href="parameter-type-coercion.html">coerced</a> to boolean.</p><p>For example,
you may be working on an application that does a lot of <a
class="external-link"
href="http://lucene.apache.org/java/docs/index.html">Lucene</a> searches, and
you represent the results as a SearchResult object:</p><div class="code panel
pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>SearchResult.java</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public class SearchResult<T> {
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public class
SearchResult<T> {
public final Class<T> itemType;
public final List<T> items;
public final int size;
@@ -102,14 +102,14 @@
}
</pre>
</div></div><p>In a SearchResult, the <code>size</code> property is the
overall number of results from the search. The <code>items</code> list is a
single "page" of those results to present to the user, consisting of items from
<code>firstIndex</code> to <code>lastIndex</code> within the overall
set.</p><p>In your templates, you have to check to see if the SearchResult
exists, then see if it is empty, before you can get to the part that displays
the content:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:if test="searchResult">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><t:if
test="searchResult">
<t:if test="! searchResult.empty">
. . .
</t:if>
</t:if>
</pre>
</div></div><p>The first test checks to see if <code>searchResult</code> is
not null (null is treated as false). The second checks to see if the search
result is empty.</p><p>What we'd like is for the test to look at the
<code>searchResult</code> directly and treat an empty search result as false,
and a non-empty search result as true. This is similar to what Tapestry already
does for Collections.</p><p>This is just a matter of adding a <a
href="parameter-type-coercion.html">
<code>Coercion</code></a><code>:</code></p><div class="code panel pdl"
style="border-width: 1px;"><div class="codeHeader panelHeader pdl"
style="border-bottom-width: 1px;"><b>AppModule.java (partial)</b></div><div
class="codeContent panelContent pdl">
-<pre class="brush: java; gutter: false; theme: Default"
style="font-size:12px;">public static void
contributeTypeCoercer(Configuration<CoercionTuple> configuration) {
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: java;
gutter: false; theme: Default" data-theme="Default">public static void
contributeTypeCoercer(Configuration<CoercionTuple> configuration) {
add(configuration, SearchResult.class, Boolean.class,
new Coercion<SearchResult, Boolean>() {
@@ -128,7 +128,7 @@ private static <S, T> void add(Con
}
</pre>
</div></div><p>Inside this thicket of generics and brackets is the code that
treats a SearchResult as a boolean: <code>return
!input.isEmpty();</code>.</p><p>With this in place, the previous template can
be simplified:</p><div class="code panel pdl" style="border-width: 1px;"><div
class="codeContent panelContent pdl">
-<pre class="brush: xml; gutter: false; theme: Default"
style="font-size:12px;"><t:if test="searchResult">
+<pre class="syntaxhighlighter-pre" data-syntaxhighlighter-params="brush: xml;
gutter: false; theme: Default" data-theme="Default"><t:if
test="searchResult">
. . .
</t:if>
</pre>