Skip to content

Design and templating

bwanab edited this page Feb 2, 2012 · 14 revisions

Design and templating

Many Clojure web applications use Hiccup for HTML templating. If the programmer is also the designer, then Hiccup is ideal. However, most developers are bad at design. We need to work with people who are good at design and who don't need to care about Clojure. ClojureScript One proposes one approach to templating which allows designers to work with HTML, CSS and images without having to set an eye on Hiccup data structures or those pesky parentheses.

A typical designer workflow will look something like this:

  1. Run lein repl
  2. Type (dev-server) to launch the development server
  3. Open a browser to http://localhost:8080 and click the Design button
  4. Click on links to individual pages to assess the current look and feel of each page
  5. Add/Edit files in the templates directory, add CSS and images to public/css and public/images
  6. Update links to the above files by editing public/design.html
  7. Goto step 4 and repeat until the designer is happy

Any changes made to template HTML files can be seen in the browser upon refresh.

Templates, partials, layouts, snippets etc.

ClojureScript One doesn't care how you create HTML. The templating system discussed here is not used by the running application. Its only purpose is to make designers' lives a little better.

To avoid repetition, two new HTML elements are introduced: _include and _within.

_include will include another HTML file in the current file and _within indicates that its content is to be included in another template. When using the _within tag, HTML ids are used to determine which elements are to be replaced.

A simple example will show how these new tags may be used.

Suppose we have a layout file templates/layout.html which contains the following HTML:

<html>
  <head>Example</head>
  <body>
    <_include file="menu.html"/>
    <div id="content"></div>
    <div id="footer"></div>
  </body>
</html>

Furthermore, suppose we have the following two files named templates/menu.html and templates/example.html.

<!-- templates/menu.html -->
<div>Navigation Menu</div>
<!-- templates/example.html -->
<_within file="layout.html">
  <div id="content">New Content</div>
  <div id="footer">A Footer</div>
</_within>

If we point the server at http://localhost:8080/design/example.html, the following file will be served:

<html>
  <head></head>
  <body>
    <div>Navigation Menu</div>
    <div id="content">New Content</div>
    <div id="footer">A Footer</div>
  </body>
</html>

Templating works with files in the templates directory and the public directory. To see other examples, look at the HTML files in these directories..

Including templates in the application

How does the HTML that the designers work with end up in the ClojureScript application? Enlive is an HTML transformation library for Clojure. We use it to extract snippets of HTML and insert them into the application.

You may be wondering how this is possible given that Enlive is a Clojure library and we are working in ClojureScript. That is a great question. The answer can be found in how ClojureScript macros work.

The snippets of HTML that are used in the application are created with the snippets macro shown below.

(defn snippet [file id]
  (render (html/select (html/html-resource file) id)))

(defmacro snippets []
  {:form (snippet "form.html" [:div#content])
   :greeting (snippet "greeting.html" [:div#content])})

Enlive is used to grab two chunks of HTML from the design HTML pages. In both cases it is a div element with a "content" id. Notice that snippets is a macro. In ClojureScript, macros are Clojure macros and run only at compile time. This means we can use any Clojure library from a macro.

The application host page

The JavaScript application we are creating must be hosted within an HTML page. The layout for the host page is contained in a file named templates/application.html. The Clojure namespace one.host-page contains the code for generating the host page for development mode, production mode and for building the deployment artifacts.

JavaScripts which are added to the host page can be configured in the one.sample.config namespace.