FreeMarker layouts to reduce template redundancy?
Asked Answered
C

1

10

According to the FreeMarker include statement docs, you can make header- and footer- aware templates like so:

<#include "/header.ftl">
<!-- Content of my this page -->
<#include "/footer.ftl">

But if my web app has hundreds of pages/views, this is a lot of redundant copy pasta. It would be great if there was like a "layout" concept in FreeMarker, where I could say "Hey, here is a layout:"

<#include "/header.ftl">
<@import_FTL_Somehow>
<#include "/footer.ftl">

And then create separate templates for each view/page (index.ftl, contactUs.ftl, etc.) and then tell FreeMarkers which FTL files "use" the layout. That way I wouldn't have to keep specifying header/footer includes in each and every template file.

Does FreeMarker support this kind of concept?

Crusade answered 20/11, 2015 at 17:15 Comment(0)
G
9

It doesn't, though if you only need a footer or header it can be solved with some TemplateLoader hack (where the TemplateLoader inserts the header and footer snippets, as if was there in the template file). But the usual solution in FreeMarker is calling the layout code explicitly from each templates, but not with two #include-s directly, but like:

<@my.page>
  <!-- Content of my this page -->
</@my.page>

where my is an auto-import (see Configuration.addAutoImport).

Update: Another approach is that you have a layout.ftl like:

Heading stuff here...
<#include bodyTemplate>
Footer stuff here...

And then from Java you always call layout.ftl, but also pass in the body template name using the bodyTemplate variable:

dataModel.put("bodyTemplate", "/foo.ftl");
cfg.getTemplate("layout.ftl").process(dataModel, out);
Gaylene answered 21/11, 2015 at 8:15 Comment(4)
Thanks @Gaylene (+1) - from their Javadocs, this addAutoImport method: "Adds an invisible #import templateName as namespaceVarName at the beginning of all templates. The order of the imports will be the same as the order in which they were added with this method." However, I'm still not understanding its exact usage:it sounds like this will only import one template (either the header or the footer, but not both).Crusade
Any chance you'd be willing to update your answer with a quick code example showing 2 different pages using this solution? Ideally, I could see the Java code where addAutoImport is called, as well as what the 2 FTL files look like (so I can see how addAutoImport prevents them from - redundantly - requiring the header/footer #include statements). Thanks again!Crusade
Auto-import is only used to define my, not for actually inserting anything. It's to spare an <#import '/lib/myutils.ftl' as my> at the beginning of each file, since you wanted to avoid boilerplate code as much as possible.Gaylene
I have also updated my answer with another approach (the one with layout.ftl).Gaylene

© 2022 - 2024 — McMap. All rights reserved.