User-defined directive (<@...>) - Apache FreeMarker Manual

Unsupported web browser - Use a modern browser to view this website!

- Home
- Manual
- Java API

- Contribute
- Report a Bug
- Download

Manual
Previous Next

# User-defined directive (<@...>)

## Synopsis

    <@user_def_dir_exp param1=val1 param2=val2 ... paramN=valN/>
    (Note the XML-style / before the >)
    or if you need loop variables (more details...)
    <@user_def_dir_exp param1=val1 param2=val2 ... paramN=valN ; lv1, lv2, ..., lvN/>

    Or the same as the above two but with end-tag (more details...):

    <@user_def_dir_exp ...>
      ...
    </@user_def_dir_exp>
    or
    <@user_def_dir_exp ...>
      ...
    </@>

    Or all above but with positional parameter passing (more details...):

    <@user val1, val2, ..., valN/>
    ...etc.

Where:

- `user_def_dir_exp`: Expression evaluates to an user-defined directive (for example a macro), that will be called.
- `param1`, `param2`, ...etc.: The name of parameters. They are not expressions.
- `val1`, `val2`, ...etc.: The value of parameters. They are expressions.
- `lv1`, `lv2`, ...etc.: The name of loop variables. They are not expressions.

The number of parameters can be 0 (i.e. no parameters).

The order of parameters is not significant (unless you use positional parameter passing). The name of parameters must be unique. Lower- and uppercase letters are considered as different letters in parameter names (i.e. `Color` and `color` is not the same).

## Description

This will call an user-defined directive, for example a macro. The meaning of parameters, and the set of supported and required parameters depend on the concrete user-defined directive.

You may read the tutorial about user-defined directives.

Example 1: Calls the directive that is stored in the variable `html_escape`:

Template

    <@html_escape>
      a < b
      Romeo & Juliet
    </@html_escape>

Output:

Output

      a &lt; b
      Romeo &amp; Juliet

Example 2: Calls a macro with parameters:

Template

    <@list items=["mouse", "elephant", "python"] title="Animals"/>
    ...
    <#macro list title items>
      <p>${title?cap_first}:
      <ul>
        <#list items as x>
          <li>${x?cap_first}
        </#list>
      </ul>
    </#macro>

Output:

Output

      <p>Animals:
      <ul>
          <li>Mouse
          <li>Elephant
          <li>Python
      </ul>

    ...

### End-tag

You can omit the `user_def_dir_exp` in the end-tag. That is, you can always write `</@>` instead of `</@anything>`. This rule is mostly useful when the `user_def_dir_exp` expression is too complex, because you don't have to repeat the expression in the end-tag. Furthermore, if the expression contains other than simple variable names and dots, you are not allowed to repeat the expression. For example, `<@a_hash[a_method()]>...</@a_hash[a_method()]>` is an error; you must write `<@a_hash[a_method()]>...</@>`. But `<@a_hash.foo>...</@a_hash.foo>` is OK.

There's also a special rule that says that if the `user_def_dir_exp` ends with `?with_args(...)`, then that's ignored when the end-tag is matched, so you can write something like `<@myMacro?with_args(args)>...</@myMacro>`.

### Loop variables

Some user-defined directives create loop variables (similarly to `list` directive). As with the predefined directives (as `list`) the name of loop variables is given when you call the directive (as `foo` in `<#list foos as foo>...</#list>`), while the value of the variable is set by the directive itself. In the case of user-defined directives the syntax is that the name of loop variables is given after a semicolon. For example:

Template

    <@myRepeatMacro count=4 ; x, last>
      ${x}. Something... <#if last> This was the last!</#if>
    </@myRepeatMacro>

Note that the number of loop variable created by the user-defined directive and the number of loop variables specified after the semicolon need not match. Say, if you are not interested if the repetition is the last, you can simply write:

Template

    <@myRepeatMacro count=4 ; x>
      ${x}. Something...
    </@myRepeatMacro>

or you can even:

Template

    <@myRepeatMacro count=4>
      Something...
    </@myRepeatMacro>

Furthermore, it does not cause error if you specify more loop variables after the semicolon than the user-defined directive creates, just the last few loop variables will not be created (i.e. those will be undefined in the nested content). Trying to use the undefined loop variables, however, will cause error (unless you use built-ins like `?default`), since you try to access a non-existing variable.

See the the tutorial about user-defined directives for more explanation.

### Positional parameter passing

Positional parameter passing (as `<@heading "Preface", 1/>`) is a shorthand form of normal named parameter passing (as `<@heading title="Preface" level=1/>`), where you omit the parameter name. This shorthand form should be used if a user-defined directive has only one parameter, or if it is easy to remember the order of parameters for a frequently used user-defined directive. To use this form, you have to know the order in which the named parameters are declared (trivial if the directive has only one parameter). Say, if `heading` was created as `<#macro heading title level>...`, then `<@heading "Preface", 1/>` is equivalent with `<@heading title="Preface" level=1/>` (or `<@heading level=1 title="Preface"/>`; if you use parameter names, the order is not important). Note that positional parameter passing is currently only supported for macros.

Previous Next