# __Tangular__ Template Engine

[![+Professional Support](https://www.totaljs.com/img/badge-support.svg)](https://www.totaljs.com/support/) [![+Chat with contributors](https://www.totaljs.com/img/badge-chat.svg)](https://messenger.totaljs.com)

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

---

- Tangular can be used in Node.js: `$ npm install tangular`
- [Source-code on GitHub](https://github.com/totaljs/Tangular)

---

## Usage

__Tangular__ template engine is wrapped into the `Tangular` variable defined in `window` scope:

```javascript
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`.

```javascript
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.

```javascript
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.

```javascript
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.

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

__Auto-encoding__:

```html
<div>{{ name }}</div>
```
Renders:
```html
<div>Pe&lt;b&gt;ter&lt;/b&gt;</div>
```

__Disabled encoding__:

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

Renders:

```html
<div>Pe<b>ter</b></div>
```

## Loops

- Tangular can render only `Array` in loops
- `$index` property contains a current index in the `Array`

```html
{{ foreach m in items }}
	<div>{{ m.name }}</div>
	<div>Current index: {{ $index }}</div>
{{ end }}
```

## Conditions

- supports `{{ else if ... }}`

```html
{{ if age > 30 }}
	Is too old.
{{ else }}
	is too young.
{{ fi }}
```

## Custom helpers

- output from helper __is not encoded__

```javascript
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__:

```html
<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:

```javascript
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?__

```javascript
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>
```

## 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__:

```html
<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

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

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

### Date formatting

- uses [`Date.format()`](@17092508390003lex1#method-date-format-)

```html
<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__:

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

### Number formatting

- uses [`Number.format()`](@17092508390004lex0#method-number-format-)

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

### A currency formatting

`+v17` can format a number to currency.

- uses [`Number.currency()`](@17092508390004lex0#method-number-currency-)

```html
<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.

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

OR

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