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.
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.
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.
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.
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.
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.
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.
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: {{data.name}}</p>
<p>Age: {{data.age}}</p>
</div>
</script>