Synopsis
Recommended form (on-based), but this is
only supported since FreeMarker
2.3.34:
<#switch value>
<#on refValue1>
... (Handles refValue1)
<#on refValue2, refValue3>
... (Handles both refValue2 and refValue3))
...
<#case refValueN>
...
<#break>
<#default>
...
</#switch>
Deprecated legacy form (case-based):
<#switch value>
<#case refValue1>
... (Handles refValue1)
<#break>
<#case refValue2>
<#case refValue3>
... (Handles both refValue2 and refValue3)
<#break>
...
<#case refValueN>
...
<#break>
<#default>
...
</#switch>
Where:
-
value,refValue1, etc.: Expressions evaluates to scalars of the same type.
Additional rules:
-
A
switchblock either haveon-s, orcase-s, but not both. -
default: Optional, can occur at most once. Must be after theon-s. There's no ordering restriction when used withcase-s. -
break:-
If the
switchusescasethenbreakimmediately exits from the closes enclosingswitch. This is used to prevent fall-through into the nextcase, or into the following (adjacent)default. (To be precise,breakbehaves as described if theswitchdoesn't containon, and thus also if all it contains is adefault.) -
If the
switchusesonthenbreakis not supported byswitchdirectly, but naturally can be used when theswitchis inside something else that supportsbreak(like inside a list). -
With
case,continuedoes the same asbreak. This is an old bug that works for backward compatibility, but don't utilize it. Withon, this is fixed.
-
Description
Using this directive with case is not
recommended, as it's error-prone because of the fall-through
behavior. Starting from FreeMarker 2.3.34, use
on instead of case. In
earlier versions use elseif-s
instead.
Switch is used to choose a fragment of template depending on
the value of an expression, and is a shorthand instead using if-elseif-else:
<#switch animal.size>
<#on "small">
Processed if animal.size was "small"
<#on "medium">
Processed if animal.size was "medium"
<#on "large", "extra large">
Processed if animal.size was "large" or "extra large"
<#default>
Processed if animal.size is neither of the above
</#switch> Before FreeMarker 2.3.24, on wasn't
supported, only case (note the usage of
break, and the intentional omission of it after
<#case "large">):
<#switch animal.size>
<#case "small">
Processed if animal.size was "small"
<#break>
<#case "medium">
Processed if animal.size was "medium"
<#break>
<#case "large">
<#case "extra large">
Processed if animal.size was "large" or "extra large"
<#break>
<#default>
Processed if animal.size is neither of the above
</#switch> Above examples are basically equivalent with this:
<#assign value = animal.size> <#if value == "small"> Processed if animal.size was "small" <#elseif value == "medium"> Processed if animal.size was "medium" <#elseif value == "large" || value == "extra large"> Processed if animal.size was "large" or "extra large" <#else> Processed if animal.size is neither of the above </#if>
That is, when the switch directive is
processed, it chooses an on or
case directive where a
refValue equals with
value, and continues
the processing of the template there. If there is no
on or case directive with
appropriate refValue,
then it continues processing at the default
directive, if that exists, otherwise it continues the processing
after the end-tag of switch.
Be careful with case's fall-through
behavior! It means that after processing have jumped on the matching
case, it will not leave the
switch directive when it reaches another
case or default, only when it
reaches a break. Example:
<#switch x>
<#case 1>
1
<#case 2>
2
<#default>
d
</#switch> If x is 1, then it will
print 1 2 d (actually with more white-space
between); if x is 2 then it
will print 2 d; if x is
3 then it will print d. This
is usually unintended, or if it is intended then probably not
obvious for the reader, and that's why on is
recommended over case.
