Language Guide ============== # Template Directives Overview Almost all of the Marko templating directives can be used as either an attribute or as an element. For example: _Applying directives using attributes:_ ```xml
No colors!
``` _Applying directives using elements:_ ```xml
No colors!
``` The disadvantage of using elements to control structural logic is that they change the nesting of the elements which can impact readability. For this reason it is often more suitable to apply directives as attributes. # Text Replacement Dynamic text is supported using either `$` or `${}`. Examples: ```xml Hello $data.name! Hello ${data.name}! Hello ${data.name.toUpperCase()}! ``` By default, all special HTML characters will be escaped in dynamic text to prevent Cross-site Scripting (XSS) Attacks. To disable HTML escaping, you can use `$!` as shown in the following sample code: ```xml Hello $!{data.name}! ``` If necessary, you can escape `$` using a forward slash to have it be treated as text instead of a placeholder token: ```xml Test: \${hello} ``` # Expressions Wherever expressions are allowed, they are treated as JavaScript expressions and copied out to the compiled template verbatim. However, you can choose to use alternate versions of the following JavaScript operators: JavaScript Operator | Marko Equivalent ------------------- | ----------------- `&&` | `and` || | `or` `===` | `eq` `!==` | `ne` `<` | `lt` `>` | `gt` `<=` | `le` `>=` | `ge` For example, both of the following are valid and equivalent: ```xml
Show More
``` ```xml
Show More
``` # Includes Marko supports includes/partials. Other Marko files can be included using the `` tag and a relative path. For example: ```xml ``` Alternatively, you can pass the template data using the `template-data` attribute whose value should be a JavaScript expression that resolves to the template data as shown below: ```xml ``` The value of the `template` attribute can also be a dynamic JavaScript expression that resolves to a loaded template as shown below: In your JavaScript controller: ```javascript var myIncludeTarget = require('./my-include-target.marko'); var anotherIncludeTarget = require('./another-include-target.marko'); template.render({ myIncludeTarget: myIncludeTarget, anotherIncludeTarget: anotherIncludeTarget }, ...); ``` And then in your template: ```xml ``` You can also choose to load the include target within the calling template as shown below: ```xml ... ``` # Variables Input data passed to a template is made available using a special `data` variable. It's possible to declare your own variables as shown in the following sample code: ```xml ``` To assign a new value to an existing variable the `` tag can be used as shown in the following sample code: ```xml ``` The `` directive can be used to create scoped variables as shown in the following sample code: ```xml Hello $nameUpper! Hello $nameLower! ``` # Conditionals ## if...else-if...else Any element or fragment of HTML can be made conditional using the following directives: - `if` - `else-if` - `else` *Applied as attributes:* ```xml
Hello World
Hello World
A
B
C
Something else
A
B
Something else
``` *Applied as elements:* ```xml
Hello World
A
B
C
Something else
``` ## unless...else-if...else The `unless` directive is also supported as an alternative to `if` in cases where the condition should be negated. ```xml
Hello World
A
B
Something else
``` *Applied as elements:* ```xml
Hello World
A
B
C
Something else
``` ## Shorthand Conditionals Shorthand conditionals allow for conditional values inside attributes or wherever expressions are allowed. Shorthand conditionals are of the following form: `{?;[;]}` For example: ```xml
Hello
``` With a value of `true` for `active`, the output would be the following: ```xml
Hello
``` With a value of `false` for `active`, the output would be the following: ```xml
Hello
``` _NOTE: If the expression inside an attribute evaluates to `null` or an empty string then the attribute is not included in the output._ As shown in the previous example, the "else" block for shorthand conditionals is optional. The usage of an else block is shown below: ```xml
Hello
``` With a value of `false` for `active`, the output would be the following: ```xml
Hello
``` ## Conditional Attributes Marko supports conditional attributes when the value of an attribute is an expression. Marko also supports [HTML `boolean` attributes](https://html.spec.whatwg.org/#boolean-attributes) (e.g., ``) If an attribute value resolves to `null`, `undefined`, `false` or an empty string then the attribute will not be rendered. If an attribute value resolves to `true` then only the attribute name will rendered. For example, given the following data: ```javascript { title: '', active: true, checked: false, disabled: true } ``` And the following template: ```xml ${data.title}
``` The output HTML will be the following: ```xml
``` # Looping ## for Any element can be repeated for every item in an array using the `for` directive. The directive can be applied as an element or as an attribute. _Applied as an attribute:_ ```xml
  • ${item}
``` _Applied as an element:_ ```xml
  • ${item}
