Templates

Alpaca includes an advanced templating system that is driven by views. You can create your own views and templates at compile time (when you actually build Alpaca) or you can override them on the fly at runtime.

Templates can be supplied either as inline functions (which are discovered if you've built them at compile time), as URLs (which are loaded at runtime), as DOM references (which are then sourced) or as HTML strings. In the latter two cases, the templates are acquired and then compiled before use.

Alpaca uses Handlebars by default for its templating engine. However, you can plug in your own templating engine if you wish. In most cases, you won't need to do so since Handlebars is quite capable and easy to extend.

Alpaca renders forms in a nested mechanism, starting from the top and then diving down. Each layer in the dive is essentially a container or a control. Containers are for Arrays and Objects. Controls are for everything else.

A detailed explanation of this structure is provided on the views documentation page.

Layouts

You can control the layout of fields using a layout template. A layout template is simply an HTML block with CSS identifiers that Alpaca can use to allocate fields into appropriate sections of the DOM. For example, you might have a two column layout with two side-by-side columns. The left might have a CSS class left. And the right might have a CSS class right. These can be used to allocate fields to one column or the other.

For more information on layouts, please read through the layouts documentation.

Wizards

You can allocate your fields onto multi-step wizards complete with Previous and Next buttons so that users can complete some fields before moving on the next set of fields. This is achieved in a manner similar to layouts but includes some additional wizard-specific settings so that you can plug in custom validation logic and more.

For more information on wizards, please read through the wizards documentation.

Specific Template Overrides

From a build perspective, you can override controls and templates that are used to render controls at build time, allowing you to produce entirely new field types and views to support them. This is great for developers who want to build their own field libraries for use in their projects or with their clients.

As you've seen with both layouts and wizards, you can also provide HTML templates at runtime. Alpaca compiles them and uses them straight away.

Using this mechanism, if you want, you can override specific templates for a given view at runtime.

Here is an example where we override the message template so that messages are displayed in big red text.

{% raw %} {% endraw %}

Individual Field Overrides

In the previous example, we changed the message template for all fields in the form. We can also do this for individual fields, on at a time, if we wish.

Here is an example of a form where we override just the name field. Note that for field overrides referencing of fields is done via path. The path /name corresponds to the name field right below root. In this example, we use a URL to load a template from another file.

In this case, we override the template control-text which is the template for the text field control.

{% raw %} {% endraw %}

Field Overrides, Paths and Arrays

In the example above, we did a very simple field-level override using a single path element. If you have nested fields, you can use the very sample approach and reference fields using the path semantics. For example, a form with an address object that has a city text field on it could be referenced like this:

/address/city

Using these mechanics, you can override individual fields anywhere in your form.

Alpaca expresses paths for array elements using [x] notation. For example, you might have a form that supports multiple addresses. In this case, the address field might be an array instead of an object.

If you had two elements in the address array, you could reference them like this:

/address[0]
/address[1]

And similarly, if you wanted to reference the city field of either one separately, you would do it like this:

/address[0]/city
/address[1]/city

You can use this fine-grained path specification to override templates at a field level for specific parts of your form. For example, you might want to override the city field for the first address but not the second.

At other times, you might want to generally describe an override for all items in an array. In this case, you can use a generalized field path match like this:

/address/city

Alpaca uses a best-fit approach to find a matching path override. Exact index-based ([x]) path matches are preferred. If you have a path with multiple index-based elements (for example, /a[0]/b[1]/c[2]/d), then multiple matching path overrides might be specified (such as /a/b/c/d or /a[0]/b/c[2]/d). Alpaca does it's thing and finds all matches. It then picks the one that is the most specific to the path.

Here is a list of names with a people array. Each person has a name. We override the second entry (John Rambo)'s name field (templates-example3-control.html). We override to draw a blue box around the control field. We also override all of the fields using a non-index specific path and set names to italics and read-only (templates-example3-control-text.html).

Note: At present, adding and removing new elements only performs DOM creation once (when the new element is inserted). Field overrides are respected at creation time and do not recalibrate on each incremental insert. Thus, be careful with the matching path overrides. They are often more useful for slight tweaks and adjustments. If you're looking for more full-blown custom layout and formatting, custom views, custom layouts and custom fields will prove to be more powerful.

{% raw %} {% endraw %}

Global Templates

If you want to completely do away with Alpaca's views engine and simply provide your own global template to do the rendering, you can also do that! A global template is a template that has access to the data and can elect to represent it any way you want.

These kinds of global templates are useful when you want to display content for rendering purposes. For editing and form interaction, the view engine is extremely useful because it works its way down to actual HTML controls and does all the actual data binding management for you. However, for pure display purposes, global templates can be quite a valuable thing.

Here's a simple display template. This just provides the HTML template as a string.

{% raw %} {% endraw %}

Loading Templates from DOM

We saw how one option to render templates is to provide a URI to a template. That works nicely since the template file is distinct and reusable. However, it also incurs an HTTP load when the browser is rendering. Another option is to reference a DOM element and use the DOM element as a template.

Here is that same global template example using a DOM element.

Note: To use this DOM approach, you have to be sure that the DOM is ready before Alpaca starts. Alpaca will look to the DOM to retrieve the template when Alpaca is initialized (which is right away when you call $.alpaca). Thus, be sure to use the $(document).ready method to ensure the DOM has loaded before Alpaca inits.

You'll have to view source to find the script#template5. But for reference, it looks like this:

<script type="text/x-handlebars-template" id="template5">
    <div>
        <p>Name: {% raw %}{% endraw %}</p>
        <p>Age: {% raw %}{% endraw %}</p>
    </div>
</script>
{% raw %} {% endraw %} {% raw %} {% endraw %}