# Templating

The templating module is used throughout this and most of the other applications which ship with eXist. Its design has one goal: a clean separation of concerns. All views are plain, valid HTML5. They do not include any XQuery or other executable code. Application code should go into separate XQuery modules and will be called automagically by the templating framework.

This document provides a number of simple, working examples. For a detailed description of the features of the templating framework, refer to the documentation.

The templating module scans the HTML for elements with class attributes following a simple convention and tries to translate them into XQuery function calls. In the simplest case, a class attribute which triggers a function call just contains the name of a function in an XQuery library known to the system. For example:

<div class="ex:hello"></div>

The expanded output of this template call is shown below:

Here's the code for the templating function. The two parameters are required for any function to be used by the templating framework:

$node
  The HTML node being processed. This is the node with the class attribute which triggered the templating call.
$model
  Application data which may have been provided by template functions further up in the document (see below)

declare function ex:hello($node as node()*, $model as map(*)) as element(span) { <span>Hello World!</span> };

Note: instead of putting template calls into class attributes, you can also use the HTML5-compliant method: specify the template call as well as any optional parameters (see the section below) in data attributes:

## Parameter Injection

Very often, you will also need to pass static parameters to the template. This is done by appending a query string to the template call:

<div class="ex:multiply?n1=5&n2=8"></div>

This calls the following function:

declare function ex:multiply($node as node()*, $model as map(*), $n1 as xs:int, $n2 as xs:int) { $n1 * $n2 };

Parameters can be static or dynamic. Static parameters are specified in the HTML as in the example above. Dynamic parameters are read from the HTTP request or HTTP session. The templating framework automatically tries to determine a value for a given function parameter by looking at those alternatives in turn. If you add "?n1=2&n2=4" to the location URL of this page in your browser, you'll see how the output below will change:

Again, the expanded output is shown below:

## Annotations

By default, the return value of a templating function will replace the HTML node it was called for. This means the element will be lost unless you copy it. To avoid manually copying the wrapper element, the `%templates:wrap` annotation does just that.

There's also an annotation `%templates:default` to define a fallback value for a parameter.

declare %templates:wrap %templates:default("language", "en") function ex:hello-world($node as node(), $model as map(*), $language as xs:string, $user as xs:string) as xs:string { switch($language) case "de" return "Hallo " || $user case "it" return "Ciao " || $user default return "Hello " || $user };

This function could be called with:

<div class="hi ex:hello-world?user=Mary></div>

Please note the extra class "hi", which should color the div. Without %templates:wrap, it would have been lost. Output below:

## Nested Template Calls

Templating calls can be nested, which enables us to build more complex HTML structures. For example:

<table class="ex:addresses"> <tr class="templates:each?from=addresses&amp;to=address"> <td class="ex:print-name"></td> <td class="ex:print-street"></td> <td class="ex:print-city"></td> </tr> </table>

`ex:addresses` retrieves a set of addresses from the database and puts them into the `$model`. `templates:each` iterates through the model items and processes its inner HTML once for each item. Finally, the `ex:print-name` and friends print out a specific field of the address.

The corresponding XQuery functions are:

declare %templates:wrap function ex:addresses($node as node(), $model as map(*)) as map(*) { map { "addresses" := collection($config:app-root || "/data/addresses")/address } }; declare %templates:wrap function ex:print-name($node as node(), $model as map(*)) { $model("address")/name/string() }; declare %templates:wrap function ex:print-city($node as node(), $model as map(*)) { $model("address")/city/string() }; declare %templates:wrap function ex:print-street($node as node(), $model as map(*)) { $model("address")/street/string() };

Again, the HTML output is displayed below:

## Source Links

- The template functions used for the examples in this page.
- The main XQuery which triggers the templating in this app.
- Shakespeare app: the HTML and the XQuery module implementing the templating functions.