``` Given the following value for items: ```javascript ["red", "green", "blue"] ``` The output would be the following: ```xml
  • red
  • green
  • blue
``` ### Loop Status Variable The `for` directive also supports a loop status variable in case you need to know the current loop index. For example: ```xml
  • $color ${loop.getIndex()+1}) of ${loop.getLength()} - FIRST - LAST
``` ### Loop Separator ```xml $color
$color
``` ### Range Looping A range can be provided in the following format; ` from to [ step ]`. The `from`, `to` and `step` values must be numerical expressions. If not specified, step defaults to 1. ```xml
  • $i
``` ```xml
  • $i
``` ```xml
  • ${myArray[i]}
``` ### Property Looping ```xml
  • $name: $value
``` ### Custom Iterator A custom iterator function can be passed as part of the view model to the template to control looping over data. A sample custom iterator function that loops over an array in reverse is shown below: ```javascript { reverseIterator: function(arrayList, callback) { for(var i=arrayList.length-1; i>=0; i--){ callback(arrayList[i]); } } } ``` The custom iterator can then be used in a template as shown below: _Applied as part of a `for` attribute:_ ```xml
$item
``` _Applied as part of a `` element:_ ```xml $item ``` Custom iterators also support providing a custom status object for each loop iteration: ```javascript { reverseIterator: function(arrayList, callback){ var statusVar = {first: 0, last: arrayList.length-1}; for(var i=arrayList.length-1; i>=0; i--){ statusVar.index = i; callback(arrayList[i], statusVar); } } } ``` _Applied as part of a `for` attribute:_ ```xml
${status.index}$item
``` _Applied as part of a `` element:_ ```xml ${status.index}$item ``` # Macros Parameterized macros allow for reusable fragments within an HTML template. A macro can be defined using the `` directive. ## def The `` directive can be used to define a reusable function within a template. ```xml Hello $name! You have $count new messages. ``` The above macro can then be invoked as part of any expression. Alternatively, the [``](#invoke) directive can be used invoke a macro function using named attributes. The following sample template shows how to use macro functions inside expressions: ```xml Hello $name! You have $count new messages.

${greeting("John", 10)}

${greeting("Frank", 20)}

``` ## invoke The `` directive can be used to invoke a function defined using the `` directive or a function that is part of the input data to a template. The `` directive allows arguments to be passed using element attributes, but that format is only supported for functions that were previously defined using the `` directive. ```xml Hello ${name}! You have ${count} new messages. ``` The output for the above template would be the following: ```xml

Hello John! You have 10 new messages.

Hello Frank! You have 20 new messages.

``` _NOTE:_ By default, the arguments will be of type "string" when using `.` However, argument attributes support JavaScript expressions which allow for other types of arguments. Example: ```xml count="10" count="${10}" ``` # Structure Manipulation ## attrs The `attrs` attribute allows attributes to be dynamically added to an element at runtime. The value of the attrs attribute should be an expression that resolves to an object with properties that correspond to the dynamic attributes. For example: ```xml
Hello World!
``` Given the following value for the `myAttrs` variable: ```javascript {style: "background-color: #FF0000;", "class": "my-div"} ``` The output would then be the following: ```xml
Hello World!
``` ## body-only-if If you find that you have a wrapper element that is conditional, but whose body should always be rendered then you can use the `body-only-if` attribute to handle this use case. For example, to only render a wrapping `` tag if there is a valid URL then you could do the following: ```xml Some body content ``` Given a value of `"http://localhost/"` for the `data.linkUrl` variable: , the output would be the following: ```xml Some body content ``` Given a value of `undefined` for the `data.linkUrl` variable: , the output would be the following: ```xml Some body content ``` # Comments Standard HTML comments can be used to add comments to your template. The HTML comments will not show up in the rendered HTML. Example comments: ```xml

Hello

``` If you would like for your HTML comment to show up in the final output then you can use the custom `html-comment` tag: ```xml This is a comment that *will* be rendered

Hello

``` Output: ```xml

Hello

``` # Whitespace The Marko compiler will remove unnecessary whitespace based on some builtin rules, by default. These rules are partially based on the rules that browser's use to normalize whitespace and partially based on the goal of allowing nicely indented markup with minified output. These rules are as follows: - For text before the first child element: `text.replace(/^\n\s*/g, '')` - For text after the last child element: `text.replace(/\n\s*$/g, '')` - For text between child elements: `text.replace(/^\n\s*$/g, '')` - Any contiguous sequence of whitespace characters is collapsed into a single space character In addition, whitespace within the following tags is preserved by default: - `
`
- `
```

Example output:

```xml
HomeMy Profile