Skip to content

Template Text

Build text using a text template - for generating text in formats other than HTML, where you don’t need automatic escaping and you have full control over the format of the output.

Basic Example

A sample template that outputs a greeting:

<p>Hello, {{ .name }}!</p>
<p>You are {{ .age }} years old.</p>

Matching Data:

{
"name": "John",
"age": 30
}

This will output:

<p>Hello, John!</p>
<p>You are 30 years old.</p>

Note: numbers in templating are always treated as decimals. ao if you want to compare numbers use decimals like 1.0 instead of 1.
Field names in templates can’t have spaces or special characters.

Accessing Nested Data

For nested data, dot notation is used to access fields in objects and to access items in arrays you need to use the index function.
Example:

{
"user": {
"details": {
"name": "Jane Doe"
},
"hobbies": ["reading", "hiking", "coding"]
}
}

Then, in your template:

<!-- Accessing nested object properties -->
{{ .user.details.name }}
<!-- Accessing array elements using index function -->
{{ index .user.hobbies 0 }} <!-- outputs: reading -->
{{ index .user.hobbies 1 }} <!-- outputs: hiking -->
{{ index .user.hobbies 2 }} <!-- outputs: coding -->

Array and String (Text) Slicing

<body>
<!-- Using slice to extract parts of an array -->
<p>Full List: {{ .numbers }}</p>
<p>Slice [1:3]: {{ slice .numbers 1 3 }}</p>
<p>Slice [:2]: {{ slice .numbers 0 2 }}</p>
<p>Slice [2:]: {{ slice .numbers 2 }}</p>
<p>Slice [1:4:4]: {{ slice .numbers 1 4 4 }}</p>
<!-- Using slice on a string -->
<p>Original String: "{{ .text }}"</p>
<p>Slice [1:4]: "{{ slice .text 1 4 }}"</p>
</body>

Matching JSON Data:

{
"numbers": [10, 20, 30, 40, 50],
"text": "Hello, World!"
}

Explanation:

  1. Array slicing:

    • slice .numbers 1 3 returns [20, 30] (elements from index 1 to 3, exclusive).
    • slice .numbers 0 2 returns [10, 20] (elements from the start to index 2, exclusive).
    • slice .numbers 2 returns [30, 40, 50] (elements from index 2 to the end).
    • slice .numbers 1 4 4 is equivalent to Go syntax numbers[1:4:4] (advanced slicing for specifying capacity, often used for reslicing).
  2. String slicing:

    • slice .text 1 4 returns β€œell” (characters from index 1 to 4, exclusive).

Logic Examples

Using a Boolean Field:

{{ if .isActive }}
<p>The item is active.</p>
{{ else }}
<p>The item is not active.</p>
{{ end }}

Matching Data:

{
"isActive": true
}

If-Else Example:

{{ if eq .status "success" }}
<p>Operation was successful.</p>
{{ else if eq .status "pending" }}
<p>Operation is pending.</p>
{{ else }}
<p>Operation failed.</p>
{{ end }}

Matching Data:

{
"status": "success"
}

Using with

With sets the scope to a specific data structure, reducing complexity when accessing nested fields.
Example:

{{ with .user }}
<p>Name: {{ .name }}</p>
<p>Email: {{ .email }}</p>
{{ end }}

Matching Data:

{
"meta": {
"version": 1,
"someOtherKey": "someOtherValue"
},
"user": {
"name": "John",
"email": "john@example.com"
}
}

Explanation: Inside the with block, . refers to .user. This reduces complexity when accessing nested fields.

Define a Sub Template

Define a Sub Template: Use define to create reusable named sub templates:

{{ define "greeting" }}
<p>Hello, {{ .name }}!</p>
{{ end }}

Invoke a Defined Template: Use template to invoke a named template:

{{ template "greeting" . }}

Logical Operators

The template engine provides several logical operators for complex conditions:

OperatorDescriptionExampleResult
andReturns true if both conditions are true{{ if and .isAdmin .isActive }}True only if both isAdmin and isActive are true
orReturns true if either condition is true{{ if or .isAdmin .isModerator }}True if either isAdmin or isModerator is true
notInverts a boolean value{{ if not .isDisabled }}True if isDisabled is false

Example usage:

{{ if and .isLoggedIn (not .isBanned) }}
<p>Welcome back, {{ .username }}!</p>
{{ else if or .isGuest .isNewUser }}
<p>Please complete your profile.</p>
{{ else }}
<p>Access denied.</p>
{{ end }}

Matching Data:

{
"isLoggedIn": true,
"isBanned": false,
"isGuest": false,
"isNewUser": false,
"username": "John"
}

This will output:

<p>Welcome back, John!</p>

Note: You can combine multiple operators and use parentheses to control precedence:

{{ if and (or .isAdmin .isModerator) (not .isOnVacation) }}
<p>You can moderate content.</p>
{{ end }}

Comparison Functions

The template engine provides several comparison operators for numeric and text (string) values:

OperatorDescriptionExampleResult
eqEqual to{{ if eq .count 10.0 }}True if count equals 10.0
neNot equal to{{ if ne .status "error" }}True if status is not β€œerror”
ltLess than{{ if lt .price 20.0 }}True if price is less than 20.0
leLess than or equal to{{ if le .quantity 5.0 }}True if quantity is less than or equal to 5.0
gtGreater than{{ if gt .age 18.0 }}True if age is greater than 18.0
geGreater than or equal to{{ if ge .score 90.0 }}True if score is greater than or equal to 90.0

