Defining variables in the template

Most of the variables that a typical template works with comes from the data-model. But templates can also define variables themselves, usually to hold loops variables, temporary results, macros, etc. Such variables are outside the data-model; modifying the data-model from templates is by design unsupported. Note that each template processing job has its own private set of these variables, which will be thrown away when the template processing job is finished.

You access variables defined in the template the same way as you access variables defined in the data-model root. For example, if you create a variable called "foo" in the template, you can print its value with ${foo}. If, coincidently, there's a variable called "foo" in the data-model too, the variable created in the template will hide (not overwrite!) it.

There are these kinds of variables that are defined in a template:

  • "plain" variables: They are accessible from everywhere in the template, or from another templates that was inserted with the include directive. You can create and replace these variables with the assign directive, or, because macros and functions are just variables, with the macro directives and function directives.

  • Local variables: They can only be set inside a macro definition body or function definition body, and are only visible from there, not from other macros or functions called from there. A local variable only exists for the duration of a macro or function call. You can create and replace local variables inside the definition body with the local directive. Macro and function parameters are also local variables.

  • Loop variables: Loop variables are created automatically by directives like list (like x in <#list xs as x>...</#list>), and they only exist between the start-tag and end-tag of the directive. (User defined directives, like macros, can also create loop variables.) They are only visible directly between these tags, not from macros or functions called from there. As such, they are quite similar to local variables, but they can't be assigned to directly.

  • Global variables: These should be seldom used. Global variables are shared by all templates, even if they belong to different name spaces because of import-ing. Thus, their visibility is similar to data-model variables. They are set via the global directive. Global variables hide (but don't overwrite) the data-model variables of the same name.

Example: Create and replace variables with assign:

Template
<#assign x = 1>  <#-- create variable x -->
${x}
<#assign x = 2> <#-- replace variable x -->
${x}
<#assign x++> <#-- replace variable x -->
${x}
Output
1
2
3

In the next example we demonstrate that local variables hide (not overwrite) "plain" variables of the same name, and that loop variables hide (not overwrite) local and "plain" variables of the same name:

Template
<#assign x = "plain">
1. ${x}  <#-- we see the plain var. here -->
<@test/>
6. ${x}  <#-- the value of plain var. was not changed -->
<#list ["loop"] as x>
    7. ${x}  <#-- now the loop var. hides the plain var. -->
    <#assign x = "plain2"> <#-- replaces the plain var, not the loop var. -->
    8. ${x}  <#-- it still hides the plain var. -->
</#list>
9. ${x}  <#-- now the new value of plain var. becomse visible -->

<#macro test>
  2. ${x}  <#-- we still see the plain var. here -->
  <#local x = "local">
  3. ${x}  <#-- now the local var. hides it -->
  <#list ["loop"] as x>
    4. ${x}  <#-- now the loop var. hides the local var. -->
  </#list>
  5. ${x}  <#-- now we see the local var. again -->
</#macro>
Output
1. plain
  2. plain
  3. local
    4. loop
  5. local
6. plain
    7. loop
    8. loop
9. plain2 

In the next example we demonstrate that an inner loop variable can hide (not overwrite) an outer loop variable of the same name:

Template
<#list ["loop 1"] as x>
  ${x}
  <#list ["loop 2"] as x>
    ${x}
    <#list ["loop 3"] as x>
      ${x}
    </#list>
    ${x}
  </#list>
  ${x}
</#list>
Output
  loop 1
    loop 2
      loop 3
    loop 2
  loop 1

When a variable hides the variable from the data-model, you can still read that variable from the data-model using special variable globals. For example, assume we have a variable called user in the data-model with value "Big Joe":

Template
${user}          <#-- prints: Big Joe -->
<#assign user = "Joe Hider">
${user}          <#-- prints: Joe Hider -->
${.globals.user} <#-- prints: Big Joe -->

You could also write .data_model.user instead, and then not even a <#global user = "..."> can hide the value in the data-model. However, global variables are often purposely set to override the value coming from the data-model, so using globals is a better practice usually.

For information about syntax of variables (allowed characters and such) please read: The Template/Expressions