Template Inheritance using only Thymeleaf

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

Template Inheritance using only Thymeleaf

Novabyte
Hey,

New Thymeleaf user here, the documentation on the site is really very good. I've been through it all and the relevant posts on the forum.

I've got some idea of how to achieve the basic level of template inheritance I want but I can't make it materialise in code form.

I'd like to have a root template that looks like this (pseudo code):

<html>
<head/>  !-- contains all core css and js --
<body>
<header/> !-- a thymeleaf fragment --
<div id="main"/> !-- a thymeleaf include ? --
<footer/>  !-- a thymeleaf fragment --
<div/>  !-- contains all remaining js resources --
</body>

And a child page:

<thymeleaf include> !-- the <div id="main"> section --
My page
</thymeleaf include>

I have a query about fragments too, the code in the Tutorial Guide shows a full page layout (including doctype... etc) for a fragment:

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-2.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<body>
  <div th:fragment="copy">
© 2011 The Good Thymes Virtual Grocery
  </div>
</body>
</html>

Is the reason it's defined with all the other tags to present a valid XML document to the parser to extract the fragment from?
Reply | Threaded
Open this post in threaded view
|

Re: Template Inheritance using only Thymeleaf

Zemi
Administrator
Hi,

following the "Thymeleaf style", you don't have layout templates like Apache Tiles, but you have full pages where you can include fragments from other pages.

Thus, you have HTML pages viewable with just a browser.

So you have to compose your common HTML in some page, for example, index.html, and declare the fragments in this page. For example:

index.html:
     <html>
           <head>....</head>
           <body>
                  <header th:fragment="myHeader" />
                  ....
           </body>
     </html>

Later, you have to include this header in EVERY page:

search.html:
     <html>
           <head>....</head>
           <body>
                  <header th:include="index.html::myHeader" />
                  ....
           </body>
     </html>

login.html:
     <html>
           <head>....</head>
           <body>
                  <header th:include="index.html::myHeader" />
                  ....
           </body>
     </html>

product.html:
     <html>
           <head>....</head>
           <body>
                  <header th:include="index.html::myHeader" />
                  ....
           </body>
     </html>

You could do it in the Tiles style, but you would loss the benefits of browseable pages.
Reply | Threaded
Open this post in threaded view
|

Re: Template Inheritance using only Thymeleaf

Zemi
Administrator
In reply to this post by Novabyte
> I have a query about fragments too, the code in the Tutorial Guide shows a full page layout (including doctype... etc)
> Is the reason it's defined with all the other tags to present a valid XML document to the parser to extract the fragment from?

Yes, the parser needs a valid XML document unless you have configured Thymeleaf with the template mode "Legacy HTML5".

Anyway, writing valid XML is a good practice.
Reply | Threaded
Open this post in threaded view
|

Re: Template Inheritance using only Thymeleaf

Novabyte
In reply to this post by Zemi
Thank you Zemi for the prompt reply.

A usecase I have for template inheritance is: I have a javascript library that I want to update the version of, instead of cycling through the <head/> for every page I could update the root template with the change and it'll be propagated to every page that inherits from root.

I guess as an alternative I could define the head as a fragment to be included across pages. Normally I like to have a <head/> defined in the root template but have an import that allows an inherited page to add additional information (like stylesheets or Javascript or meta information).

The problem with this approach is the page fragment would contain the core information such as the main stylesheet which makes viewing the page with just the browser quite useless.

How do you normally layout your templates?
Reply | Threaded
Open this post in threaded view
|

Re: Template Inheritance using only Thymeleaf

Zemi
Administrator
For a javascript include you could put it in the index.html:
        <script th:fragment="jquery" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>

And include in your pages like this:
        <script th:substituteby="index.html::jquery"></script>

Unfortunately, you will have to declare a fragment for each javascript file, because you cannot put them into a container element. Maybe you could be interested in JAWR to avoid this problem.
Reply | Threaded
Open this post in threaded view
|

Re: Template Inheritance using only Thymeleaf

Novabyte
With the approach you suggest for javascript, it would mean no direct browser rendering with JS resources?

Thanks for all the suggestions, I really like the XML namespace approach to templating afforded by Thymeleaf as well as the opportunity to use direct browser rendering during development by the web designers. I think I'll just bite the bullet and mirror the code for the <head/> across each page. It will be a pain to update by hand... but the hope is I won't have to do it too often.

Thanks for all the help.