Closure Template Commands

Table of Contents

  1. Overview
  2. delpackage
  3. namespace
  4. alias
  5. template, /template
  6. @param
  7. Special Characters
  8. literal, /literal
  9. print
  10. msg, /msg
  11. fallbackmsg
  12. let, /let
  13. if, elseif, else, /if
  14. switch, case, default, /switch
  15. foreach, ifempty, /foreach
  16. for, /for
  17. call, /call, param, /param
  18. Delegate Templates (with delpackage)
  19. Delegate Templates (with variant)
  20. css


Commands are instructions that you give the template compiler to create templates and add custom logic to templates. Put commands within Closure Template tags, which are delimited by braces ({}). Specify the command name as the first token in the tag (except the print command, which is implied if no command is specified), and add additional tokens to form the command text. For example, to create a template, use the tag {template ...}. Within the template you can enclose other commands to evaluate conditional expressions, iterate over data objects, or print messages.

A few of the tags below belong at the top of a Closure Template file, while most of them belong within a template. Within the body of a template, any text within Closure Template tags is parsed and understood by the compiler, while anything outside of Closure Template tags is raw text that is output as-is. The syntax for command text varies depending on the specific command. This chapter describes all of the template commands that you can use.


{delpackage <delegate_package_name>}

This tag belongs at the start of a template file, before the namespace tag. It must appear at the start of its own line. It is associated with one of the two ways to use delegate templates. For details, please see the section on using delegate templates with delpackage.


Syntax (basic form):
{namespace <namespace>}
With all optional attributes:
{namespace <namespace> autoescape="<contextual/true/false>"}

This tag is required at the start of every template file. It must appear at the start of its own line. It declares the namespace for the file, which serves as the common prefix for the full name of every template in the file. You can optionally declare the default autoescape mode for every template in the file (recommended value is strict). You can override this default in the template tag.

Closure Templates allows multiple files to have the same namespace. However, note that Closure Library and Closure Compiler do not allow it, so if you're using Closure Templates in JavaScript together with other Closure technologies, then it's recommended to avoid having the same namespace in multiple template files.


{alias <namespace>}
{alias <namespace> as <identifier>}

This tag belongs at the start of a Soy file, after the namespace tag. It must appear at the start of its own line. You can include any number of alias declarations. Each declaration will alias the given namespace to an identifier. For the first syntax form above, the alias is the last identifier in the namespace. For the second syntax form above, the alias is the identifier you specify. When you call a template in an aliased namespace, you don't need to type the whole namespace, but only the alias plus the template's partial name.

For example, if you declare
{alias long.namespace.root.projectx.mymodule.myfeature}
{alias long.namespace.root.projectx.foomodule.utils as fooUtils}
then you can replace the calls
{call long.namespace.root.projectx.mymodule.myfeature.myTemplate /}
{call long.namespace.root.projectx.foomodule.utils.someHelper /}
{call myfeature.myTemplate /}
{call fooUtils.someHelper /}

Note that delegate templates have their own full names (not a partial name prefixed by the namespace), so the alias command currently does not affect delegate calls (delcall).

template, /template

Syntax (basic form):
{template <template_name>}
With all optional attributes:
{template <template_name> private="<true/false>" autoescape="<true/false/contextual>"}

These tags must appear at the start of their own lines.

The template name must be a dot followed by an identifier because it is a partial name relative to the file's namespace. For example, if the file's namespace is ui.settings.login and the template's partial name is .newPassword, then the full template name would be ui.settings.login.newPassword.

