8

I want to create a master template that every other view page will inherit.

So the master template will have:

HEADER
--CONTENT--
FOOTER
  1. the header will optionally show (if the user is logged in), the username and other user object properties.

  2. the --CONTENT-- is a placeholder that other 'inheriting' view pages will inject their content into.

So my questions are, is this possible with freemarker? If so, any guidance?

How would I pass the user object to the header from my controller actions? ideally the object would be passed in somewhere OTHER than each and every view page (to avoid having to maintain this code on each and every view page).

Blankman
  • 259,732
  • 324
  • 769
  • 1,199

4 Answers4

3

Yes, it's possible. In our applications things like the user object exist in session scope, but this could be any scope freemarker has access to:

<#if Session.the_user?? && Session.the_user.loggedIn>
    <#-- header code -->
</#if> 

You can omit the Session. and Freemarker will search the various scopes for the given variable name.

To inject the content, include this at the point in the master template where you'd like the view page to put its content:

<#nested>

The view pages then declare their use of the master template as follows:

<#import "/WEB-INF/ftl/path/to/template/master.ftl" as com>
<@com.template>
    View page content
</@com.template>
Pat
  • 25,237
  • 6
  • 71
  • 68
  • I'm using spring MVC, and I will load the User object if the user is logged in during the event that fires before ALL action methods. Where should I store the user object then? – Blankman Jul 20 '10 at 02:33
  • If it fires before every action then it sounds like the request scope is a good candidate for holding the user object. – Pat Jul 20 '10 at 10:11
  • For **double inheritence**, see [this question](https://stackoverflow.com/questions/67598981/freemarker-templates-double-inheritence-child-extends-parent-extends-grandparen). – Geoffrey De Smet May 19 '21 at 08:04
2

I made Freemarker template inheritance - https://github.com/kwon37xi/freemarker-template-inheritance I think it's what you want. It is tested on freemarker 2.3.19.

KwonNam
  • 686
  • 1
  • 8
  • 19
1

I implemented something like this:

base.ftl

<#macro page_head>
  <title>Page title!</title>
</#macro>

<#macro page_body></#macro>

<#macro display_page>
  <!DOCTYPE html>
  <html lang="en">
  <head>
    <@page_head/>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  </head>
  <body>
    <@page_body/>
  </body>
  </html>
</#macro>

then index.ftl will inherit the boilerplate templates as:

<#include "base.ftl">
<#macro page_head>
  <title>Welcome studs!</title>
</#macro>

<#macro page_body>
    <h1> Welcome user</h1>
</#macro>
<@display_page/>

this site was helpful for the above code reference https://nickfun.github.io/posts/2014/freemarker-template-inheritance.html

Ujjwal Jung Thapa
  • 604
  • 2
  • 8
  • 31
1

In newer Freemarker versions, the <#nested> element is extremely useful:

base.ftl:

<#macro layout>
    <html>
    <body>
    <p>OptaPlanner AI</p>
    <#nested>
    </body>
    </html>
</#macro>

baseWithDownloadButton.ftl:

<#import "base.ftl" as base>

<@base.layout>
    ${content.body}<#-- Only applicable for jbake -->
    <p>Download button</p>
</@base.layout>
Geoffrey De Smet
  • 26,223
  • 11
  • 73
  • 120