Tips on Tiles

Here are some tips on using tiles.

Nested tiles

Problem

How do you do nested tiles? For example, suppose my .mainLayout is header/body/footer tiles.

Header

Body

Footer

However, for the edit page, I want to compose "body" from multiple subtiles.

Header

A

B

Footer

layout.jsp:

   <tiles:insert attribute="header" />
   <tiles:insert attribute="body"/ >
   <tiles:insert attribute="footer" />

editBody.jsp:

   <table>
      <tr>
         <td><tiles:insert attribute="a"/></td>
         <td><tiles:insert attribute="b"/></td>
      </tr>
   </table>

So, had do I set the values of "a" and "b" from tiles-def.xml?

There are two possible ways.

Solution #1

The first way is to use 2 definitions (plus the defaultLayout definition) in tiles-def.xml:

  <definition name="defaultLayout" template="/WEB-INF/layout.jsp">
      <put name="header" value="/WEB-INF/header.jsp" />
      <!-- definitions based on this layout must define "body"  -->
      <put name="footer" value="/WEB-INF/footer.jsp" />
  </definition>

  <!-- first define the inner tile -->
  <definition name="editpage.body" template="/WEB-INF/editBody.jsp">
      <put name="a" value="/WEB-INF/a.jsp" />
      <put name="b" value="/WEB-INF/b.jsp" />
  </definition>

   <!-- then define the whole page by referencing the inner tile -->
  <definition name="editpage" extends="defaultLayout">
      <put name="body" value="editpage.body"  type="definition"/>
  </definition> 

This is a versatile solution but on the downside the tiles-def.xml file gets big.

Solution #2

Another approach is to only use one definition (plus the defaultLayout definition) in the tiles-def.xml file.

tiles-def.xml:

   <definition name="defaultLayout" template="/WEB-INF/layout.jsp">
       <put name="header" value="/WEB-INF/header.jsp" />
       <!-- definitions based on this layout must define "body"  -->
       <put name="footer" value="/WEB-INF/footer.jsp" />
   </definition>

   <definition name="editPage" extends="defaultLayout">
       <put name="body" value="/WEB-INF/editBody.jsp" />
       <put name="a" value="/WEB-INF/a.jsp" />
       <put name="b" value="/WEB-INF/b.jsp" />
   </definition>

layout.jsp:

   <tiles:insert attribute="header">
   <tiles:insert attribute="body" >
       <!-- propogate "a" and "b" down to the next level -->
       <tiles:put name="a" beanName="a"/>
       <tiles:put name="b" beanName="b"/>
   </tiles:insert>
   <tiles:insert attribute="footer">

editBody.jsp:

   <table>
      <tr>
         <td><tiles:insert attribute="a"/></td>
         <td><tiles:insert attribute="b"/></td>
      </tr>
   </table>

The downside of this approach is that layout.jsp must know the list of possible arguments to (any) body.jsp page.

How do I refresh a single tile without changing the other ones?

This is a common question. You are getting confused between frames and tiles. Although frames and tiles can be combined, in general tiles are used in place of frames. In this case the server combines all the tiles into a single web page (without any frames), so you can't refresh just one tile. You have to refresh the whole page.

  • No labels