# Template Syntax

The structure and content of quick app components and pages are defined in templates, using an HTML-based markup language with essential components and events that enable user interaction.

This HTML-based template syntax allows you to declaratively bind the rendered DOM to the underlying component data. The system renders the pages using virtual DOM to offer reactivity, applying minimal DOM manipulations when the component states change.

The templating system enables the definition of static content and data interpolation.

A template section is identified by the <template> tag in UX documents.

WARNING

Templates can only contain one root node (e.g., a <div> element). You can use <block> as the root node.

You can include static content directly on the templates:

<template> 
    <text>Sample text</text> 
</template> 

# Decorators

You can customize filters to modify or decorate the content rendered in pages.

A filter is a method defined in the component instance. The method must have an argument (the input) and return a value after processing the data and applying the format.

For instance, a method to capitalize a text:

<script> 
    export default { 
        private: { 
            message: 'hello' 
        }, 
        capitalize(value) { 
            if (!value) return '' 
            value = value.toString() 
            return value.charAt(0).toUpperCase() + value.slice(1) 
        }
    } 
</script>

To use a filter, you can add it to the end of the expression and separate it with a pipe (|).

To apply the formatter of the previous example:

<template> 
    <text>{{ message | capitalize }}</text> 
</template> 

The filter uses the received the expression value as the first parameter.

These filters can be connected in a pipeline as in the following example.

<template> 
    <text>{{ message | filterA | filterB }}</text> 
</template>
<script> 
    export default { 
        private: { 
            message: 'hello' 
        }, 
        filterA(value) { 
            if (!value) return '' 
            return '(A) ' + value  
        },
        filterB(value) { 
            if (!value) return '' 
            return '(B) ' + value  
        }        
    } 
</script>

The result of the previous pipeline produces the text:

(B) (A) hello

# Data Binding

The most basic form of data binding is text interpolation using the syntax (double curly braces):

<template> 
    <text>{{message}}</text> 
</template> 

The mustache tag will be replaced with the value of the message property from the current component instance. It will also be updated once the message property changes.

The following example shows how to bind a data property with the template.

<template>
    <text>{{message}}</text> 
</template> 
<script> 
    module.exports= { 
        data: { 
            message: 'Hello World!' 
        } 
    } 
</script>

Data interpolation can be also used in element's attributes. Also with advanced operations inline:

<template> 
    <text style="{{'background-color:'+color}}">Static content</text> 
</template> 
<script> 
    module.exports= { 
        data: { 
            color: "red" 
        } 
    } 
</script>

# List Rendering

We can use a data array to render a list of elements using the for directive. This directive must be applied on an array in the instance of the component, and it generates two reserved local variables that can be used in the scope of the block where the for directive is applied.

Children of the element that contains the for directive may use the following variables:

  • $idx: index of the array (from 0 to array.length - 1)
  • $item: variable that contains the element in the array at the position $idx.

The following example...

<template> 
  <div> 
    <div for="{{animals}}"> 
        <text>Index: {{$idx}}</text>
        <text>{{$item.identifier}}</text>
        <text>{{$item.name}}</text> 
    </div> 
  </div> 
</template> 
<script> 
  module.exports={ 
    data: { 
      animals: [
        {
          name: "cat",
          identifier: "01"
        }, 
        {
          name: "platypus",
          identifier: "02"
        },
        {
          name: "turtle",
          identifier: "03"
        }
      ]
    } 
  } 
</script>

rendering the following texts on the page:

Index: 0
01
cat

Index: 1
02
platypus

Index:2
03
turtle

The for directive can use the tid attribute to define the attribute of the array elements that must be used as a unique identifier of each array element. If tid is not specified, the system considers the array index ($idx) by default.

Use of tid attribute in the loop directive, indicating that $item.identifier is the unique identifier of the array elements:



 







<template> 
  <div> 
    <div for="{{animals}}" tid="identifier"> 
        <text>Index: {{$idx}}</text>
        <text>{{$item.identifier}}</text>
        <text>{{$item.name}}</text> 
    </div> 
  </div> 
</template> 

We can use other alternative notations to define loops with the for directive:

  • for="element in list", where element is a the name of the variable that contains the array element that can be used in the loop. The default array index is $idx.
  • for="(index,element) in list", where index is the array index, and element is the variable with the array item to be used in the loop.

WARNING

If The data attribute specified by tid must exist and be unique.

# Conditional Rendering

The template could include directives to render blocks conditionally. If the condition defined by the directive is not met, the element is removed from the Virtual DOM.

There are two main types of directives to control the conditional rendering: if/elif/else and show.

# if/elif/else Directives

The directive if is used to conditionally render a block only when the directive's expression returns a truthy value.

  <text if="{{condition1}}">If block</text> 

It is also possible to add a complementary else block:

  <text if="{{condition1}}">If block</text> 
  <text else>Else section</text> 

In case you need to chain "else if" blocks after the if directive, you can use the elif directive.

<template> 
  <div> 
    <text if="{{condition1}}">If block</text> 
    <text elif="{{condition2}}">ElIf part</text> 
    <text else>Else section</text> 
  </div> 
</template> 
<script> 
  module.exports= { 
    data: { 
      condition1: false, 
      condition2: true 
    } 
  } 
</script>

The previous example renders:

ElIf part

WARNING

The if, elif, and else blocks must be sibling nodes. Otherwise, the compilation fails.

# show Directive

The effect of the conditional show directive is equivalent to the display: none CSS statement, so the elements within the block are in the Virtual DOM.

<template> 
  <text show="{{visible}}"> Hello World! </text> 
</template> 
<script> 
  module.exports= { 
    data: { 
      visible: false 
    } 
  } 
</script>

TIP

Currently, the show directive only applies to native components, and it does not cause any effect in custom components. For custom components, you can pass the conditional parameters through props, and using show directly in the inner elements.

TIP

You can use the basic <block> element to control the conditional rendering. This element only supports the for and if/elif/else attributes. If no attribute is specified in a <block> section, the section is treated as a transparent node in a build, and its sub-nodes are added to its parent <block> node in the virtual DOM.

# Event Binding

We can listen to events on elements and run some scripts when they are triggered. We can use the name of the event with the prefix on, or using the @ symbol.

For instance, the follow example binds the method press() with the click event of <div> elements.

<template> 
    <div> 
        <!-- Normal format --> 
        <div onclick="press"></div> 
        <!-- Shortcut --> 
        <div @click="press"></div> 
    </div> 
</template> 
<script> 
    module.exports= { 
        press: function(e) { 
            this.title = 'You clicked!!' 
        } 
    } 
</script>

The event handler includes an argument for the event that is triggered. In the case the method includes other parameters, the event is automatically added to the parameter list.

Read more in the Events section.

# Reusing Custom Components

Custom components can be reused from any component. You only need to import the custom component using the <import> element in the UX file.

For instance:

<import name='cool-button' src='./cool-button'></import> 
<template>
  <div class="container">
    <text class="title">Hi Quick Apps!</text>
    <cool-button></cool-button>
  </div>
</template>

Read more about components.