jComponent / Helpers / Tangular
Updated: 23. May 2019
Author: Peter Širka

Tangular Template Engine

Professional Support Chat with contributors

This template engine is a nice alternative to Handlebars or Mustache template engine. Tangulars supports really great features like:

  • loops
  • conditions
  • custom helpers
  • second model called repository
  • auto-encoding HTML values
  • pre-compiled templates


Usage

Tangular template engine is wrapped into the Ta or Tangular variable defined in window scope:

var template = Tangular.compile('My name is {{ name }} and I am {{ age }} years old.');

console.log(template({ name: 'Peter', age: 34 }));
// Output: My name is Peter and I am 34 years old.

console.log(template({ name: 'Lucia', age: 36 }));
// Output: My name is Lucia and I am 36 years old.

console.log(template({ name: 'Anna', age: 5 }));
// Output: My name is Anna and I am 5 years old.

console.log(template({ name: 'Betty', age: 2 }));
// Output: My name is Betty and I am 2 years old.

Methods

Method: Tangular.compile()

Method compiles a template String to a Function.

Tangular.compile(template);
// template {String}
// returns {Function(model, repository}

var template = Tangular.compile('My name is {{ firstname }} {{ lastname }}.');
// template {Function(model, repository}
// returns {String}

var output = template({ firstname: 'Peter', lastname: 'Širka' });
// output {String}
console.log(output);

Method: Tangular.render()

Method compiles and renders a template String to a String. This method is slower than Tangular.compile() because each calling the template is compilated just in time.

Tangular.render(template, model, [repository]);
// template {String}
// model {Object}
// repository {Object} optional
// returns {String}

var output = Tangular.render('My name is {{ firstname }} {{ lastname }}.', { firstname: 'Peter', lastname: 'Širka' });
console.log(output);

Method: Tangular.register()

This method registers a new custom helper.

Tangular.register(name, callback);
// name {String}
// callback {Function(value, arg1, argN)}
// returns {Tangular}

Tangular.register('lowercase', function(value) {
    return (value || '').toString().toLowerCase();
});

Auto-encoding HTML entities

Tangular automatically encodes all raw values.

var model = { name: 'Pe<b>ter</b>' };

Auto-encoding:

<div>{{ name }}</div>

Renders:

<div>Pe<b>ter</b></div>

Disabled encoding:

<div>{{ name | raw }}</div>

Renders:

<div>Pe<b>ter</b></div>

Loops

  • Tangular can render only Array in loops
  • $index property contains a current index in the Array
{{ foreach m in items }}
    <div>{{ m.name }}</div>
    <div>Current index: {{ $index }}</div>
{{ end }}

Conditions

  • supports {{ else if ... }}
{{ if age > 30 }}
    Is too old.
{{ else }}
    is too young.
{{ fi }}

Custom helpers

  • output from helper is not encoded
Thelpers.reverse = function(value) {
    var arr = (value || '').toString().split('');
    arr.reverse();
    return arr.join('');
};

Thelpers.uppercase = function(value) {
    return (value || '').toString().toUpperCase();
};

Thelpers.add = function(value, plus) {
    return (value || '').toString() + plus;
};

Usage:

<div>{{ name | reverse }}</div>
<div>{{ name | reverse | uppercase }}</div>
<div>{{ name | reverse | uppercase | add(' - Tangular is the best') }}</div>

Repository

Repository is something like a second model. You can access to all properties in the repository via $ keyword:

var template = Tangular.compile('{{ name }} {{ $.name }}');

var output = template({ name: 'Peter' }, { name: 'Širka' });
console.log(output);
// Output: Peter Širka
  • repository can be used in loops and conditions too
  • is optional

Good to know

How to use Tangular with non-reference type?

var template = Tangular.compile('<div class="tag">{{}}</div>');

console.log(template('Node.js'));
// Output: <div class="tag">Node.js</div>

console.log(template('Total.js'));
// Output: <div class="tag">Total.js</div>

console.log(template('jComponent'));
// Output: <div class="tag">jComponent</div>

How can I change Tangular delimiters to another?

// Default settings:
Tangular.settings.delimiters = ['{{', '}}'];

// Custom:
Tangular.settings.delimiters = ['(', ')'];
var template = Tangular.compile('<div>(name)</div>');

console.log(template({ name: 'Peter' }));
// Output: <div>Peter</div>

Best practice

The advice below describes how to store and compiles Tangular template engine in HTML code directly. Browser doesn't render a content inside <script type="text/html> tag.

Example:

<script type="text/html" id="mytemplate">
    <h1>{{ title }}</h1>
    <p>{{ body }}</p>
</script>

<script>
    var template = Tangular.compile($('#mytemplate').html());
    console.log(template({ title: 'Hello world!', body: 'Are you happy?' });
</script>

jComponent built-in helpers

You can use built-in Tangular helpers preddefined in jComponent library:

Pluralize

{{ beers | pluralize('# zero', '# one', '# few', '# more') }}

<!-- +v17 - Supports environments (Array or String values separated by "," comma) -->
{{ beers | pluralize('[beers]') }}

Date formatting

<div>{{ datecreated | format('dd.MM.yyyy') }}</div>

<!-- +v17 - The format below is inherited from "DEF.dateformat" -->
<div>{{ datecreated | format }}</div>

With help of environment key:

<div>{{ datecreated | format('[format]') }}</div>

Number formatting

<div>{{ price | format(2) }}</div>

A currency formatting

+v17 can format a number to currency.

<div>{{ price | currency('eur') }}</div>
<div>{{ price | currency('usd') }}</div>

<!-- The currency below is inherited from "DEF.currency" -->
<div>{{ price | currency }}</div>

Default value

+v17 If the value is null or undefined then the helper renders a default value. Default value is: --- , but can be changed for own value.

<div>{{ name | def }}</div>

OR

<div>{{ name | def('...') }}</div>