3.0 beta 2

Templates

Traditionally, there are two common ways of building user interfaces - via component trees or using html templates. ActiveWidgets allows using both, depending on the task.

The templates and components are closely integrated - the components themselves are implemented using templates while the templates allow very natural inclusion and references of the component tree.

Syntax

The template consists of html markup with embedded expressions.

<div>
    <h1>{{$title}}</h1>
    <div class="content">{{$content}}</div>
</div>

The expressions are separated by double mustaches - {{ and }}.

Expressions

ActiveWidgets templates allow simultaneous access to the local data context and the component tree.

var data = {
    firstName: 'John',
    lastName: 'Smith'
};

// the template refers to the data fields
var tpl = AX.template('{{$firstName}} <b>{{$lastName}}</b>');

// the data context is the first argument of the template function
var html = tpl(data);

The data variables start with $ prefix while component properties are prefixed with @ symbol.

var obj = new AX.Container({

    textInput: {
        component: 'input',
        width: 100
    },

    submitButton: {
        component: 'button',
        text: 'Submit'
    }
});

// the template includes child components
var tpl = AX.template('<div>{{@textInput}} {{@submitButton}}</div>');

// the template is called as a component method ('this' refers to component)
var html = tpl.call(obj);

It is also possible to refer both to the data fields and component properties in the same template or even in the same expression.

var tpl = AX.template('{{ $amountInStock > 0 ? @orderForm : @notificationMessage }}');

// both the component and the data context passed into the template call
var html = tpl.call(obj, data);

The template expressions can be any valid javascript expressions (the data/component references will be replaced with variable names before compiling into the javascript function). The references can also be dot-separated paths. And the component references can be any properties of the component itself, its parent properties or properties of any object up in the component tree.

total: {{ $product.price * $order.amount }}

The expressions can also use constants or any object/function in the global scope.

<div class="alert">{{ AX.i18n(@message) }}</div>

Using templates

The compiled template is a function which accepts data as its first argument and expects this keyword referring to an ActiveWidgets component. Running the template function produces the html result string. To compile a template run AX.template() converter function with the template source.

// compile template string into the template function
var tpl = AX.template(source);

// call template function to produce html string
var html = tpl.call(component, data);

Templates as calculated properties

The template functions are intended for use in ActiveWidgets components as calculated properties.

var tpl = AX.template('Hello, {{@name}}!');

var obj = new AX.Object({
    name: 'John',
    html: tpl
});

obj.html(); // returns 'Hello, John!'

For example, this is how outerHTML property is defined in AX.HTML class -

var outerHTML = AX.template('<{{@tag}}{{@attributes}}>{{@innerHTML}}</{{@tag}}>');

In most cases you don't have to explicitly call AX.template() - common html properties (html, innerHTML, outerHTML) are already defined with AX.template as a converter function.

button.html('{{@icon}} {{@text}}'); // AX.template() converter is called on assignment

When the template function is called as an object property, its data argument is set to the object's bound data record (see Data Binding).

var person = {
    firstName: 'John',
    lastName: 'Smith'
};

var obj = new AX.Component({
    data: person,
    html: 'Hello, {{$firstName}}'
});

HTML vs. plain text

All text fields are escaped before inserting them into the html string produced by the template. To distinguish between plain text strings (which have to be escaped) and html content, the html in ActiveWidgets is always returned as String object. The template functions always return String object (html), so any property defined with AX.template converter will be treated as html content, while all other properties considered plain text and escaped. If you need a static html property (not a template), use AX.html() converter.