Wiki Markup |
---|
{float:right|background=#eee} {contentbylabel:title=Related Articles|showLabels=false|showSpace=false|space=@self|labels=component-templates,component-classes} {float} |
You may 'll see frequent reference to a Layout Component in Tapestry documentation, but you won't find it such a component in the component reference. The Layout Component component is a component that you create to provide common elements across all of your pages.
In traditional servlet development, you may be familiar with the use of a JSP include to include a banner across the top of your page and a copyright message across the bottom. Tapestry doesn't have a mechanism for such includes – nor does it need one.In Tapestry, you could implement those recurring page elements as components (a banner component, a copyright component, etc.) and then add those components to every page.
But there's an even better way. Just create a layout component that provides the overall structure and recurring content for your pagesInstead, you create a layout component that acts as a template:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_03.xsd"> <head> <title>My Nifty Web Application</title> </head> <body> <div class="nav-top"> Nifty Web Application </div> <t:alerts/> <t:body/> <div class="nav-bottom"> (C) 20082012 NiftyWebCo, Inc. </div> </body> </html> |
...
The magic is in the <t:body/> element in the center; this will be replaced by each page's content, whatever that is.
In a real-world example, the two <div> elements in this example above might contain the typical repeating recurring content you'll see across the pages of a web application: banners (and banner ads!), menus, login forms and so forth. Often these layout components get very complex ... in fact, in many applications the Layout component grows can grow to be more as complex than almost as any other component.
...
Using the Layout in a Page
To use your layout component
...
The Alerts component is new in Tapestry 5.3; it allows the application to present alert messages to the client in a consistent way.
Layout is a regular component like other, with an ordinary component template. Like all component templates, it will be stored on the classpath (typically under src/main/resources).
Components must always have a Java class. But in this trivial example, the Layout component doesn't need any logic:
Code Block | ||
---|---|---|
| ||
@Import(stylesheet="context:css/site.css")
public class Layout
{
}
|
We use the @Import annotation (in 5.2 or later), as opposed to directly adding the <link> element to the template, for significant performance benefits described elsewhere. (For 5.0 and 5.1, use the deprecated @IncludeStyleSheet annotation instead.)
...
, just have each page in your application wrap itself in the layout, like this:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<html t:type="layout" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"> <h1>Welcome to the Nifty Web Application!</h1> <p> Would you like to <t:pagelink page="login">Log In</t:pagelink>? </p> </html> |
Note the "t:type="layout" part. That says, in effect, "wrap the layout component around my content".
The magic is in the <t:body/> element of the layout template; this will be replaced by each page's content, whatever that is.
Info |
---|
Remember that if your layout component includes a link to a resource such as an image or a stylesheet, you must use an absolute URL. The same component will be used for pages in many different folders, or with many different activation contexts, so relative URLs won't work. The best approach is to use the context binding prefix. |
This is an example of using the Layout component in a page (in this case, Welcome.tml). To keep our Welcome.tml page template relatively preview-able, we are using an <html> element and the t:type attribute to specify that it is a component. The At render time, the page's <html> tag will be removed, and replaced with the content from the Layout.tml template (which conveniently starts with an <html> element). The <t:body> element in Layout.tml will be replaced with the page-specific content here: the <h1> and <p> tags.
Any page in the application that follows this pattern, using the Layout component, will have the same look and feel.
Layout is a regular component like other, with an ordinary component template. Like all component templates, it will be stored on the classpath (typically under src/main/resources).
Components must always have a Java class. But in this trivial example, the Layout component doesn't need any logic:
Code Block | ||
---|---|---|
| ||
@Import(stylesheet="context:css/site.css")
public class Layout
{
}
|
We use the @Import annotation (in 5.2 or later), as opposed to directly adding the <link> element to the template, for significant performance benefits described elsewhere. (For 5.0 and 5.1, use the deprecated @IncludeStyleSheet annotation instead.)
You may find that your application has more than one look and feel: perhaps user registration pages have one look, while administrative pages have another. This can be accomplished by having multiple layout components (using any names you choose) and using those different layout types for different pages.
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<html t:type="commonLayout" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd">
<h1>Administrative Functions</h1>
<t:body/>
</html>
|
A more advanced example
Here's an example of a Layout component with a few more features. It has a "title" parameter, so that every page can pass in its own title to be rendered in the <title> tag and in an <h1> tag at the top of the HTML. There is also a "style" parameter that allows each page to pass in a block of CSS rules to be rendered in the <head> section of the page (useful for those few CSS rules that can't be put into a static CSS file). Notice the HTML5-style DOCTYPE declaration at the top, the charset definition as UTF-8, and the addition of an "alerts" component.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<!DOCTYPE html> <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"> <head> <meta charset="UTF-8"> <title>$title - NiftyWebCo, Inc</title> <style type="text/css"> <t:delegate to="style" /> </style> </head> <body> <div class="nav-top"> Nifty Web Application </div> <h1>${title}</h1> <t:alerts/> <t:body/> <div class="nav-bottom"> (C) 2012 NiftyWebCo, Inc. </div> </body> </html> |
The Alerts component above is new in Tapestry 5.3; it allows the application to present alert messages to the client in a consistent way. If you want alerts to always appear in the banner of your web site, it may make sense to put it in the layout component's template, as above.
The corresponding component class is still very simple, adding support for the "title" and "style" parameters:
Code Block | ||
---|---|---|
| ||
@Import(stylesheet="context:css/site.css")
public class Layout
{
/** The page title, for the <title> element and the <h1>element. */
@Property
@Parameter(required = true, defaultPrefix = BindingConstants.LITERAL)
private String title;
/** Optional CSS rules to place into the page head */
@Property
@Parameter(defaultPrefix = BindingConstants.LITERAL)
private Block style;
}
|
Here's how you might use the above layout component for a UserList page:
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<html t:type="layout" title="List of Users"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"
xmlns:p="tapestry:parameter">
<p:style>
TD.profile { background: url('${backgroundImage}') }
</p:style>
<div>
Imagine a table of user account information here.
</div>
</html>
|
The <p:style> element (and its contents) are passed to the layout component as a style
parameter (a block parameter, in this case). The rendered HTML would look like the following (assuming UserList.java has a backgroundImage property whose value is the string "http://www.example.com/fuzzy.gif"):
Code Block | ||||
---|---|---|---|---|
| ||||
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>List of Users - NiftyWebCo, Inc</title> <style type="text/css"> TD.profile { background: url('http://www.example.com/fuzzy.gif') } </style> </head> <body> <div class="nav-top"> Nifty Web Application </div> <h1>List of Users</h1> <div id="alerts"></div> <div> Imagine a table of user account information here. </div> <div class="nav-bottom"> (C) 2012 NiftyWebCo, Inc. </div> </body> </html> |