Search code examples
htmlfreemarker

How can I display data of a list entry via a macro in Apache Freemarker?


Im using the templating engine freemarker (v. 2.3.31) with java/spring. Goal: In my <#list></#list> I would like render data for each dog via a macro that is defined in another file (dog-detail.html.ftl).

<#import "../base/templates/dog-detail.html.ftl" as detail>
...

<div class="content">
    <label>${(data.title)!""}</label>

    <#if (data.dogs)?has_content>
        <#list (data.dogs) as dog >

          <label>inside dog detail</label>

            <@detail.detail dog?index+1 />

        </#list>
        <#else>
        <label>no dogs here ...</label>
    </#if>
</div>

dog-detail.html.ftl:

<#macro detail index>

    <label>Hello I am the ${index}. dog. My name is ${(dog.name)!""} i am ${(dog.age)!""} years old</label>

</#macro>

my json:

{
  "title": "hello i am a title",
  "dogs": [
    {
      "name": "Bello",
      "age": 5
    },
    {
      "name": "Bella",
      "age": 4
    },
    {
      "name": "Woof",
      "age": 10
    }
  ]
}

The output:

<div class="content">
  <label>hello i am a title</label>
  <label>inside dog detail</label>
  <label>Hello I am the 1. dog. My name is  i am  years old</label>
  <label>inside dog detail</label>
  <label>Hello I am the 2. dog. My name is  i am  years old</label>
  <label>inside dog detail</label>
  <label>Hello I am the 3. dog. My name is  i am  years old</label>
</div>

I never had trouble accessing data in a macro, yet whenever I try to access an entry in a list within a macro it does not work. What am I doing wrong?

I tried to pass the whole "dog" as a param to the macro, this did not work as freemarker seems not to be able to handle whole json nodes as params.

Current Work Around

When the index is passed to the macro, the data can be accessed like so: ${(data.dogs[index-1].name)!""} .


Solution

  • Generally in my macro my variables work when I call them with their full json path, example: data.title. However, the expression data.dogs[index].name still did not work for some reason. I am guessing it is because the place I am calling it from (inside the dogs list)

    In the meantime, I had a look at the namespace documentation and found a work around:

    .data_model.data.dogs[index].name
    

    This enabled me to access the dog respectively its properties without having to pass the entire dog as json