These are the template tag's attributes:

  • private: Optional. Default false. Set this to true if you want this to be a private template. A private template can be called by other templates, including templates from other .soy files, as long as the callers are all within the bundle of .soy files that is compiled together. When you set private to true, the template compiler can optimize calls to that template in various ways, including inlining all calls of that template and removing that template altogether.

  • autoescape: Optional. Affects the encoding of print commands and is set according to these rules:
    • If there is an autoescape value specified in the template tag, use that value.
    • Else if there is an autoescape value specified in the file's namespace declaration, use that value.
    • Else default to the value true, which means that the outputs from all print commands are HTML-escaped by default as a safeguard against cross-site scripting vulnerabilities.
    HTML-escaping is not always ideal, so templates with autoescape="contextual" (as described in the Security chapter) use an escaping convention that is appropriate to the context in which a print command appears. You have two options for turning off autoescaping for data that is known to be safe:
    • Recommended: Mark the value as sanitized content.
    • Use the |noAutoescape print directive. For example, {$userName} is autoescaped while {$productNameHtml |noAutoescape} is not autoescaped. Note that this example also demonstrates the convention that known-to-be-safe HTML data values should have keys whose names end in Html.
    You can set autoescape to false for a whole template if you know that every template input is safe and you'd rather not add |noAutoescape to every print tag. But this may cause cross-site scripting errors later when unsafe content is added by someone who doesn't notice the autoescape="false" in the template tag. The decision is up to you, and it is a per-template decision.

    Warning: If you use autoescape="false" for a template, you must sanitize all the HTML content in that template, or else risk cross-site scripting vulnerabilities.


Syntax (basic form):
{template <template_name>}
  {@param <param_name>: <param_type>}
  {@param? <optional_param_name>: <param_type>}

The {@param} is used to declare a template parameter. Parameter declarations must come first in the template, preceding all other template content.

In the past, template parameters were declared using @param doctags in template comments. The doctag syntax allowed template authors to specify the type of a parameter, but that information was not used by the template compiler and the parameter types were not enforced.

The {@param} template command replaces the older doctag syntax (although that syntax is still available). Parameters declared with the new syntax will be strongly-typed - that is, the template compiler will perform both compile-time and run-time checks to ensure that the parameter data is consistent with the declated type.

Although a template may have both new-style and old-style parameter declarations, a given parameter may only be declared once. Parameters declared using the old-style syntax will be considered to have "unknown" type, regardless of the type specified in the doc comment. The reason for this is that many pre-existing parameter type declarations are inconsistent and incorrect, since they were never enforced.

Doc comments for params

Doc comments for parameters may appear either before or after the parameter declaration. If before, the comment must be on the preceding line; if after, the comment must start on the same line as the parameter declaration.


{template .example}
  /** A leading doc comment. */
  {@param name: string}
  {@param? height: int} /** A trailing doc comment. */

Parameter type expressions

The following lists the various forms of type expressions which are accepted:

Type Expression Meaning
any The supertype of all types. Any value may be assigned to the "any" type.
null The null type. Often used as a member of a union type to indicate the value might null or optional.
? The "unknown" type.
Primitive types.

number = (int|float).
Sanitized content types (produced by Soy templates using strict autoescaping.)
Object or enumeration of specific named type.
list<ElementType> List containing elements of type ElementType.
map<KeyType, ValueType> A general map with keys of type KeyType. Allows item access, i.e. {$a[b]]}.
[a:int, b:float] A record type. Allows field access, i.e. {$a.b}.
type1|type2 Union type expression. A union of a|b may contain either a value of type a or a value of type b

Notes on the above table

  • Named types: "Named" types represent object or enumeration types. These types are not defined in the template language, but must be defined externally and imported into the compiler's type registry via a Java plugin (not covered in this document.) Using a type name which is not registered will produce an error.
  • Sanitized Content Types: These are types representing pre-escaped strings for various contexts. It is also legal to pass in a regular string or UnsanitizedText object for parameters declared with these types, however it will be contextually-escaped before use.
  • Optional Parameters: A parameter declarations ending with a question mark character (@param?) indicates an optional parameter, which is equivalent to the type expression type|null.
  • Records vs. Maps: Maps only support "item" access syntax (value[key]) whereas records only support field access (value.field).
  • The "Any" Type (any) is the supertype of all other types. The only operations that are allowed on any are printing and (implicit) casting to boolean.
  • The "Unknown" Type (?): This is a special type which disables all type checking - all operations are valid on values of unknown type. Old-style parameter declarations (using doc tags) will be assigned the unknown type.

Special Characters

Use the following special character commands to add raw text characters:

Special Character Equivalent Raw Text
{sp} space
{nil} empty string
{\r} carriage return
{\n} new line (line feed)
{\t} tab
{lb} left brace
{rb} right brace

