在Freemarker中使用三目运算符?

54

我只想做类似于这样的事情:

<a href="${ a? 'a.htm' : 'b.htm'}">

尝试使用变量url=(a? a.htm:b.htm).............. <a href="${url}"> - Shailesh Saxena
4
如下所述,您可以使用?string,但是a的值确切是什么?您是想测试它是否存在,还是布尔值为true - ddekany
5个回答

104

如果你正在使用 freemarker 2.3.23 或更新版本,你可以使用内置的 then 命令:

<a href="${a?then('a.htm','b.html')}" target="${openTarget}">
如果你正在使用旧版本的freemarker,则可以使用内置的string代替:
<a href="${a?string('a.htm','b.html')}" target="${openTarget}">
当应用于布尔值时,内置的 string 函数会起到三元运算符的作用。

4
乍一看这是在做什么并不是很明显。我已经点赞了这个答案,但更易读的方式可能是使用<#if><#else> - Jake Toronto
3
这句话并不容易阅读,因为这不是其预期的用法。它用于格式化布尔值,例如 Registered: ${registered?string('yes', 'no')}。从2.3.23开始有了condition?then(whenTrue, whenFalse)来实现这一功能。 - ddekany
@ddekany 谢谢你的信息,我已更新答案并添加了新方案。 - obourgain

8
如果您使用的是2.3.23之前的旧版本Freemarker,则可以使用此宏来提供一种简单的方法来执行三元操作:
<#macro if if then else=""><#if if>${then}<#else>${else}</#if></#macro>

它易于使用,外观漂亮且易读:

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

请注意,这里使用的是@if而不是内置指令中的#if。以下是更多示例。
<!-- `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> 

由于某种原因,如果它们是非布尔表达式,则无法在无名称参数周围添加括号。这可能会进一步提高可读性。


4
您可以定义一个名为if的自定义函数,声明方式如下:
<#function if cond then else="">
  <#if cond>
    <#return then>
  <#else>
    <#return else>
  </#if>
</#function>

该函数可以在任何${...}表达式中使用。你的代码应该像这样:
<a href="${if(a, 'a.htm', 'b.htm')}">

与@kapep相比,我认为您应该使用函数而不是宏。宏生成(文本)输出,而函数返回一个值,该值可以被分配给变量,也可以写入输出,因此使用函数更加灵活。此外,应用函数的方式更接近于使用三元运算符,该运算符也将在${...}表达式中使用,而不是作为指令。
例如,如果您需要多次使用条件链接目标,则将其分配给局部变量是有意义的。
<#assign targetUrl=if(a, 'a.htm', 'b.htm')/>
<a href="${targetUrl}">link 1</a>
...
<a href="${targetUrl}">link 2</a>

使用函数而不是宏,@kapep的示例将如下所示:
<!-- `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>

4
从FreeMarker 2.3.23开始,你可以写成a?then('a.htm', 'b.htm')。使用condition?then(whenTrue, whenFalse)相比于condition?string(whenTrue, whenFalse)的优点是它适用于非字符串类型的whenTruewhenFalse,而且它只计算whenTruewhenFalse表达式中的一个(选择的分支)。

2
使用插值语法:

使用插值语法:

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

has_content: 可用于处理字符串(如果为空字符串,则返回FALSE)

。最初的回答。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接