|
FreeMarker ExpressionsA FreeMarker expression within an output escape sequence refers to a scalar in the root hash of the data model. This is either a string or a numerical value that will be output directly as text: ${foo} Note that FM version 2.0 introduces a new syntax for when the result must absolutely be numerical. #{bar} If the above expression is not a number, an exception is thrown. The purpose of this is to prevent mistakes such as: The price of the product is #{bar} dollars. and having that resolve to: The price of the product is foobar dollars. If, instead, we had written: The price of the product is ${bar} dollars. The above is obvious nonsense unless the value of bar is numerical. However, with the standard dollar-sign syntax, no such sanity check is performed. An additional option that you have when using the #{...} syntax is of adding a specifier for the minimum and maximum number of digits to display after the decimal point. For example, the following says to display the number resulting from
the expression #{foo + bar ; m2M4} (Word to the wise: In later releases, there will be full support for internationalized/localized display of numbers and currencies, so the above is really a stopgap measure in this release.) In either case, this escape sequence means "print the variable's value here". An expression that has no referent, or whose referent is null, produces no output. Expressions inside template tags don't have these delimiters: <if foo> hello </if> This prints "hello" if the boolean value of Hash access operatorsIf two identifiers are separated by a dot, the one on the left is a hash (also called "map" or "dictionary" in other languages) the one on the right is the name of a key in that hash: <p>First Name: ${book.author.firstName}</p> When an identifier followed by an expression in brackets, the expression
is evaluated at run time as the name of a hash key. The following are all
equivalent, if foo.bar foo["bar"] foo[propName] foo["ba" + "r"] foo[propStart + "r"] You can chain together dynamic hash keys. All of the following are equivalent: foo.bar.baz.bing foo["bar"]["baz"]["bing"] foo["bar"].baz["bing"] Sequence access operatorsOn an expression that evaluates to a TemplateSequenceModel, you can use numerical indexes to access the sequence elements, like this: mySequence[1] mySequence[index] Where index is a TemplateModel with a numerical value (eg, 1). Note that in FreeMarker, sequences start at zero. You can also express subsequences using the range expressions in the
form mySequence[2..5] mySequence[ofs..(ofs+len)] The range expressions are also used to express substrings, like in: myString[2..5] If the expression to which the range operator is applied can be interpreted both as a sequence and as a string (that is, it evaluates to what we call a multimodel), the subsequence takes precedence over the substring functionality. To access the substring functionality in this case, use this little workaround that will convert the expression into a simple string first, then apply the range operator: ("" + myStringAndSequenceMultiModel)[2..5] Additional operatorsIn addition to the dot and bracket operators, the following operators are supported in expressions:
Operations on numbersFor numerical values, the basic 4-function calculator arithmetic is supported as well as comparisons.
Note that, for certain comparisons, you have a choice between the "natural" operator and an alternative. You can use either < or \lt. This is because the use of < and > can confuse many HTML-oriented editors and parsers. (Though outputting HTML is not the only use for FreeMarker, in practice, it is probably used mostly for web-based applications.) One detail you might note in the above is an inconsistency between > and >= and the other operators. An expression containing > or >= must be within parentheses, while this is not required for the other operators. Here is the explanation. Consider the following code: <if x>y> FreeMarker will not parse this as you intended, because the > is being used to indicate the end of the directive. In other words, <if x> is a valid "if" directive on its own. That is why, if you use the "natural" greater-than operator in a boolean expression, it must be within parentheses. Thus, the above expression must be written as: <if (x>y)> This is not necessary if you use the "web-safe" alternatives \gt and \gte since then the confusion is not there. Nor are the parentheses necessary if you < or == etcetera. So you can perfectly well write: <if x<y> LiteralsString literals are delimited by double quotes. A backslash in a string
literal can be used to escape a double quote. To include a backslash
character, use Number literals are either positive or negative integers or fractional numbers using the decimal notation. Method callsAn expression followed by a pair of parentheses with an optional comma separated list of arguments is a method call: foo() foo("hello") deal(king, queen, spade) A method, which is a TemplateMethodModel, can return a list, a hash, a scalar, another method, or null. You can chain together method calls if each one returns a hash containing the next method: foo().bar() or even if it returns another TemplateMethodModel: foo()("arg") In the first example, CommentsA comment looks like this: <comment> Comment text... </comment> Any text or markup inside the comment is ignored. Comments cannot be nested inside other comments. Here are some more examples of syntactically valid expressions: !(color == "blue" || color == "violet") "customer" + customer.number foo && (!(bar || baz) || bing) eventManager.getEvent(eventID).importance If you use a boolean expression for its string value (not something
you'll often need to do), its string value is |
|