Thursday, 7 May 2009

Convenient directive for iterating lists in freemarker

We are seeing the same pattern of iterating lists within freemarker appearing:
<#list items as item>
  <#if item_has_next>,</#if>
<#list>

this is quite verbose, and error prone so I have added a new directive called 'iterate', which automatically appends a separator (default is comma) if required.
<@iterate items ; item>
  whatever I want to do with the ${item}.
<@iterate>

The directive:
<#macro iterate items separator=','>
<#list items as item>
  <#nested item/>
  <#if item_has_next>${separator}<!--#if-->
<#list>
<#macro>

To use, this you need to put it into a file (i.e. mystuff.ftl) and then include it within all the templates from which you want to use the new directive (i.e. all of them ;)).
My freemarker fu sucks a bit at this point. We have a web app so I included it in /WEB-INF/views/includes/mystuff.ftl (of course I didn't call it that!). Unfortunately I needed to specify the relative path as I couldn't figure out the fully qualified one - /WEB-INF/views/includes/mystuff.ftl and /views/includes/mystuff.ftl don't work.
So, if my template is /WEB-INF/views/people/list.ftl then I need to do the following:
<#include ../includes/mystuff.ftl>

<@iterate people ; person> Person ${person_index}: ${person.name} <@iterate>

We are using Spring to configure Freemarker, which means using FreeMarkerConfigurer. Unfortunately, I don't think this supports the ability to specify automatic includes (similar to JSP preludes and codas), so I might need to write my own. No biggies.

No comments:

Post a Comment