Accessing a dynamic Freemarker variable

Background

This article shows how to use a Freemarker variable that has a dynamic name.

Creating a variable that has a dynamic name in Freemarker in a bit unintuitive and involves a number of steps.

The eval built-in function can be used to access the value of a dynamic variable.

Process

Step 1. Construct a variable containing the dynamic name

Construct a variable within the template containing the dynamic variable name.

e.g.

Freemarker template e.g. simple.ftl
<#-- use this inside a macro -->
<#local numCategories>question.currentProfileConfig.get("faceted_navigation.${facet.name}.numCategories")</#local>
<#-- use this elsewhere -->
<#assign numCategories>question.currentProfileConfig.get("faceted_navigation.${facet.name}.numCategories")</#assign>

Step 2. Construct a variable containing the dynamic value

Construct a variable within the template containing the dynamic variable value.

Ensure that the variable assignment handles a null case and sets a default value.

The following sets the maxCategories variable to hold the value of the configuration key faceted_navigation.${facet.name}.numCategories.

e.g.

Freemarker template e.g. simple.ftl
<#-- use this inside a macro -->
<#local maxCategories=numCategories?eval!""/>
<#-- use this elsewhere -->
<#assign maxCategories=numCategories?eval!""/>

Step 3. Comparison against the dynamic varible

To perform comparisons against the dynamic variable test maxCategories

e.g.

Freemarker template e.g. simple.ftl
<#if maxCategories=="">

Example: read a context-specific configuration value

The example below reads a custom configuration value that sets the maximum number of categories to display for a facet. It then passes this value to another Freemarker macro.

Freemarker template e.g. simple.ftl
<#-- Read the max number of categories for each facet from config -->
<#-- Set maxCategories to the facet specific config value if it exists, otherwise set it to "".-->
<#local numCategories>question.currentProfileConfig.get("faceted_navigation.${facet.name}.numCategories")</#local>
<#local maxCategories=numCategories?eval!""/>
<#-- Check if maxCategories = "" and if so set it to either the collection level default from profile.cfg, collection.cfg, or a hardcoded system default (20)

     Note: I the above line isn't included in the if statement because there isn't a way to check for the existence of the variable configuration param
-->
<#if maxCategories=="">
  <#if question.currentProfileConfig.get("faceted_navigation.numCategories")??>

    <#local maxCategories>${question.currentProfileConfig.get("faceted_navigation.numCategories")}</#local>
  <#else>
    <#local maxCategories="20"/>
  </#if>
</#if>

<@FacetCategory tag="" max=maxCategories?number>
...