How properly write and use definitions in thymeleaf-extras-tiles2 ?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

How properly write and use definitions in thymeleaf-extras-tiles2 ?

blandger
Hi folks.
I previously used sitemesh library, but now I tried to use Tiles with thymeleaf.
I not quite understand how properly use it. Here is my example. Currently I have working thymeleaf-extras-tiles2 in project.
I can use one 'full layout' (top + body + footer) for all pages in project, but I need some 'internal' pages do not have 'full layout' , but rather use 'body + footer', 'body only' layouts. I can't get it working as not quite understand my mistake.

I have following folder structure in web module, nothing special.
WEB-INF\tiles-defs.xml

WEB-INF\templates\
(contains all thymeleaf pages) as well as 'internal pages' in sub-folders
say they are :
             \templates\index.html
             \templates\login.html
             \templates\profile\profile.html

WEB-INF\templates\include\
                           blank.html, footer.html, header.html, layout.html, layoutWithoutTop.html, layoutBodyOnly.html
(contains all thymeleaf tiles pieces)

In 'top level' WEB-INF\tiles-defs.xml I created following definitions:
<tiles-definitions>

    <definition name="baseBodyOnly" template="include/layoutBodyOnly" templateType="thymeleaf">
        <put-attribute name="body" value="include/blank :: bodyContent" type="thymeleaf"/>
    </definition>

    <definition name="baseWithoutTopMenu" template="include/layoutWithoutTop" templateType="thymeleaf">
        <put-attribute name="body" value="include/blank :: bodyContent" type="thymeleaf"/>
        <put-attribute name="footer" value="include/footer :: footerBlock" type="thymeleaf"/>
    </definition>

    <definition name="baseLayout" template="include/layout" templateType="thymeleaf">
        <put-attribute name="topMenu" value="include/header :: topMenuBlock" type="thymeleaf"/>
        <put-attribute name="body" value="include/blank :: bodyContent" type="thymeleaf"/>
        <put-attribute name="footer" value="include/footer :: footerBlock" type="thymeleaf"/>
    </definition>
..........
So I made THREE definitions with 3 different sets of 'make ups'. First markup/definition is 'body only', second - body + footer, third 'layout' - top + body + footer.

Here is my WEB-INF\templates\include\layout.html  for 'maximal' number included pieces:
<!DOCTYPE html>
<html........>
<head>
    <title tiles:substituteby="title">Layout Title</title>
..........
</head>
<body>
<div tiles:include="topMenu">Top Menu Block Content</div>
<div tiles:substituteby="body">Main Page Body Content</div>
<div tiles:substituteby="footer">Footer Block</div>
</body>
</html>
The other TWO htmls - layoutWithoutTop.html, layoutBodyOnly.html  have less pieces in HTML. I'm skipping them because they are similar to WEB-INF\templates\include\layout.html

My typical 'content page' has following structure, e.g. profile/profile.html:
<!DOCTYPE html>
<html lang="en".....>
<head>
    <title th:text="#{profile.page.title}">Profile Details</title>
</head>
<body>
<div id="main" tiles:fragment="bodyContent">
       /////// BODY CONTENT FOR PROFILE PAGE /////
</div>
</body>
</html>

Then I have following definition inside WEB-INF\tiles-defs.xml that can be applied to ALL pages in FULL project:
    <definition name="**" extends="baseLayout">
        <put-attribute name="title" value="{1} :: titleContent" type="thymeleaf"/>
        <put-attribute name="body" value="{1} :: bodyContent" type="thymeleaf" />
    </definition>
All works fine at that point.

Now my question... I want profile/profile.html page to be constructed WITHOUT top block. So I'm putting following definition inside WEB-INF\tiles-defs.xml  just before <definition name="**"
<raw>
........
    <definition name="profile/profile" extends="baseWithoutTopMenu">
        <put-attribute name="title" value="{1} :: titleContent" type="thymeleaf"/>
        <put-attribute name="body" value="{1} :: bodyContent" type="thymeleaf" />
    </definition>
    <definition name="**" extends="baseLayout">
     ..............
</tiles-definitions>


But I'm getting error:
org.springframework.web.util.NestedServletException: Request processing failed; 
nested exception is org.thymeleaf.exceptions.TemplateInputException: 
Error resolving template "{1}", template might not exist 
or might not be accessible by any of the configured Template Resolvers (include/layoutWithoutTop:8)
......

1. How properly use {1} in <definition name="profile/profile" ????

2. Is it possible to 'inherit' tiles definitions:
<definition name="baseBodyOnly"....
<definition name="baseWithoutTopMenu" .....
<definition name="baseLayout" ...
inside OTHER xml config files, say in:
WEB-INF\profile\tiles-defs.xml having 'separated' definitions like:

    <definition name="profile/*" extends="baseBodyOnly">
        <put-attribute name="title" value="{1} :: titleContent" type="thymeleaf"/>
        <put-attribute name="body" value="{1} :: bodyContent" type="thymeleaf" />
    </definition>

Will that work ?
Reply | Threaded
Open this post in threaded view
|

Re: How properly write and use definitions in thymeleaf-extras-tiles2 ?

danielfernandez
Administrator
Hi,

blandger wrote
1. How properly use {1} in <definition name="profile/profile" ????

Tiles (not Thymeleaf) allows you to use placeholders like "{1}" only when you have wildcards like "*" in your definition name. So if you are setting your definition to "profile/profile", you cannot use "{1}". You should write "profile/profile" instead.



