In the last post we looked at how Thymeleaf handles reusable layouts. A reddit user enlightened me about an open source 'dialect' for Thymeleaf that makes it behave in a similar manner to SiteMesh. It's documented pretty well, but...
Yeah, documentation can be boring sometimes, so I thought I'd put together a quick post on how that would look in the Spark Java application I've been working with. It works well, but it suffers from an inability to pass model variables to the layout template. That's something that SiteMesh can handle (although in a less-than-elegant manner in my opinion) and in my view it is almost deal breaker. Something as simple as a nav menu that is common across all pages will ultimately require some dynamic data, and if we're going to need to th:insert
the fragment on every page, then what are we really gaining by using this style of layout template? I'll add how I'd think this could be handled at the end of this post, but first let's look at how to implement this dialect in the project.
The first step is to include the dialect, so in build.gradle
, under dependencies
, add:
compile group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '2.2.1'
Now modify your Bootstrap.groovy
in the main()
method to add the dialect. The rest of the Bootstrap class looks the same as our last post (with the exception of a new/modified route that I've created for this feature called /thymeleaf-layout
): Now create the layout itself - similar to how you'd do in SiteMesh:
A few items to note in the layout:
layout
namespace. The dialect uses it's own namespace instead of the Thymeleaf th
namespace.<head>
element of the 'child' page, by default the 'layout' page <head>
content will be merged. This is configurable. Any child <title>
elements will replace the layout <title>
element, but you can tweak that behavior too.<div layout:fragment="content"></div>
. This is where what we define in the child layout will end up. Very SiteMesh-like.As mentioned above, the <div layout:fragment="content">
starting on line 10 will be what ends up getting populated in the layout template. But as I mentioned above, there's no easy way to pass menu content from the child to the layout (that I've found). Technically, this works in the layout:
But that depends on the 'menu' variable to be in the model on every single page. I'd normally make sure it was, but something about that approach just feels dirty to me. I'd much rather pass the variable from the child to the layout in some manner (here is how SiteMesh handles it). Even that approach feels a little wonky to me, which is why I think I prefer the approach used in my last post, but perhaps I'm missing a feature of this dialect.
I've written many blog posts about connecting to an Autonomous DB instance in the past. Best practices evolve as tools, services, and frameworks become...
Email delivery is a critical function of most web applications in the world today. I've managed an email server in the past - and trust me - it's not fun...
In my last post, we looked at the technical aspects of my Brain to the Cloud project including much of the code that was used to collect and analyze the...