Thursday, 14 May 2009

FreeMarker an iterating a map

We use FreeMarker to render our views in our web tier. It is a really powerful, fairly extensible (would love to easily add/override builtins!!!), but there are a couple of pain points.

The first is iterating maps. Without going into too much detail, you may expect to be able to do the following:
<#list map as entry>
  Hi there ${entry.key}, this is your value ${entry.value}
</#list>
but you can't.

Neither can you do:
<#list map.entrySet() as entry>
  ...
</#list>


Neither can you do:
<#list map.keySet() as key>
  ${map[key]} or ${map.key} or ${map.(key)} or ${map.[key]}
</#list>

Instead, you need to do the following:

Neither can you do:
<#list map?keys as key>
  ${map.values[key_index]}
</#list>
Nice.

Yeah.

6 comments:

  1. Thanks a lot . It helps me and solved my problem.... :)

    ReplyDelete
  2. Thank you, safes me some time to figure this out myself.
    One simple note, the "Neither can you do:" title on the last code section seems to be a copy&paste error :-)

    ReplyDelete
  3. Actually, in Java the performance is better if you iterate over the entry set instead of the key set. For example, the following will work in Freemarker:

    <#list map.entrySet() as entry>
       <input type="hidden" name="${entry.key}" value="${entry.value}" />
    </#list>

    ReplyDelete
    Replies
    1. I didn't get working the entrySet() version with Java.

      Delete
  4. If 'map.values' doesn't work try 'map?values', like:
    <#list map?keys as key>
    ${map?values[key_index]}

    ReplyDelete
  5. Freemarker: 2.3.20
    Java: 1.7 or higher
    Data model: TreeMap()
    Right solution: see "Anonymous 17 January 2013 at 05:41" comment
    Thank you!

    ReplyDelete