web-dev-qa-db-fra.com

Utiliser l'opérateur ternaire dans freemarker?

Je veux juste faire quelque chose comme ça:

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

Si vous utilisez freemarker 2.3.23 ou plus récent, vous pouvez utiliser le then intégré:

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

Si vous utilisez une ancienne version de freemarker, vous pouvez utiliser à la place le string intégré:

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

Lorsqu'il est appliqué à un booléen, le string intégré agira comme un opérateur ternaire.


73
obourgain

Cette macro fournit un moyen plus simple d'effectuer des opérations ternaires:

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

Il est facile à utiliser et semble agréable et assez lisible:

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

Notez qu'il s'agit de @if - et pas #if comme dans la directive intégrée. Voici quelques exemples supplémentaires.

<!-- `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> 

Pour une raison quelconque, vous ne pouvez pas ajouter de parenthèses autour des paramètres sans nom, s'il s'agit d'expressions non booléennes. Cela aurait pu augmenter encore la lisibilité.

6
kapex

Depuis FreeMarker 2.3.23, vous pouvez écrire a?then('a.htm', 'b.htm'). L'avantage de condition?then(whenTrue, whenFalse) sur condition?string(whenTrue, whenFalse) est qu'il fonctionne pour les chaînes non whenTrue et whenFalse, et qu'il n'évalue que l'un des whenTrue et whenFalse expressions (quelle que soit la branche choisie).

3
ddekany

Vous pouvez définir une fonction personnalisée if qui est déclarée comme suit:

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

La fonction peut être utilisée dans n'importe quel ${...} expression. Votre code ressemblerait à ceci:

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

Contrairement à @kapep, je pense que vous devriez utiliser une fonction, pas une macro. Les macros produisent une sortie (textuelle), tandis que les fonctions renvoient une valeur qui peut par exemple être affectée à une variable, mais également écrite dans la sortie, donc l'utilisation d'une fonction est plus flexible. De plus, la façon d'appliquer la fonction est beaucoup plus proche de l'utilisation d'un opérateur ternaire, qui serait également utilisé à l'intérieur de ${...} expressions, pas comme une directive.

Par exemple, si vous avez besoin de la cible de lien conditionnel plusieurs fois, il serait logique de l'affecter à une variable locale:

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

En utilisant la fonction au lieu de la macro, les exemples de @ kapep ressembleraient à ceci:

<!-- `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>
2
YetAnotherFrank

Utilisation de la syntaxe d'interpolation:

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

has_content: peut être utilisé pour gérer STRING (retourne FALSE en cas de chaîne vide)

0
desiredeveloper