Built-ins to handle undefined variables

As we explained in the chapter about expressions, an error will occur and abort the template processing if you try to access a non-existent variable. However four special built-ins can suppress this error, and examine if the variable is present or not. The examined variable can be top-level variable, hash subvariable, or sequence subvariable as well. These built-ins can be used with all variable types. (For those who know what's Java null, FreeMarker just treats them as missing variables. See also: question about null in the FAQ)

Note

The frequent usage of these built-ins is usually the sign of bad practice. You may revisit you data model so you don't need to use these built-ins often. You will find the reasons in this FAQ entry.

default

This built-in allows you to specify a default value for an undefined expression.

Example. Assume no variable called mouse is present:

${mouse?default("No mouse.")}
<#assign mouse="Jerry">
${mouse?default("No mouse.")}  

The output will be:

No mouse.
Jerry  

So, you always use this built-in in a syntactic construct expr?default(default-expr). If expr is defined, it evaluates to expr, otherwise it evaluates to default-expr.

You can use this built-in in two ways with non-top-level variables:

product.color?default("red")  

This examines if the product hash contains a subvariable called color or not, and returns "red" if not. The important point is that product hash itself must exist, otherwise the template processing will die with error.

(product.color)?default("red")  

This examines if product.color exists or not. That is, if product does not exist, or product exists but it does not contain color, the result will be "red", and no error will occur. The important difference between this and the previous usage is that when surrounded with parentheses, it is allowed for any component of the expression to be undefined, while without parentheses only the last component of the expression is allowed to be undefined.

Of course, the built-in can be used with sequence subvariables as well:

<#assign seq = ['a', 'b']>
${seq[0]?default('-')}
${seq[1]?default('-')}
${seq[2]?default('-')}
${seq[3]?default('-')}  

the outpur will be:

a
b
-
-  

A negative sequence index (as seq[-1]?default('-')) will cause an error even with default (and similar) built-ins.

exists

It is true if the variable exists, otherwise it is false.

Example. Assume no variable called mouse is present:

<#if mouse?exists>
  Mouse found
<#else>
  No mouse found
</#if>
Creating mouse...
<#assign mouse = "Jerry">
<#if mouse?exists>
  Mouse found
<#else>
  No mouse found
</#if>  

The output will be:

  No mouse found
Creating mouse...
  Mouse found  

With non-top-level variables the rules are the same as with default, that is, you can write product.color?exists and (product.color)?exists

has_content

It is true if the variable exists and is not ``empty'', otherwise it is false. The meaning of ``empty'' depends on the concrete case. This follows intuitive common-sense ideas. The following are empty: a string with 0 length, sequence or hash with no subvariables, a collection which has passed the last element. If the value is not a string or sequence or hash or collection, then it counts as non-empty if it's a number or a date or a boolean (e.g. 0 and false are not empty), otherwise it counts as empty. Note that when your data model implements multiple template model interfaces you may get unexpected results. However, when in doubt you can use always use expr?if_exists?size > 0 or expr?if_exists?length > 0 instead of expr?has_content.

With non-top-level variables the rules are the same as with default built-in, that is, you can write product.color?has_content and (product.color)?has_content

if_exists

It evaluates to the variable itself if the variable is defined. On the other hand, if the variable is undefined, it evaluates to a special model that acts as a zero-length string (""), boolean false, empty sequence and hash, and a method which ignores its parameters and whose return value is undefined.

Example. Assume no variable called mouse is present:

(${mouse?if_exists})
Creating mouse...
<#assign mouse = "Jerry">
(${mouse?if_exists})  

The output will be:

()
Creating mouse...
(Jerry)  

With non-top-level variables the rules are the same as with default built-in, that is, you can write product.color?if_exists and (product.color)?if_exists


Page generated: 2006-03-15 13:49:01 GMT FreeMarker Manual -- For FreeMarker 2.3.6