| <?xml version="1.0" encoding="UTF-8"?> |
| <!-- |
| Copyright 2004, 2005 The Apache Software Foundation |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| <document> |
| <properties> |
| <title>Page and component templates</title> |
| </properties> |
| <body> |
| |
| <section name="Page and component templates"> |
| <p> |
| Unlike many other web frameworks, such as |
| <a href="http://struts.apache.org/">Struts</a> |
| or |
| <a href="http://opensymphony.com/webwork/">WebWork</a> |
| , Tapestry does not "plug into" an external templating system such as JavaServer |
| Pages or |
| <a href="http://velocity.apache.org/">Velocity</a> |
| . Instead, Tapestry integrates its own templating system. |
| </p> |
| |
| <p> |
| Tapestry templates are designed to look like valid HTML files (component HTML |
| templates will just be snippets of HTML rather than complete pages). Tapestry |
| "hides" its extensions into special attributes of ordinary HTML elements. |
| </p> |
| |
| <p> |
| Don't be fooled by the terminology; we say "HTML templates" because that is the |
| prevalent use of Tapestry ... but Tapestry is equally adept at WML or XML. |
| </p> |
| |
| <subsection name="Template locations"> |
| <p> |
| The general rule of thumb is that a page's HTML template is simply an HTML file, |
| stored in the context root directory. That is, you'll have a |
| <em>MyPage</em>.html HTML template, a WEB-INF/ |
| <em>MyPage</em>.page page specification, and a |
| <em>MyPage</em> class, in some Java package. |
| </p> |
| |
| <p> |
| Tapestry always starts knowing the name of the page and the location of the |
| page's specification when it searches for the page's HTML template. Starting |
| with this, it performs the following search: |
| </p> |
| |
| <ul> |
| <li>In the same location as the specification</li> |
| <li> |
| In the web application's context root directory (if the page is an |
| application page, not a page from a component library) |
| </li> |
| </ul> |
| |
| <p> |
| In addition, any HTML template in the web application context is considered a |
| page, even if there is no matching page specification. For simple pages that |
| don't need to have any page-specific logic or properties, there's no need for a |
| page specification. Such a page may still use the special Tapestry attributes |
| (described in the following sections). |
| </p> |
| |
| <p> |
| Finally, with some |
| <a href="configuration.html#configuration.search-path">minor configuration</a> |
| it is possible to change the extension used for templates. For example, if you |
| are developing a WML application, you may wish to name your application's |
| template files with the extension .wml. |
| </p> |
| |
| </subsection><!-- template.locations --> |
| |
| <subsection name="Template Contents"> |
| |
| |
| <p>Tapestry templates contain a mix of the following elements:</p> |
| |
| <ul> |
| <li>Static HTML markup</li> |
| <li>Tapestry components</li> |
| <li>Localized messages</li> |
| <li>Special template directives</li> |
| </ul> |
| |
| <p> |
| Usually, about 90% of a template is ordinary HTML markup. Hidden inside that |
| markup are particular tags that are placeholders for Tapestry components; these |
| tags are recognized by the presence of the jwcid attribute. "JWC" is short for |
| "Java Web Component", and was chosen as the "magic" attribute so as not to |
| conflict with any real HTML attribute. |
| </p> |
| |
| |
| <p> |
| Tapestry's parser is quite flexible, accepting all kinds of invalid HTML markup. |
| That is, attributes don't |
| <em>have</em> |
| to be quoted. Start and end tags don't have to balance. Case is ignored when |
| matching start and end tags. Basically, the kind of ugly HTML you'll find "in |
| the field" is accepted. |
| </p> |
| |
| <p> |
| The goal is to allow you to preview your HTML templates using a WYSIWYG HTML |
| editor (or even an ordinary web browser). The editor will ignore the undefined |
| HTML attributes (such as jwcid). |
| </p> |
| |
| <p> |
| A larger goal is to support real project teams: The special markup for Tapestry |
| is unobtrusive, even invisible. This allows an HTML designer to work on a |
| template without breaking the dynamic portions of it. Importantly, the designers |
| can work with their normal tools and editors. This is completely unlike JSPs, |
| where the changes to support dynamic output are extremely intrusive and result |
| in a file that is meaningless to an HTML editor. |
| </p> |
| |
| </subsection><!-- template.contents --> |
| |
| <subsection name="Components in templates"> |
| |
| |
| <p> |
| Components can be placed anywhere inside a template, simply by adding the jwcid |
| attribute to any existing tag. For example: |
| </p> |
| |
| <source xml:space="preserve"><html> |
| <head> |
| <title>Example HTML Template</title> |
| </head> |
| <body |
| <span jwcid="border"> |
| |
| Hello, |
| <span jwcid="@Insert" value="ognl:user.name">Joe User</span> |
| </span> |
| </body> |
| </html></source> |
| |
| <p> |
| The first span is a reference to a |
| <em>declared component</em> |
| ; the type and parameters of the component are declared in the page's |
| specification. |
| </p> |
| |
| <p> |
| The second span is an |
| <em>implicit component</em> |
| ; the type of the component is |
| <a href="../components/general/insert.html">Insert</a> |
| . The value parameter is bound to the |
| <a href="http://www.ognl.org">OGNL</a> |
| expression |
| <code>user.name</code> |
| . |
| </p> |
| |
| <p> |
| The point of all this is that the HTML template should preview properly in a |
| WYSIWYG HTML editor. Unlike |
| <a href="http://jakarta.apache.org/velocity/">Velocity</a> |
| or JSPs, there are no strange directives to get in the way of a preview (or |
| necessitate a special editting tool), Tapestry hides what's needed inside |
| existing tags; at worst, it adds a few non-standard attributes (such as jwcid) |
| to tags. This rarely causes a problem with most HTML editors. |
| </p> |
| |
| <p> |
| Templates may contain components using two different styles. |
| <em>Declared components</em> |
| are little more than a placeholder; the type of the component is defined |
| elsewhere, in the page (or component) specification. |
| </p> |
| |
| <p> |
| Alternately, an |
| <em>implicit component</em> |
| can be defined in place, by preceding the component type with an "@" symbol. |
| Tapestry includes over forty components with the framework, additional |
| components may be created as part of your application, or may be provided inside |
| a component library. |
| </p> |
| |
| <p> |
| In the above example, a <span> was used for both components. Tapestry |
| doesn't care what tag is used for a component, as long as the start and end tags |
| for components balance (it doesn't even care if the case of the start tag |
| matches the case of the end tag). The example could just as easily use |
| <div> or <fred>, the rendered page sent back to the client web |
| browser will be the same. |
| </p> |
| |
| <p> |
| The default attribute name is |
| <code>jwcid</code> |
| , but there are occasions when that is not desirable. The |
| org.apache.tapestry.jwcid-attribute-name |
| <a href="configuration.html#configuration.properties">configuration property</a> |
| allows you to control the template parser's behavior. |
| </p> |
| |
| <subsection name="Component bodies"> |
| |
| |
| <p> |
| In Tapestry, each component is responsible for rendering itself and its |
| <em>body</em> |
| . A component's body is the portion of its page's template that its tags |
| encloses. The Tapestry HTML template parser is responsible for dividing up |
| the template into chunks: blocks of static HTML, component start tags |
| (recognized by the jwcid attribute) and matching component end tags. It is |
| quite forgiving about case, quotes (which may be single quotes, double |
| quotes, or even omitted), and missing close tags (except for components, |
| which must be balanced). |
| </p> |
| |
| <span class="info"> |
| <strong>Note:</strong> |
| <p> |
| More correct would be to say "its container's template" as a component |
| may be contained within another component. For simplicities sake, we'll |
| describe this as if it was always a simple two-level heirarchy even |
| though practical Tapestry applications can be many levels deep. |
| </p> |
| </span> |
| |
| <img alt="Component templates and bodies" |
| src="../images/UsersGuide/component-body.png" /> |
| |
| <p> |
| In most cases, a component will make use of its body; it simply controls if, |
| when and how often its body is rendered (when rendering the HTML response |
| sent to the client). Other components, such as |
| <a href="../components/general/insert.html">Insert</a> |
| , have no use for their bodies, which they discard. Each component declares |
| in its own specification (the allow-body attribute of the |
| <a href="spec.html#spec.component-specification"> |
| <component-specification> |
| </a> |
| ) whether is allows or discards its body. |
| </p> |
| |
| <p> |
| In the previous example, the |
| <a href="../components/general/insert.html">Insert</a> |
| component had a body, the text "Joe User". This supports WYSIWYG preview; |
| the text will be displayed when previewing. Since the |
| <a href="../components/general/insert.html">Insert</a> |
| component discards its body, this text will not be used at runtime, instead |
| the OGNL expression |
| <code>user.name</code> |
| will be evaluated and the result inserted into the response. |
| </p> |
| |
| <span class="warn"> |
| <strong>Warning:</strong> |
| <p> |
| If you put a component inside the body of an |
| <a href="../components/general/insert.html">Insert</a> |
| (or any other component that discards its body), then Tapestry will |
| throw an exception. You aren't allowed to create a component simply to |
| discard it. |
| </p> |
| </span> |
| |
| </subsection><!-- templates.components.body --> |
| |
| <subsection name="Component ids"> |
| |
| |
| <p> |
| Every component in Tapestry has its own id. In the above example, the first |
| component has the id "border". The second component is anonymous; the |
| framework provides a unique id for the component since one was not supplied |
| in the HTML template. The framework provided id is built from the |
| component's type; this component would have an id of |
| <code>$Insert</code> |
| ; other |
| <a href="../components/general/insert.html">Insert</a> |
| components would have ids |
| <code>$Insert$0</code> |
| , |
| <code>$Insert$1</code> |
| , etc. |
| </p> |
| |
| <p> |
| A component's id must only be unique within its immediate container. Pages |
| are top-level containers, but components may have their own templates, and |
| so can also contain other components. |
| </p> |
| |
| |
| <p> |
| Implicit components can also have a specific id, by placing the id in front |
| of the "@" symbol: |
| </p> |
| |
| <source xml:space="preserve"> |
| <span jwcid="insert@Insert" value="ognl:user.name">Joe User</span> |
| </source> |
| |
| <p> |
| The component is still implicit; nothing about the component would go in the |
| specification, but the id of the component would be |
| <code>insert</code> |
| . |
| </p> |
| |
| <p> |
| Providing explicit ids for your components is rarely required, but often |
| beneficial. It is especially useful for form control components. |
| </p> |
| |
| <p> |
| Each component may only appear |
| <em>once</em> |
| in the template. You simply can't use the same component repatedly ... but |
| you can duplicate a component fairly easily; make the component a declared |
| component, then use the copy-of attribute of the |
| <a href="spec.html#spec.component"><component></a> |
| element to create clones of the component with new ids. |
| </p> |
| |
| |
| </subsection><!-- templates.components.ids --> |
| |
| <subsection name="Specifying parameters"> |
| |
| |
| <p> |
| Components are configured by |
| <em> |
| <a href="bindings.html">binding</a> |
| </em> |
| their parameters. In a page or component specification, the |
| <a href="spec.html#spec.binding"><binding></a> |
| element is used to bind component parameters. |
| </p> |
| |
| <p> |
| Inside an HTML template, attributes of the tag are used to bind parameters. |
| This can be very succinct. In some cases where an |
| <a href="http://www.ognl.org">OGNL</a> |
| expression is used, the value can become quite long or complex ... in which |
| case, converting the component to be a declared component (that is, defined |
| in the page or component specification) and using the |
| <a href="spec.html#spec.binding"><binding></a> |
| element will be more manageable. |
| </p> |
| |
| |
| <p> |
| Tapestry will |
| <em>merge</em> |
| together parameter bindings in the specification with those provided |
| directly in the template. Generally speaking, conflicts (the same parameter |
| bound in both places) will be an error. The exception is when the parameter |
| bound in the HTML template, as an attribute, is a literal string value ... |
| in which case, Tapestry assumes that the attribute value is there for |
| WYSIWYG purposes and is quietly ignored. |
| </p> |
| |
| |
| <p> |
| Components may have both |
| <em>formal</em> |
| and |
| <em>informal</em> |
| parameters. The component specification defines each formal parameters using |
| the |
| <a href="spec.html#spec.parameter"><parameter></a> |
| element, and a component indicates whether it accepts or rejects informal |
| parameters with the allow-informal-parameters attribute of the |
| <a href="spec.html#spec.component-specification"> |
| <component-specification> |
| </a> |
| element. |
| </p> |
| |
| <p> |
| Informal parameters are |
| <em>not</em> |
| limited to simply strings; using |
| <a href="bindings.html">binding reference</a> |
| prefixes, it is possible for them to be OGNL expressions, references to |
| assets, or anything else. |
| </p> |
| |
| <p> |
| If a component does not allow informal parameters, then attempting to bind |
| any parameters (beyond the formal set of parameters for the component) is an |
| error. The exception to this is literal values in the template, which are |
| (again) assumed to be there for WYSIWYG purposes, and quietly ignored. |
| </p> |
| |
| <p>Two final notes about informal parameters:</p> |
| |
| <ul> |
| <li> |
| Informal parameters in the template are assumed to be literal strings |
| unless they have a binding prefix (i.e., "ognl:", "message:", or so |
| forth). |
| </li> |
| <li> |
| Informal parameters are normally converted to string values and added as |
| additional attributes in the output markup. A special case is when the |
| value for an informal parameter is an |
| <a |
| href="../apidocs/org/apache/tapestry/IAsset.html"> |
| IAsset |
| </a> |
| (possibly specified with the "asset:" prefix), in which case the |
| attribute value will be the |
| <em>URL</em> |
| for the asset. |
| </li> |
| </ul> |
| |
| <subsection name="Seperation of Concerns"> |
| |
| |
| <p> |
| Before Tapestry 3.0, there was a more clear separation of concerns. The |
| template could only have declared components (not implicit), and any |
| informal attributes in the template were always static values. The type |
| of the component and all its formal parameters were always expressed in |
| the specification. The template was very much focused on presentation, |
| and the specification was very much focused on business logic. There |
| were always minor exceptions to the rules, but in general, seperation of |
| concerns was very good. |
| </p> |
| |
| <p> |
| With Tapestry 3.0, you can do more in the HTML template, and the |
| specification file is much less important ... but the seperation of |
| concerns is much more blurred together. It is very much acceptible to |
| mix and match these approaches, even within a single page. In general, |
| when learning Tapestry, or when prototyping, it is completely appopriate |
| to do as much as possible in the HTML template. For large and complex |
| applications, there are benefits to moving as much of the dynamic logic |
| as possible out of the template and into the specification. |
| </p> |
| |
| </subsection> |
| |
| </subsection><!-- templates.components.parameters --> |
| |
| <subsection name="Formal and informal parameters"> |
| |
| |
| <p> |
| Components may accept two types of parameters: |
| <em>formal</em> |
| and |
| <em>informal</em> |
| . Formal parameters are those defined in the component's specification, |
| using the |
| <a href="spec.html#spec.parameter"><parameter></a> |
| element. Informal parameters are |
| <em>additional</em> |
| parameters, beyond those known when the component was created. |
| </p> |
| |
| <p> |
| The majority of components that accept informal parameters simply emit the |
| informal parameters as additional attributes. Why is that useful? Because it |
| allows you to specify common HTML attributes such as class or id, or |
| JavaScript event handlers, without requiring that each component define each |
| possible HTML attribute (the list of which expands all the time). |
| </p> |
| |
| <span class="info"> |
| <strong>Note:</strong> |
| <p> |
| If you are used to developing with JSPs and JSP tags, this will be quite |
| a difference. JSP tags have the equivalent of formal parameters (they |
| are called "tag attributes"), but nothing like informal parameters. |
| Often a relatively simply JSP tag must be bloated with dozens of extra |
| attributes, to support arbitrary HTML attributes. |
| </p> |
| </span> |
| |
| <p> |
| Informal and formal parameters can be specified in either the specification |
| or in the template. Informal parameters |
| <em>are not</em> |
| limited to literal strings, you may use the |
| <code>ognl:</code> |
| and |
| <code>message:</code> |
| prefixes with them as well. |
| </p> |
| |
| |
| <p> |
| Not all components allow informal parameters; this is controlled by the |
| allow-informal-parameters attribute of the |
| <a href="spec.html#spec.component-specification"> |
| <component-specification> |
| </a> |
| element. Many components do not map directly to an HTML element, those are |
| the ones that do not allow informal parameters. If a component forbids |
| informal parameters, then any informal parameters in the specification or |
| the template will result in errors, with one exception: static strings in |
| the HTML template are simply ignored when informal parameters are forbidden; |
| they are presumed to be there only to support WYSIWYG preview. |
| </p> |
| |
| <p> |
| Another conflict can occur when the HTML template specified an attribute |
| that the component needs to render itself. For example, the |
| <a href="../components/link/directlink.html">DirectLink</a> |
| component generates a |
| <code><a></code> |
| tag, and needs to control the href attribute. However, for preview purposes, |
| it often will be written into the HTML template as: |
| </p> |
| |
| <source xml:space="preserve"> |
| <a jwcid="@DirectLink" listener="listener:. . ." href="#"> . . . </a></source> |
| |
| |
| <p> |
| This creates a conflict: will the template href (the literal string "#") be |
| used, or the dynamically generated URL produced by the |
| <a href="../components/link/directlink.html">DirectLink</a> |
| component, or both? The answer is: the component wins. The href attribute in |
| the template is ignored. |
| </p> |
| |
| <p> |
| Each component declares a list of reserved names using the |
| <a href="spec.html#spec.reserved-parameter"><reserved-parameter></a> |
| element; these are names which are not allowed as informal parameters, |
| because the component generates the named attribute itself, and doesn't want |
| the value it writes to be overriden by an informal parameter. Case is |
| ignored when comparing attribute names to reserved names. |
| </p> |
| |
| </subsection><!-- template.components.formal --> |
| |
| |
| |
| </subsection><!-- template.components --> |
| |
| <subsection name="Template directives"> |
| |
| |
| <p> |
| For the most part, a Tapestry page or component template consists of just static |
| HTML intermixed with tags representing components (containing the jwcid |
| attribute). The overarching goal is to make the Tapestry extensions completely |
| invisible. |
| </p> |
| |
| <p> |
| Tapestry supports a limited number of additional directives that are not about |
| component placement, but instead address other concerns about integrating the |
| efforts of HTML developers with the Java developers responsible for the running |
| application. |
| </p> |
| |
| <subsection name="Localization"> |
| |
| |
| <p> |
| Tapestry includes a number of |
| <a href="localization.html">localization features</a> |
| localization features. As we've seen, it is possible to access the messages |
| for a page or component using the |
| <code>message:</code> |
| prefix on a component parameter. |
| </p> |
| |
| <p> |
| What about the static text in the template itself? How does that get |
| translated? One possibility would be to make use of the Insert component for |
| each piece of text to be displayed, for example: |
| </p> |
| |
| <source xml:space="preserve"> |
| <span jwcid="@Insert" value="message:hello">Hello</span></source> |
| |
| |
| <p> |
| This snippet will get the |
| <code>hello</code> |
| message from the page's message catalog and insert it into the response. The |
| text inside the <span> tag is useful for WYSIWYG preview, but will be |
| discarded at runtime in favor of a message string from the catalog, such as |
| "Hello", "Hola" or "Bonjour" (depending on the selected locale). |
| </p> |
| |
| <p> |
| Because, in an internationalized application, this scenario will occur with |
| great frequency, Tapestry includes a special directive to perform the |
| equivalent function: |
| </p> |
| |
| <source xml:space="preserve"> |
| <span key="hello">Hello</span></source> |
| |
| |
| <p> |
| This is not an |
| <a href="../components/general/insert.html">Insert</a> |
| component, but behaves in a similar way. The tag used |
| <em>must be</em> |
| <span>. You do not use the |
| <code>message:</code> |
| prefix on the message key ( |
| <code>hello</code> |
| ). You can't use OGNL expressions. |
| </p> |
| |
| <p> |
| Normally, the <span> does not render, just the message. However, if |
| you specify any additional attributes in the <span> tag (such as, |
| commonly, id, class, or style, to specify a CSS style), then the |
| <span> will render around the message. For example, the template: |
| </p> |
| |
| <source xml:space="preserve"> |
| <span class="error" key="invalid-access">Invalid Access</span></source> |
| |
| <p>might render as:</p> |
| |
| <source xml:space="preserve"> |
| <span class="error">You do not have the necessary access.</span> |
| </source> |
| |
| |
| <p> |
| In this example, the placeholder text "Invalid Access" was replaced with a |
| much longer message acquired from the message catalog. |
| |
| </p> |
| |
| <p> |
| In rare cases, your message may have pre-formatted HTML inside it. Normally, |
| output is filtered, so that any reserved HTML characters in a message string |
| are expanded to HTML entities. For example, a < will be expanded to |
| &lt; If this is not desired, add the attribute value |
| <code>raw="true"</code> |
| to the <span>. This defeats the filtering, and text in the message is |
| passed through as-is. |
| </p> |
| |
| |
| </subsection><!-- template.directives.l10n --> |
| |
| <subsection name="$remove$ jwcid 	 "> |
| |
| |
| <p> |
| HTML templates in Tapestry serve two purposes. On the one hand, they are |
| used to dynamically render pages that end up in client web browsers. On the |
| other hand, they allow HTML developers to use WYSIWYG editors to modify the |
| pages without running the full application. |
| </p> |
| |
| <p> |
| We've already seen two ways in which Tapestry accomidates WYSIWYG preview. |
| Informal component parameters may be quietly dropped if they conflict with |
| reserved names defined by the component. Components that discard their body |
| may enclose static text used for WYSIWYG prefix. |
| </p> |
| |
| <p> |
| In some cases, we need even more direct control over the content of the |
| template. Consider, for example, the following HTML template: |
| </p> |
| |
| <source xml:space="preserve"> |
| <table> |
| <tr> |
| <th>First Name</th> |
| <th>Last Name</h> |
| </tr> |
| <tr jwcid="loop"> |
| <td><span jwcid="insertFirstName">John</span></td> |
| <td><span jwcid="insertLastName">Doe</span></td> |
| </tr> |
| <tr> |
| <td>Frank</td> |
| <td>Smith</td> |
| </tr> |
| <tr> |
| <td>Jane</td> |
| <td>Jones</td> |
| </tr> |
| </table> |
| </source> |
| |
| <p> |
| This is part of the HTML template that writes out the names of a list of |
| people, perhaps from some kind of database. When this page renders, the |
| <code>loop</code> |
| component (presumably a |
| <a href="../components/general/for.html">Foreach</a> |
| , such details being in the page's specification) will render its body zero |
| or more times. So we might see rows for "Frank Miller", "Alan Moore" and so |
| forth (depending on the content of the database). However, every listing |
| will also include "Frank Smith" and "Jane Jones" ... because the HTML |
| developer left those two rows in, to ensure that the layout of the table was |
| correct with more than one row. |
| </p> |
| |
| <p> |
| Tapestry allows a special jwcid, |
| <code>$remove$</code> |
| , for this case. A tag so marked is not a component, but is instead |
| eliminated from the template. It is used, as in this case, to mark sections |
| of the template that are just there for WYSIWYG preview. |
| </p> |
| |
| <span class="info"> |
| <strong>Note:</strong> |
| <p> |
| Normally, |
| <code>$remove$</code> |
| would not be a valid component id, because it contains a dollar sign. |
| </p> |
| </span> |
| |
| <p>With this in mind, the template can be rewritten:</p> |
| |
| |
| <source xml:space="preserve"> |
| <table> |
| <tr> |
| <th>First Name</th> |
| <th>Last Name</h> |
| </tr> |
| <tr jwcid="loop"> |
| <td><span jwcid="insertFirstName">John</span></td> |
| <td><span jwcid="insertLastName">Doe</span></td> |
| </tr> |
| <tr jwcid="$remove$"> |
| <td>Frank</td> |
| <td>Smith</td> |
| </tr> |
| <tr jwcid="$remove$"> |
| <td>Jane</td> |
| <td>Jones</td> |
| </tr> |
| </table> |
| </source> |
| <p> |
| With the |
| <code>$remove$</code> |
| blocks in place, the output is as expected, one table row for each row read |
| from the database, and "Frank Smith" and "Jane Jones" nowhere to be seen. |
| </p> |
| |
| <span class="warn"> |
| <strong>Warning:</strong> |
| <p> |
| It's not allowed to put components inside a removed block. This is |
| effectively the same rule that prevents components from being put inside |
| discarded component bodies. Tapestry will throw an exception if a |
| template violates this rule. |
| </p> |
| </span> |
| |
| |
| </subsection><!-- template.directives.remove --> |
| |
| <subsection name="$content$ jwcid"> |
| |
| |
| <p> |
| In Tapestry, components can have their own templates. Because of how |
| components integrate their own templates with their bodies (the portion from |
| their container's template), you can do a lot of interesting things. It is |
| very common for a Tapestry application to have a Border component: a |
| component that produces the <html>, <head>, and <body> |
| tags (along with additional tags to reference stylesheets), plus some form |
| of navigational control (typically, a nested table and a collection of links |
| and images). |
| </p> |
| |
| <p> |
| Once again, maintaining the ability to use WYSIWYG preview is a problem. |
| Consider the following: |
| </p> |
| |
| <source xml:space="preserve"> |
| <html> |
| <head> |
| <title>Home page</title> |
| <link ref="stylesheet" href="style.css" type="text/css"/> |
| </head> |
| <body> |
| <span jwcid="border"> |
| |
| <!-- Page specific content: --> |
| |
| <form jwcid=". . ."> |
| . . . |
| </form> |
| </span> |
| </body> |
| </html> |
| </source> |
| |
| |
| |
| <p> |
| It is quite common for Tapestry applications to have a |
| <em>Border</em> |
| component, a component that is used by pages to provide the <html>, |
| <head>, and <body> tags, plus common navigational features |
| (menus, copyrights, and so forth). In this example, it is presumed that the |
| <code>border</code> |
| component is a reference to just such as component. |
| </p> |
| |
| <p> |
| When this page renders, the page template will provide the <html>, |
| <head> and <body> tags. Then when the |
| <code>border</code> |
| component renders, it will |
| <em>again</em> |
| render those tags (possibly with different attributes, and mixed in with |
| much other stuff). |
| </p> |
| |
| <p> |
| If we put a |
| <code>$remove$</code> |
| on the <html> tag in the page template, the entire page will be |
| removed, causing runtime exceptions. |
| </p> |
| |
| <p> |
| Instead, we want to identify that the portion of the template |
| <em>inside</em> |
| the <body> tag (on the page template) as the only part that should be |
| used. The |
| <code>$content$</code> |
| component id is used for this purpose: |
| </p> |
| |
| <source xml:space="preserve"> |
| <html> |
| <head> |
| <title>Home page</title> |
| <link ref="stylesheet" href="style.css" type="text/css"/> |
| </head> |
| <body jwcid="$content$"> |
| <span jwcid="border"> |
| |
| <!-- Page specific content: --> |
| |
| <form jwcid=". . ."> |
| . . . |
| </form> |
| </span> |
| </body> |
| </html> |
| </source> |
| |
| |
| <p> |
| The <body> tag, the text preceding its open tag, the </body> |
| tag, and the text following it are all removed. It's as if the template |
| consisted only of the <span> tag for the |
| <code>border</code> |
| component. |
| </p> |
| |
| </subsection><!-- template.directives.content --> |
| |
| |
| </subsection><!-- template.directives --> |
| |
| </section> |
| |
| |
| </body> |
| </document> |