Example usage:

{{ if and (ge .age 18.0) (lt .age 65.0) }}
<p>Working age adult</p>
{{ else if lt .age 18.0 }}
<p>Minor</p>
{{ else }}
<p>Senior citizen</p>
{{ end }}

Matching Data:

{
"age": 25.0
}

This will output:

<p>Working age adult</p>

Note: All number comparisons in Comnoco templating must use decimal numbers (e.g., use 10.0 instead of 10).

Escaping Functions

Use specialized functions to escape output.
HTML Escaping:

<div>{{ .userInput | html }}</div>

JavaScript Escaping:

<script>var data = "{{ .jsonData | js }}";</script>

URL Query Escaping:

<a href="/search?q={{ .query | urlquery }}">Search</a>

Adding Variables

You can declare and use variables within your template. Variables are local to the scope they are defined in. Examples:

{{ $greeting := "Hello, World!" }}
<p>{{ $greeting }}</p>
{{ $count := 2 }}
{{ if eq $count 1 }}
<p>Count is one.</p>
{{ else }}
<p>Count is not one.</p>
{{ end }}

Trim Markers

Use trim markers ({{- and -}}) to manage whitespace in your templates. This helps keep nested templates readable and clean, especially with conditional blocks.

Example:

<div>
{{ if .showGreeting }}
<p>
{{- .greeting -}}
</p>
{{ end }}
<p>
{{- if .showName -}}
Hello, {{ .name }}!
{{- else -}}
Hello, Guest!
{{- end -}}
</p>
</div>

Matching Data:

{
"showGreeting": true,
"greeting": "Welcome to our website",
"showName": true,
"name": "John"
}

This will output (notice the lack of extra whitespace):

<div>
<p>Welcome to our website</p>
<p>Hello, John!</p>
</div>

Without trim markers, the same template would output:

<div>
<p>
Welcome to our website
</p>
<p>
Hello, John!
</p>
</div>

Important Notes:

  • {{- (with space) trims all whitespace before the block
  • -}} (with space) trims all whitespace after the block
  • Be careful with {{-3}} vs {{- 3}} - the first is treated as a negative number, the second trims whitespace before outputting 3
  • Trim markers are especially useful in loops and conditional blocks to prevent unwanted line breaks and indentation

Comments

Use comments to document or temporarily disable parts of a template during development or debugging. Single-line comment:

{{/* This is a single-line comment */}}

Multi-line comment:

{{/*
This is a multi-line comment.
It will not be rendered.
*/}}

With Trim Markers:

{{- /* Comment with whitespace trimming */ -}}

The template engine provides several print functions for formatting output:

Basic Print Functions

<!-- Simple print concatenates arguments -->
<p>{{ print "Hello, " .name "!" }}</p>
<!-- Printf allows formatted output -->
<p>{{ printf "Balance: $%.2f" .balance }}</p>
<!-- Println adds spaces between arguments and a newline -->
<p>{{ println "Name:" .name "Age:" .age }}</p>

Matching Data:

{
"name": "John",
"balance": 125.679,
"age": 30
}

This will output:

<p>Hello, John!</p>
<p>Balance: $125.68</p>
<p>Name: John Age: 30</p>

Format Specifiers

Common format specifiers for use with printf:

<!-- Numbers (all numbers are decimals/floats) -->
<p>Default number: {{ printf "%v" .amount }}</p>
<p>Fixed decimals: {{ printf "%.2f" .amount }}</p>
<p>No decimals: {{ printf "%.0f" .amount }}</p>
<p>Scientific: {{ printf "%e" .amount }}</p>
<!-- Strings (text) -->
<p>Plain string: {{ printf "%s" .message }}</p>
<p>Quoted string: {{ printf "%q" .message }}</p>
<!-- Boolean -->
<p>Boolean value: {{ printf "%t" .isActive }}</p>

Matching Data:

{
"amount": 1234.5678,
"message": "Hello World",
"value": {"key": "sample"},
"isActive": true
}

This will output:

<p>Default number: 1234.5678</p>
<p>Fixed decimals: 1234.57</p>
<p>No decimals: 1235</p>
<p>Scientific: 1.234568e+03</p>
<p>Plain string: Hello World</p>
<p>Quoted string: "Hello World"</p>
<p>Boolean value: true</p>

Note: Since all numbers in Comnoco are treated as decimals/floats, always use float formatting specifiers (%f, %e, %E, %v) rather than integer specifiers like %d.

Returns
Text

Parameters

ParameterParameterValid BlocksRequired
Set an Override Name Show the override name slot in the tree so that it can be set statically or dynamically Boolean Block Group No
Override Name The override name of this item. Use this to replace the inherited name with a custom name. Expose it on the tree to set it dynamically. Text Block Group No
Attributes Metadata values for this block. Used in XML and multipart/form-data. Text Block Group No
Template to use The text template to use. Substitute values into the template using the dot notation, e.g. 'open curly brace' 'open curly brace' .keyname 'close curly brace' 'close curly brace' Text Block Group No
Data The values to substitute. Must be a Data Structure or valid JSON. Key names must be referenced in the template using the dot notation, e.g. 'open curly brace' 'open curly brace' .keyname 'close curly brace' 'close curly brace' Marshalled Data Block Group No