Skip to content
Brenton Ashworth edited this page Jul 2, 2013 · 9 revisions

Slicing Templates

  • Static vs Dynamic Templates
  • Template Slicing

Slicing Templates

Pedestal provides a very flexible way to write template source files. In order to use these templates in your application we need to extract them from the source.

In our ClojureScript code, we would like to have a map were we can look up a template, add it to the DOM and make changes to it. Pedestal provides functions to help us extract templates from source files.

The file

app/src/tutorial_client/html_templates.clj

contains the code which does this.

(defmacro tutorial-client-templates
  []
  {:tutorial-client-page (dtfn (tnodes "tutorial-client.html" "tutorial" [[:#other-counters]])
                               #{:id})
   :other-counter (dtfn (tnodes "tutorial-client.html" "other-counter") #{:id})})

This is a Clojure macro but you can think of it as a normal Clojure function. The only thing that is different about this function is that it will be run at compile time. When we compile our ClojureScript code, any call to tutorial-client-templates will be replaced with the return value of this function.

This code uses functions form the io.pedestal.app.templates namespace.

The tnodes function converts a template in a file into a sequence of Enlive nodes.

(tnodes "tutorial-client.html" "other-counter")

The third argument to tnodes is a vector in Enlive selectors that we would like to have "cleared". This means that the contents of the these nodes will not be included. This is helpful when you have some example data in the HTML that you don't want in the actual template, as is the case here, when you do not what to include an inner template in an outer one.

(tnodes "tutorial-client.html" "tutorial" [[:#other-counters]])

Because this is a sequence of Enlive nodes we can perform any other transformations that we would like.

There are two ways to turn this data into a template, we can use the functions tfn or dtfn.

tfn is short for template function and will create a function which, when passed a map, will fill in the template with the values in the map and return a string of HTML which can be added to the DOM. Use this when you don't need to update the template after it has been added to the DOM.

dtfn is short for dynamic template function and will create a template which can be updated even after it has been added to the DOM. dtfn takes two arguments, the sequence of nodes and a set of fields static fields. Static fields can be set once when the template is first added to the DOM, but they cannot be changed later. In the example above we would like for the ids to be fields that we set but do want them to change later so we mark them as static fields.

Checking Templates from the REPL

When slicing templates, it can be helpful to confirm that they work form the REPL before trying to use them in your application. In the tutorial-client.html-templates namespace, try some of the following:

Create the template map.

(def t (tutorial-client-templates))

Run the dynamic template function.

(def tf (:other-counter t))
(tf)

which returns

[{:counter-id [{:id G__1866, :type :content}],
  :count [{:id G__1865, :type :content}]}
 #<html_templates$fn__1857$fn__1858 tutorial_client.html_templates$fn__1857$fn__1858@5669e732>]

Get the template constructor function and create the initial template with an id value of 42.

(let [[_ ctor] (tf)]
  (ctor {:id 42}))

which returns

<div id="42" class="counter-row">
  <span class="counter-label">Counter for <span id="G__1878"></span>:</span>
  <span id="G__1877" class="counter"></span>
</div>

Dynamic templates are hard to work with manually. In the rendering section we will see that we don't have to do much on this manual manipulation in practice.

Please note that any time we make changes to the namespace tutorial-client.html-templates the server will have to be restarted of this code reloaded in order for the changes to take effect.

Next steps

In the next step we will write the rendering code which allows our application to use these templates.

The tag for this step is v2.0.10.

Home | Rendering

Clone this wiki locally