Use ternary operator in freemarker?

瘦欲@ 提交于 2019-12-02 20:03:41

If you're using freemarker 2.3.23 or newer, you can use the then built-in:

<a href="${a?then('a.htm','b.html')}" target="${openTarget}">

If you're using an older version of freemarker, you can use instead the string built-in:

<a href="${a?string('a.htm','b.html')}" target="${openTarget}">

When applied to a boolean, the string built-in will act as a ternary operator.


This macro provides a more straightforward way to do ternary operations:

<#macro if if then else=""><#if if>${then}<#else>${else}</#if></#macro>

It's easy to use and looks nice and quite readable:

<@if someBoolean "yes" "no"/>

Note that it is @if - and not #if as in the built-in directive. Here are some more examples.

<!-- `else` is optional -->
<@if someBoolean "someBoolean is true"/>  

<!-- expressions -->
<@if (someBoolean||otherBoolean)  "hello,"+user.name  1+2+3 />  

<!-- with parameter names -->
<@if someBoolean then="yes" else="no" />  

<!-- first in list? -->
<#list seq as x>
    <@if (x_index==0)  "first"  "not first"/> 
<#list> 

For some reason you can't add parenthesis around nameless parameters, if they are non-boolean expressions. That could have increased readability even more.

As of FreeMarker 2.3.23 you can write a?then('a.htm', 'b.htm'). The advantage of condition?then(whenTrue, whenFalse) over condition?string(whenTrue, whenFalse) is that it works for non-string whenTrue and whenFalse, and that it only evaluates one of whenTrue and whenFalse expressions (whichever branch is chosen).

You can define a custom function if that is declared like so:

<#function if cond then else="">
  <#if cond>
    <#return then>
  <#else>
    <#return else>
  </#if>
</#function>

The function can be used in any ${...} expression. Your code would look like so:

<a href="${if(a, 'a.htm', 'b.htm')}">

In contrast to @kapep, I think you should use a function, not a macro. Macros produce (textual) output, while functions return a value that can for example be assigned to a variable, but also written to the output, so using a function is more flexible. Furthermore, the way to apply the function is much closer to using a ternary operator, which would also be used inside ${...} expressions, not as a directive.

For example, if you need the conditional link target multiple times, it would make sense to assign it to a local variable:

<#assign targetUrl=if(a, 'a.htm', 'b.htm')/>
<a href="${targetUrl}">link 1</a>
...
<a href="${targetUrl}">link 2</a>

Using the function instead of the macro, @kapep's examples would look like this:

<!-- `else` is optional -->
${if(someBoolean, "someBoolean is true")}  

<!-- expressions -->
${if(someBoolean||otherBoolean, "hello,"+user.name, 1+2+3)} 

<!-- with parameter names: not possible with functions,
     but also not really helpful -->

<!-- first in list? -->
<#list seq as x>
    ${if(x_index==0, "first", "not first")}
<#list>

Using Interpolation syntax:

"${(a?has_content)?string('a.htm','b.htm')}"

has_content : can be used to handle STRING (returns FALSE in case of empty string)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!