blandger wrote
2. Is it possible to 'inherit' tiles definitions:
<definition name="baseBodyOnly"....
<definition name="baseWithoutTopMenu" .....
<definition name="baseLayout" ...
inside OTHER xml config files, say in:
WEB-INF\profile\tiles-defs.xml having 'separated' definitions like:

    <definition name="profile/*" extends="baseBodyOnly">
        <put-attribute name="title" value="{1} :: titleContent" type="thymeleaf"/>
        <put-attribute name="body" value="{1} :: bodyContent" type="thymeleaf" />
    </definition>

Will that work ?

Definition inheritance works OK with Thymeleaf. I recommend you to have a look at this example application https://github.com/danielfernandez/spring-webflow-samples/tree/thymeleaf/booking-mvc which is a thymeleaf-adaptation of a standard SpringSource app. Tiles is used, and as you will be able to see, a set of basic Tiles definitions are kept in a file apart and then used with "extends".

Regards,
Daniel


Reply | Threaded
Open this post in threaded view
|

Re: How properly write and use definitions in thymeleaf-extras-tiles2 ?

blandger
Thanks a lot Daniel.
As usually there are a few people can give good advice.

Could you please mention about that example and make a link to it on README.markdown page https://github.com/thymeleaf/thymeleaf-extras-tiles2  ?? Or may be I can do that?

The provided explanation on page is not quite good. I mean about tiles intself. I understand that page is about thymeleaf integration, but it would be better to have more clear examples as well.
Reply | Threaded
Open this post in threaded view
|

Re: How properly write and use definitions in thymeleaf-extras-tiles2 ?

blandger
In reply to this post by danielfernandez
danielfernandez wrote
Tiles (not Thymeleaf) allows you to use placeholders like "{1}" only when you have wildcards like "*" in your definition name. So if you are setting your definition to "profile/profile", you cannot use "{1}". You should write "profile/profile" instead.
I looked booking-mvc example and wanted clarify some rules.

Is there something special in rules used in example? I mean following...

1.
In upper config file - \WEB-INF\views.xml  the following rule in applied to all 'upper level' pages in root folder:
<definition name="intro" extends="standardLayout">
        <put-attribute name="body" value="/intro.html :: content" type="thymeleaf"/>
................

but I file below in folder - WEB-INF\hotels\views.xml  one of the rules is used with wildcard (*):
definition name="hotels/*" extends="standardLayout" templateType="thymeleaf">
      <put-attribute name="body" value="/hotels/{1}.html :: content" type="thymeleaf"/>
..........
Why the same rule was not used for #1 case ? Is it not possible there?


2.
In the next config - WEB-INF\hotels\booking\views.xml
the used rule is similar to #1 again:
<definition name="enterBookingDetails" extends="standardLayout" templateType="thymeleaf">
		<put-attribute name="body" value="/hotels/booking/enterBookingDetails.html :: content" type="thymeleaf"/>
.............

but what was wrong for using the rule #2 (with *) for that pages? Say like:
definition name="hotels/booking/*" extends="standardLayout" templateType="thymeleaf">
      <put-attribute name="body" value="/hotels/booking/{1}.html :: content" type="thymeleaf"/>
.............
Is that possible and works?


3.
Is is permitted to use one 'broad/wide pages rule: like:
    <definition name="**" extends="baseLayout">
        <put-attribute name="title" value="{1} :: titleContent" type="thymeleaf"/>
        <put-attribute name="body" value="{1} :: bodyContent" type="thymeleaf" />
    </definition>
<raw>

and use the more 'narrow page rules' inside other, internal config files like:
<raw>
<definition name="profile/profile" extends="baseLayout">
        <put-attribute name="title" value="/profile/profile :: titleContent" type="thymeleaf"/>
........
trying 'overwrite/override'  broad/wide rule by internal 'narrow rules' ? Is that possible?
Reply | Threaded
Open this post in threaded view
|

Re: How properly write and use definitions in thymeleaf-extras-tiles2 ?

blandger
In reply to this post by danielfernandez
4.
One more problem I run into.
I run web-app with thymeleaf as 'canvas Facebook' application and there is something strange.
I rewrote and rearrange tiles definitions in several config files. All looks good when it runs in browser, but something breaks inside FB canvas iframe.

I wonder, if that can be related to thymelaef + tiles integration somehow?
I can successfully access page by URL like: http://127.0.0.1:8080/profile  via controller class and forward to /profile/ptofile.html

but when I try to forward to the same url inside 'canvas' (iframe), something goes wrong and I'm getting error:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.apache.tiles.definition.NoSuchDefinitionException: /profile
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:927)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:822)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
.........
org.apache.tiles.definition.NoSuchDefinitionException: /profile
org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:625)
	org.apache.tiles.impl.BasicTilesContainer.render(BasicTilesContainer.java:321)
	org.thymeleaf.extras.tiles2.spring.web.view.ThymeleafTilesView.render(ThymeleafTilesView.java:91)
	org.thymeleaf.extras.tiles2.spring.web.view.AjaxThymeleafTilesView.render(AjaxThymeleafTilesView.java:193)
	org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
....
The same strange thing happens for root (/   or /index)
Reply | Threaded
Open this post in threaded view
|

Re: How properly write and use definitions in thymeleaf-extras-tiles2 ?

Eric Francis
In reply to this post by danielfernandez
The github link is giving me a 404 error.
Reply | Threaded
Open this post in threaded view
|

Re: How properly write and use definitions in thymeleaf-extras-tiles2 ?

danielfernandez
Administrator
dadoprso wrote
The github link is giving me a 404 error.
Because the Thymeleaf migration has already been merged into the official SpringSource repository. The new link is https://github.com/SpringSource/spring-webflow-samples/tree/master/booking-mvc

Regards,
Daniel.
Reply | Threaded
Open this post in threaded view
|

Re: How properly write and use definitions in thymeleaf-extras-tiles2 ?

Eric Francis
Ah, got it.

Thank you.