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
switch
block 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
switch
usescase
thenbreak
immediately exits from the closes enclosingswitch
. This is used to prevent fall-through into the nextcase
, or into the following (adjacent)default
. (To be precise,break
behaves as described if theswitch
doesn't containon
, and thus also if all it contains is adefault
.) -
If the
switch
useson
thenbreak
is not supported byswitch
directly, but naturally can be used when theswitch
is inside something else that supportsbreak
(like inside a list). -
With
case
,continue
does 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
.