Follow these heuristics when deciding when use {sp} and {nil}:

  • {sp}: Use {sp} to insert a space character at the beginning or end of a line, in situations where the line-joining algorithm would not normally insert a space (specifically, at line-joining locations bordered by an HTML or template tag on either side).

  • {nil}: If a line joining location normally adds a space, but you want to make the lines join without a space, then add {nil} at the end of the first line (most common) or the beginning of the second line. While the {nil} itself turns into an empty string, it adds a template tag at the line-joining location, which eliminates the default single space.

literal, /literal

{literal} ... {/literal}

This command allows you to include a literal block of raw text, possibly including special characters like braces. The rendered output is exactly what appears in the literal block. Note that this means that absolutely no processing happens within a literal block, e.g. no HTML escaping, no line joining, no removal of indentation, no parsing for template commands, and no parsing for comments.


Syntax (without directives):
{print <expression>}
With directives:
{<expression> |<directive1> |<directive2> |...}
{print <expression> |<directive1> |<directive2> |...}

The print command is the most common command in Closure Templates, so it merits a short syntax in which you can omit the command name print. When Closure Templates encounters a print tag, it simply inserts the result of the expression, coerced to a string if necessary, into the rendered output.

Note: The command name print is optional.

Print directives

Print directives are post-processing on the output of a print command. For a list of print directives, please see the section Print Directives in Functions and Print Directives.

msg, /msg

Syntax (basic form):
{msg desc="<help_text_for_translators>"}
With all optional attributes:
{msg meaning="<differentiator>" desc="<help_text_for_translators>"}

Use the msg tag to mark a section of the template as a message that needs to be translated. You must provide the required desc attribute, which provides explanation text to the (human) translators.

Note: You should never break up a sentence or phrase into multiple messages because translation is most effective with the context of the entire sentence or phrase.

Within a msg block, the template compiler turns HTML tags and template tags into placeholders, with the exception of template tags that generate raw text (e.g. special character commands and literal blocks), which are simply substituted. Messages that contain placeholders might be confusing to translators, so you should consider providing (in the desc attribute) an example of how the message looks to the user.

Here are details on how Closure Templates generate placeholders in messages:

  • The template compiler uses fixed names for common HTML placeholders, e.g. <a ...> becomes {START_LINK} and <br /> becomes {BREAK}.

  • A simple print tag that prints a data reference turns into a placeholder that's named according to the last key name, by default. For example, {$user.emailAddress} turns into the placeholder {EMAIL_ADDRESS}.

  • A complete call block (up to the closing /call) turns into a single placeholder. The placeholder is named {XXX} by default, so if you put a call inside a msg, please be sure to provide a clear example of what the message might look like in the desc attribute.

  • If you find a need to specify a placeholder name for a print or call instead of allowing the compiler generate the default name, you can add the phname attribute. The value can either be camel case or upper underscore. For example, {call .emailAddr phname="emailAddress" /} causes the placeholder name to be EMAIL_ADDRESS instead of XXX. Note that changing a placeholder name changes the message id, causing retranslation.

  • If a message contains multiple placeholders that would result in the same placeholder name, then the template compiler appends number suffixes to distinguish them, e.g. START_LINK_1, START_LINK_2.

  • Template commands for control-flow (if, switch, foreach, for) are not permitted within msg blocks. However, you can put them in a let block and then print the resulting reference from a within a msg block. If you do this, make sure the let block has absolutely no translatable content.

Example message:
{msg desc="Says hello and tells user to click a link."}
  Hello {$userName}! Please click <a href="{$url}">here</a>.
Example of what the translators see:
Hello {USER_NAME}! Please click {START_LINK}here{END_LINK}.
Example translation that one translator might give us:
{START_LINK}Zhere{END_LINK} zclick zplease. {USER_NAME} zhello!
Example output (for userName = 'Jess' and url = 'http://www.google.com/'):
<a href="http://www.google.com/">Zhere</a> zclick zplease. Jess zhello!

