Using a tapestry5 layout with several content blocks

In tapestry5, you can “skin” your pages using a layout component (see here). You basically create a layout class (make sure it is in a “components” package) (you can choose the name yourself, to show this I explicitly used “MyLayout” as name).

public class MyLayout
{
}

This is needed because tapestry uses class names to search for the matching templates. You can now create the actual template (called MyLayout.tml).

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<head>
    <title>My simple page</title>
</head>
<body>

<div style="float: left; width: 200px;" id="left">
    <p>I want some content in on the left</p>
</div>

<!-- and the page content goes on the right -->
<div id="content">
    <t:body/>
</div>
</body>
</html>

Note that your templates need to be proper xml, so you need matching closing tags in there.
If you want to use this, you can create a start page using the following class and template (this time in the pages package).

public class Start
{
    public Date getCurrentTime()
    {
        return new Date();
    }
}

We have provided a getter for the current time to include this in our example page. That way at least there is something dynamic in there already.

<t:mylayout xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <p> This is the start page for this application, a good place to start your modifications.
        Just to prove this is live: </p>

    <p> The current time is: ${currentTime}. </p>
</t:mylayout>

Because “t:mylayout” is used as root tag, tapestry will look for the “mylayout” component and replace the “t:body” tag in there with the content from this template. When tapestry looks for components, in looks for classes in the components package (the start of the package name is defined by the application module)
This works fine, but what if you want to have page specific content for more than one area in the layout?
This can be solved using a layout parameter. This is a block that is injected into the layout, and defined in the page. Let’s improve the example by defining the page title (and possibly other stuff for the header, and the left content.
The page class stays the same, but the template needs to define the parameters.

<t:mylayout xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
    <t:parameter name="title">
        <title>this is a page specific title</title>
    </t:parameter>
    <t:parameter name="left">
        <p>A simple paragraph for the left column.</p>        
    </t:parameter>

    <p> This is the start page for this application, a good place to start your modifications.
        Just to prove this is live: </p>

    <p> The current time is: ${currentTime}. </p>
</t:mylayout>

We have to modify the MyLayout template to include these parameters.

<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
<head>
    <t:delegate to="title"/>
</head>
<body>

<div style="float: left; width: 200px;" id="left">
    <t:delegate to="left"/>
</div>

<!-- and the page content goes on the right -->
<div id="content">
    <t:body/>
</div>
</body>
</html>

The “t:delegate” includes a block component which needs is injected in the MyLayout class (thanks to the “t:parameter” stuff in the page).

public class MyLayout
{
    @Parameter
    private Block left;

    @Parameter
    private Block title;

    public Block getLeft()
    {
        return left;
    }

    public void setLeft( Block explanation )
    {
        this.left = left;
    }

    public Block getTitle()
    {
        return title;
    }

    public void setTitle( Block title )
    {
        this.title = title;
    }
}

721 Comments

  1. Lucien says:

    I was stuck with the official example (http://tapestry.apache.org/layout-component.html) until I replace (in the .tml page) “<html t:type="layout"" with "<t:mylayout", following your example.

    Thanks you for the article 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

question razz sad evil exclaim smile redface biggrin surprised eek confused cool lol mad twisted rolleyes wink idea arrow neutral cry mrgreen

*