Use the meaning attribute when you have two messages that are exactly the same string in English, but might be translated to different strings in other languages. The meaning should then be a short string that distinguishes the two messages, and is used for generating different message ids. Translators do not see the meaning attribute, so you must still communicate all the details in the desc. For example:
{msg meaning="noun" desc="The word 'Archive' used as a noun, i.e. an information store."}
{msg meaning="verb" desc="The word 'Archive' used as a verb, i.e. to store information."}

See more information about translating messages in the Translation chapter.


{msg <new_attributes>}
{fallbackmsg <old_attributes>}

If you want to change a message in-place, without worrying about accidentally displaying the untranslated new source message to foreign-language users while the new message is getting translated, use the fallbackmsg feature. The template compiler automatically chooses the appropriate version of the message to use. If the new message's translation is in the message bundle, then it is used, else the compiler falls back to using the old message's translation. (This decision happens at message insertion time or render time in JavaScript or Java usage, respectively.)

When changing a message, move the old message attributes and content to the fallbackmsg portion. Then, write the new message attributes and content in the msg portion.

For example, to fix a typo in this message:
{msg meaning="verb" desc="button label"}
replace it with the new message:
{msg meaning="verb" desc="button label"}
{fallbackmsg meaning="verb" desc="button label"}

When replacing an existing message, you can change the message structure, meaning, placeholders, etc. There are no technical limitations on the relationship between the old and new messages.

Periodically, you might want to clean up your code by grepping for old fallbackmsgs and removing them. Although, it's not particularly harmful to leave fallbackmsgs in the code longer than necessary.

let, /let

Syntax for arbitrary values:
{let $<identifier>: <expression> /}
Syntax for rendering to string:
{let $<identifier>}...{/let}

Use the let command to define an alias for an intermediate value (not to be confused with the alias command, which declares an alias for a namespace). The local variable defined by let is not modifiable. You might use let because you'll need to reuse the intermediate value multiple times, or you'll need to print a rendered value using a directive, or you feel it improves the readability of your template code.

{let $isEnabled: $isAaa and not $isBbb and $ccc == $ddd + $eee /}
{if $isEnabled and $isXxx}
{elseif not $isEnabled and $isYyy}

The second syntax form listed above renders the contents of the let block to a string, including applying autoescaping. It is sometimes needed, but should be used sparingly.

Note: The alias is only defined within the immediate code block containing the let command. I.e., the alias is not necessarily defined for the rest of the template.

if, elseif, else, /if

{if <expression>}
{elseif <expression>}

Use the if command for conditional output. The section starting from if and ending in /if is called an if statement. The template compiler evaluates the expressions for if and optional elseif clauses in a boolean context. As soon one expression evaluates to true, the compiler processes that sub-block and skips the rest of the if statement is skipped. Any elseif clauses that appear after the one that evaluates to true are never evaluated. The compiler only processes the optional else command when none of the if and elseif conditions are true.

For example:

{if round($pi, 2) == 3.14}
  {$pi} is a good approximation of pi.
{elseif round($pi) == 3}
  {$pi} is a bad approximation of pi.
  {$pi} is nowhere near the value of pi.

Example output (for pi = 2.71828):

2.71828 is a bad approximation of pi.

switch, case, default, /switch

{switch <expression>}
  {case <expression_list>}
  {case <expression_list>}

Use the switch command for conditional output based on the value of an expression. The section starting from switch and ending in /switch is called a switch statement. Each case can have one or more expressions (use a comma-separated list if you have more than one), and the case matches when any one of its expressions matches the value of the switch expression. When a case matches, the template compiler process that sub-block and the skips the remainder of the switch statement. The compiler processes the optional {default} command if none of the expressions from the case statements match the switch expression.

For example:

{switch $numMarbles}
  {case 0}
    You have no marbles.
  {case 1, 2, 3}
    You have a normal number of marbles.
  {default}  // 4 or more
    You have more marbles than you know what to do with.

Example output (for numMarbles = 2):

You have a normal number of marbles.

foreach, ifempty, /foreach

{foreach <local_var> in <data_ref>}

Use the foreach command to iterate over a list. The iterator local_var is a local variable that is defined only in the block. Within the block, you can also use three built-in functions that only take foreach variables as arguments:

  • isFirst($var) returns true only on the first iteration.
  • isLast($var) returns true only on the last iteration.
  • index($var) returns the current index in the list. List indices are 0-based.

The optional ifempty command is for a fallback section that the template compiler processes when the list is empty.

For example:

{foreach $operand in $operands}
  {if not isFirst($operand)} + {/if}

Example output (for operands = ['alpha', 'beta', 'gamma']):

alpha + beta + gamma

for, /for

{for <local_var> in range(<expression1>, <expression2>, <expression3>)}

Use the for command to generate a simple numerical loop. Set the name for a local variable, which is a loop iterator that is defined only in the block. The range() function can take 1, 2, or 3 arguments. With 3 arguments, the 1st is the initial value, the 2nd is the limit (note that the loop only continues if the loop variable's value is strictly less than the limit), and the 3rd is the increment. With 2 arguments, the increment is assumed to be 1. With only 1 argument, the initial value is assumed to be 0. For example:

range(10)        →  0 1 2 3 4 5 6 7 8 9
range(4, 10)     →          4 5 6 7 8 9
range(4, 10, 2)  →          4   6   8

For example:

{for $i in range($numLines)}
  Line {$i + 1} of {$numLines}.<br>

Example output (for numLines = 3):

Line 1 of 3.<br>Line 2 of 3.<br>Line 3 of 3.<br>

call, /call, param, /param

Syntax (basic form):
{call <template_name> data="<data_to_pass>" /}
With enclosed parameters:
{call <template_name> data="<data_to_pass>"}
  {param <key1>: <expression> /}
  {param <key2>}

Use the call command to call another template and insert its output into the current template. To provide the parameters of the callee template, you can pass all or part of the caller template's data, construct values to pass using param commands, or use a combination of the two. The following sections discuss these three options in turn, using this example callee template:

 * @param largerNum An integer larger than 'smallerNum'.
 * @param smallerNum An integer smaller than 'largerNum'.
{template .exampleCallee}
  {$largerNum} is greater than {$smallerNum}.

Pass all or part of the caller's data to the callee

If you want to pass all or part of the caller's data to the callee, you must make sure that the keys are exactly the same names as the callee's parameters. For example, if the caller's data includes a list pairs where each element is a map containing keys largerNum, and smallerNum, then you can use the following:

{foreach $pair in $pairs}
  {call .exampleCallee data="$pair" /}

In addition to any data or variable reference, you can use the special value data="all" to denote that all of the caller's data should be passed. This of course means that the callee's parameters must be a subset of the caller's parameters, and have the same names. In such cases, it's good practice to use data="all" instead of re-listing the parameters. For example, if the caller's data contains two parameters aaa and bbb, and you want to pass both to the callee (with the same parameter names), it would be extra work and unnecessary to re-list each parameter like this:

// Unnecessary.
{call .mySubtemplate}
  {param aaa: $aaa /}
  {param bbb: $bbb /}

Instead, simply set data="all", like this:

// Recommended.
{call .mySubtemplate data="all" /}

Currently, the compiler will actually rewrite instances of the "unnecessary" example above to the "recommended" example. This may occasionally cause surprising behavior, where both the caller and callee also share an optional param ccc that is now passed due to the rewrite. So far, we've decided that the trade-off is worth it for the smaller/faster resulting code.

Finally, you can omit the data attribute (it is optional) if there are no parameters to be passed in this manner.

Construct values to pass

If you need to construct values to pass to the callee, use the param command. There are two forms of this command.

Syntax for arbitrary values:
{param <key>: <expression> /}
Syntax for rendering to string:
{param <key>}...{/param}

The first form is for arbitrary values and should be used in most cases.

The second form renders the contents of the param block to a string, including applying autoescaping. It is needed in some situations, but it's usually an error to use it when the first form would suffice.

In particular, a common heuristic is that if you're using the second form with a param block that contains a single print tag:
{param aaa}{$bbb}{/param}
then it's usually an error, and should be replaced with:
{param aaa: $bbb /}

Back to our example, assume that the caller's data includes a list pairs where each element is a map containing key largerInt (note the name change) and only sometimes contains the key smallerInt (otherwise undefined). Use this to make the call:
{foreach $pair in $pairs}
  {call .exampleCallee}
    {param largerNum: $pair.largerInt /}
    {param smallerNum}
      {if $pair.smallerInt}
        {$pair.smallerInt}  // if defined, pass it
        {$pair.largerInt - 100}

The above example demonstrates the two forms of the param command. The first form evaluates an expression and passes the result as the parameter. The second form renders an arbitrary section of Soy code and passes the result as the parameter.

If you're observant, you've probably noticed two issues. The first issue is the value passed for smallerNum is now a string, not an integer (fortunately in this case the callee only uses the parameter in a string context). If you noticed this issue, then perhaps you also noticed that the computation for smallerNum can be put into an expression so that indeed it can be passed as an integer:
{param smallerNum: $pair.smallerInt ? $pair.smallerInt : $pair.largerInt - 100 /}
The second issue is if $pair.smallerInt == 0, then it would be falsy and so $largerInt - 100 would be passed even though $pair.smallerInt is defined and should be passed. This is why you should generally avoid using sometimes-defined map keys. If you do use them, please consider the possibility of falsy values. In this example, if there's a possibility that $pair.smallerInt == 0, you could correct the bug by rewriting the expression using the function isNonnull:
{param smallerNum: isNonnull($pair.smallerInt) ? $pair.smallerInt : $pair.largerInt - 100 /}
or better yet, use the null-coalescing operator:
{param smallerNum: $pair.smallerInt ?: $pair.largerInt - 100 /}

Use a combination of the two

Finally, you can mix the two options above: you can pass some of the callee's parameters directly from the caller's data, and pass the rest of the parameters using param commands. For example, if the caller's data includes an integer largerNum and a list of integers smallerNums that are all smaller than largerNum, you could use the following template:

{foreach $smallerNum in $smallerNums}
  {call .exampleCallee data="all"}
    {param smallerNum: $smallerNum /}

Here, the data="all" attribute passes in the callee's original template data largerNum and the list smallerNums. However, because data="all" does not pass in the variable smallerNum, you must pass it explicitly using the param command.

Note: The data attribute of a call tag can only be used to pass all or part of the callee's original template data.

Calling a template in a different namespace

All of the above examples demonstrate calling a template in the same namespace, hence the partial template name (beginning with a dot) used in the call command text. To call a template from a different namespace, use the full template name including namespace. For example:
{call myproject.mymodule.myfeature.exampleCallee data="$pair" /}
Or, if you've aliased the namespace of the template you're calling to its last identifier, then
{call myfeature.exampleCallee data="$pair" /}

Delegate Templates (with delpackage)

The delegates feature allows you to write multiple implementations of a subtemplate and choose among them at a later time, such as on a per-user basis. Delegate templates are defined and called using commands deltemplate and delcall, which have syntax similar to template and call. There are two independent ways to use delegates, differing in how you control which delegate implementation is called. This section explains how to use delegates with delegate packages (delpackage), which is appropriate for cases where you don't intend to send code for unused delegate implementations to the client, e.g. an experiment whose code is only sent to a small subset of users. The next section explains how to use delegates with the variant attribute, which is appropriate for finer control of delegate selection at the call site.

{namespace ...}

/** Caller (basic template, not delegate template). */
{template ...}
  {delcall aaa.bbb.myButton allowemptydefault="false" data="..." /}

/** Default implementation. */
{deltemplate aaa.bbb.myButton}
{delpackage MyExperiment}
{namespace ...}

/** My experiment's implementation. */
{deltemplate aaa.bbb.myButton}

The multiple implementations must appear in different template files, and each file other than the default implementation must declare a delegate package name (delpackage). This is the identifier used to select the desired implementation at usage time.

Note that the delegate template names are not within the file's namespace. The file's namespace is only prepended to basic template names (i.e. not delegate). Instead, delegate template names are just strings that are always written in full. They can be any identifier or multiple identifiers connected with dots.

Template files can have an optional delpackage declaration at the top, just above the namespace declaration. Also, multiple template files can have the same delpackage name, putting them all within the same delegate package. If a delegate template is defined in a file without delpackage, then it is considered a default implementation. If a delegate template is defined in a file with delpackage, then it is a non-default implementation. When selecting a delegate implementation to use for handling a delegate call, a non-default implementation has higher priority (priority 1) than a default implementation (priority 0).

At render time (whether in JS or Java), when a delegate call needs to be resolved, we look at all the "active" implementations of that delegate template name and use the implementation with the highest priority. Basically, this means:

  • If there's an active non-default implementation, it is used.
  • Else, if there's an active default implementation, it is used.
  • Else, if allowemptydefault is true, then the delegate call renders to the empty string.
  • Else, a run-time error occurs.

Due to the third case, it is legal to delcall a template that has no default implementation, as long as you specify the allowemptydefault attribute. The current recommendation is to always specify the allowemptydefault attribute, because its default value will change. (The current default is true, but will be changed to false in the future.)

An "active" implementation is one that is available for this particular render call (see below in JS and Java specific notes). Rendering a delcall for which there is more than one active implementation with the same priority is a run-time error.

JS usage

In JS, an "active" implementation is simply an implementation that is defined in the JS files loaded. Ship only the generated JS files corresponding to active delpackages. If there is more than one implementation of a delegate template at the same priority, then a run-time error is generated at JS load time for that user.

Java usage

The Tofu rendering API in class SoyTofu.Renderer now includes a new method for optionally specifying the set of "active" delegate packages for the render:
For example, with our example template code above, you can call

This will result in using the non-default implementation of aaa.bbb.myButton from the MyExperiment delegate package. On the other hand, if you leave out the call to setActiveDelegatePackageNames() or if you pass a set not including "MyExperiment", then you'll be using the default implementation of aaa.bbb.myButton. If there's more than one active implementation of a delegate template at the same priority, then a render-time exception is thrown.

Delegate Templates (with variant)

The delegates feature allows you to write multiple implementations of a subtemplate and choose among them at a later time, such as on a per-user basis. Delegate templates are defined and called using commands deltemplate and delcall, which have syntax similar to template and call. There are two independent ways to use delegates, differing in how you control which delegate implementation is called. The previous section explains how to use delegates with delegate packages (delpackage), which is appropriate for cases where you don't intend to send code for unused delegate implementations to the client, e.g. an experiment whose code is only sent to a small subset of users. This section explains how to use delegates with the variant attribute, which is appropriate for finer control of delegate selection at the call site.

/** Caller (basic template, not delegate template). */
{template ...}
  {delcall aaa.bbb.myButton variant="$variantToUse" /}

/** Implementation 'alpha'. */
{deltemplate aaa.bbb.myButton variant="'alpha'"}

/** Implementation 'beta'. */
{deltemplate aaa.bbb.myButton variant="'beta'"}

Note: The variant feature is relatively new and may be subject to modifications.

Note that the delegate template names are not within the file's namespace. The file's namespace is only prepended to basic template names (i.e. not delegate). Instead, delegate template names are just strings that are always written in full. They can be any identifier or multiple identifiers connected with dots.

The variant is currently always a string. The variant in a deltemplate tag currently must be a string literal containing a valid identifier. If no variant is specified, then it defaults to the empty string. The variant in a delcall tag can be an arbitrary expression, as long as it evaluates to a string at render time.

At render time, when a delegate call needs to be resolved,

  • If there's a delegate implementation with matching variant, it is used.
  • Else, if there's a delegate implementation with no variant, it is used.
  • Else, a run-time error occurs.



{css <command_text>}

The css command is useful if you're not sure how your mapping from CSS variable names to actual CSS class names will be provided. This command allows the decision to be changed on a per-compile basis. The SoyFileSet.Builder.setCssHandlingScheme() option (or --cssHandlingScheme for SoyToJsSrcCompiler) indicates how to interpret css commands. The options are:

  • LITERAL: Insert command text as literal text.
  • REFERENCE: Evaluate command text as a data or global reference.
  • BACKEND_SPECIFIC (or GOOG for SoyToJsSrcCompiler): For the JavaScript Source backend, generates a call to the Closure Library function goog.getCssName. You can use this option with the Tofu backend if you implement SoyCssRenamingMap and pass the instance to Renderer.setCssRenamingMap().