Version 40, last updated by Richard Dallaway at 02 Apr 02:45 UTC

There are various ways to generate output when you’re using Lift but templates are the most popular. They are commonly used when you’re constructing the basic pages of your application. For stuff like RSS feeds you would use a view instead of a template. The difference between templates and views is that with templates you’re creating the response to the client through any number of XML documents and Scala classes (snippets) and with views you’re creating the response entirely in code.

See also: Creating_the_UI_for_Mapper_entities

Templates

A basic Lift template looks like this:

<lift:surround with="default" at="content"> 
  <h2>Template introduction</h2> 
  <lift:mySnippet.example>
    <p>
      This is an introduction to templates. Though it's brief I've got no doubt you'll 
      be very <peer:status /> once you're done and will ready to dive into the many 
      cool aspects of Lift. 
    </p> 
  </lift:mySnippet.example>
</lift:surround>

This is pretty cool, the template is pure xhtml, no in-line code or other nasties. Lets take a look at what happens. <lift:mySnippet.example> invokes the method example on an instance of MySnippet – Snippets are explained in the next section. The example function takes all the child elements and will process the NodeSeq and return another NodeSeq. <lift:surround with="default" at="content"> will surround all of its child elements at the content binding of the template named “default”. Note however that there’s nothing special about lift:surround – it is also a snippet which just happens come bundle with lift because it’s very convenient and is likely to be used in every project.

<lift:surround with="default" at="content"> is really handy as it helps you keep your templates DRY. You will most likely create a “master-template” which defines the main structure with menus, sidebars, footers etc. and then produce the site-specific content in their own templates. Here’s an example:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:lift="http://liftweb.net/">
  <head>
    ..... header stuff .....
  </head>
  <body>
    <div id="container">
      <div id="menu">
        <lift:Menu.builder />
      </div>
      <div id="content">
        <lift:bind name="content" />
      </div>
      <div id="footer">
        <lift:bind name="footer" />
      </div>
    </div>
  </body>
</html>

This way you can easily create a generic template with lots of configuration points. If you want to create a template that gets surrounded by the template above it could look something like this:

<lift:surround with="default">
  <lift:bind-at name="content">
    .. invoke snippet or put html here...
  </lift:bind-at>
  <lift:bind-at name="footer">
    .. invoke snippet or put html here...
  </lift:bind-at>
</lift:surround>

Snippets – Binding content into templates

Lets take a look at how the snippet class would look for the first template.

import net.liftweb.util.Helpers._
...
class MySnippet {
  def example(xhtml: NodeSeq) = {
    bind("peer",xhtml, "status" -> "excited")
  }
}

The method example takes a NodeSeq (this will be all the child nodes of the <lift:mySnippet.example> tag. The method simply invokes the bind function which takes three arguments of which the last can be repeated any number of times. The first argument is the prefix of tags to bind, the second is the NodeSeq in which to find elements to be bound and the last is the list of BindParam bindings to be applied.

You can also import net.liftweb.util.BindPlus._ and get an implicit that lets you use the following style:

  xhtml.bind("peer",  "status" -> "excited")

This makes it easy to bind several prefixes by chaining bind calls:

  xhtml.bind("peer",  "status" -> "excited").bind("otherprefix", "x" -> "y")

Binding attributes

You can also bind attributes. Lets say you want to bind the src attribute of an image you would write the template like this

<lift:mySnippet.image>
  <img myImage:url="" />
</lift:mySnippet.image>

In the snippet you would put the following as part of the BindParam list handed to the bind function:

class MySnippet {
  def image(xhtml: NodeSeq) = bind("myImage",xhtml, AttrBindParam("url","http://url.to/image.jpg","src"))
}

Preserving attributes

It is also handy to know that if you want to preserve attributes of an element that you specified you have to use -%> instead of -> in your BindParam. An example could be the following: <person:name id="yourname" />. The snippet would then have the following bind statement bind("person",xhtml, "name" -%> Text("Mads")) If you don’t use -%> in that template the id of the element will be discarded.

It’s worth noting that AttrBindParam has the following signature

final case class AttrBindParam(name: String, myValue: NodeSeq,newAttr: String)

The reason you’re able to call the AttrBindParam with a string as the second argument, as we did above, is because Lift declares a bunch of implicit conversion which you will have in scope when you import the binding helpers as such net.liftweb.util.Helpers._

When you need to modify an existing attribute value (already given in the template) use FuncAttrBindParam. For example, when template looks like

<div somePrefix:data-item="existing-item-value-" />

then doing

bind("somePrefix", xhtml, FuncAttrBindParam("data-item", ns => ns ++ Text("modified"), "data-item"))

would result in

<div data-item="existing-item-value-modified" />

Working with XHTML

When you try to work with binding for the first time it might look magic, but after all it is just handy tool that replaces content inside your NodeSeq (XHTML) that has been passed to Snippet by enclosing it in tags. Sometimes though, you might want to use your own transformations, so you need to bypass bind.

Common case is where you want to access existing elements or attributes. This is still just an XML so you can use powerful Scala XML support. Let’s say you want to get class attribute content from div.

  <lift:mySnippet.replace>
    <div class="stylestuff" >
    ...
    </div>
  </lift:mySnippet.replace>

In snippet you can access class attribute like:

class MySnippet {
  def replace(xhtml:NodeSeq): NodeSeq = {
      val classcontent = xhtml \ "div" \ "@class"
      // wrap your HTML retaining original class attribute values
      <div class={"menu" + classcontent}>{xhtml}</div>
  }
}

Bind is not your only option here, sometimes it is easier to get there without it.

A bit more advanced example

At some point on your adventure with Lift you’re going to need to iterate over a collection of data. This can be a bit confusing when you’re new to Lift (It was for me at least). Let’s say we want to make a template that will output a table with a row for each alcoholic beverage a fictive person consumed the night before.

<lift:surround with="default" at="content"> 
  <h2>Why my head hurts today</h2> 
  <lift:beerSnippet.count>
    <p>Hello <person:name /> here's a list of the alcoholic beverages you drank last night</p> 
    <table>
      <tr>
        <th>Name of beverage</th>
        <th>Count</th>
      </tr>
      <person:consumption>
        <tr>
          <td> <beverage:name /> </td>
          <td> <beverage:count /> </td>
        </tr>
      </person:consumption>
    </table>
  </lift:beerSnippet.count>
</lift:surround>

The snippet could look like this:

class BeerSnippet {
  def count( xhtml: NodeSeq ) = {
    val consumption = ("Tuborg Beer",2) :: ("Harboe pilsner",2) :: ("Red wine",1) :: ("Pan Galactic Gargle Blaster",1) :: Nil
    def bindConsumption(template: NodeSeq): NodeSeq = {
      consumption.flatMap{ case (bev, count) => bind("beverage", template,"name" -> bev,"count" -> count)}
    }
    bind("person",xhtml, "name" -> "Mads", "consumption" -> bindConsumption _)
  }
}

We’re defining a function inside of the count method. The bindConsumption function also takes a NodeSeq and returns a NodeSeq. It (flat)maps each of the tuples in the consumption list to a Node by binding to the elements of the template found in the beverage namespace. Note that we have to use flatMap instead of map, because map would result in a Seq[NodeSeq] instead of the expected NodeSeq (Seq[Node]). That’s needed to be bound into the <person:consumption> part of the template on line 11.

Note, that this example assume that HtmlProperties in request is set to xhtml and need to be changed when used with Html5Parser :
see HtmlProperties_XHTML_and_HTML5 for details.

Let’s play a bit

The bind function returns a NodeSeq as stated earlier. This means we can invoke the bind function any place that NodeSeq is expected. A place where this gets extremely cool is when you’re constructing complex Javascript HTML nodes on the client side. The Jx function of the net.liftweb.http.js package takes a NodeSeq and creates a javascript function you can call on the client side to construct the XML there.

val xhtml = Template("path" :: "to" :: "file" :: Nil) match {
  case Full(template) => bind("hello", template, "world" -> "Mads says hi!")
  case _ => Text("I'm sorry man, but the template file was nowhere to be found")
}
JsCrVar("createMarkup",Jx(xhtml).toJs)

JsCrVar results in the the following Javascript var createMarkup = function(it){ ... }. Read the Javascript Abstraction Layer article for more in depth information. This way you can create the markup as you would normally do, and decide later if you want to inject it with javascript or just process it as any other template.

Lift tags

We’ve already covered the <lift:surround with=""> and <lift:bind-at name=""> tags, but Lift has a few other tags as well.

Embed

<lift:embed what="template" />

Use it to embed a template within another template, or to access a template from a JsCmd such as SetHtml, ModalDialog, etc.

Note that incoming requests that contain *-hidden in the request will not be serviced, but you can access templates in directories named *-hidden. So, you can put AJAX templates in /ajax-templates-hidden in webapp folder.

Also, Lift’s i18n support extends to templates as well, so you can specify “/ajax-templates-hidden/welcome” and lift will serve the appropriate localized template. For example, if the current locale is set to French Canadian Lift will look for /ajax-templates-hidden/welcome_fr_CA.html, /ajax-templates-hidden/welcome_fr.html, and
/ajax-templates-hidden/welcome.html

Example

<lift:embed what="/ajax-templates-hidden/welcome" />
<lift:embed what="/templates-hidden/greeting">
  <lift:bind-at name="greeting">Hello</lift:bind-at>
  <lift:bind-at name="greetee">World</lift:bind-at>
</lift:embed>

Caveats: JavaScript contained in templates rendered via JsCmd (sent in response to AJAX requests) will not be executed. This includes comet widgets.

Also, embedded doesn’t seem to support an at attribute, so all content must be explicitly bound with bind-at elements.

Comet

<lift:comet type="ClassName" name="optional"/>

Caveats: if you have a <lift:comet /> tag and you’re using the tag from within sending AJAX stuff back, things might not work well.

Ignore

<lift:ignore>children</lift:ignore>

Uses: To have child tags that a browser may parse if the local file is loaded, but should not be included in the rendered code.

This is useful in two areas:

  • To put comments in the page that should not be rendered out the the browser
  • To have CSS and other stuff in the page even though the page will be surrounded by a template

Example

<lift:ignore>
<!-- The database info is scott/tiger -->
</lift:ignore>

Children

<lift:children>children</lift:children>

Uses: An XML file must contain only 1 root element. If you have a file that contains, for example:

<div>This is the first DIV</div><div>This is the other DIV</div>

The file will not parse correctly. So, you can wrap the file in <lift:children/> and the child nodes will be returned. Stand-alone templates may be returned via <lift:embed what="/ajax-hidden/comfirm-delete"/> in SetHtml and other JsCmds that take a NodeSeq.

Example

<lift:children>
  <div>This is the first DIV</div>
  <div>This is the other DIV</div>
</lift:children>

Loc

<lift:loc id="What"/>

Head Merge

Since version 0.4, it is possible to declare several <head> sections anywhere under body (and its children), and every <head> section will be merged into the /html/head standard location at render time. The head section could be created in the html or in scala code (such as a snippet).

However, the HTML5 parser used by Lift won’t allow multiple <head> tags, but <head_merge> can be used instead to achieve the same result.

Example

Take the file: /webapp/template-hidden/default.html

<html>
  <head>
    <title>foo</title>
  </head>
  <body>
    <lift:bind name="content" />
  </body>
</html>

and: /webapp/index.html

<lift:surround with="default" at="content">
  <head>
    <script src="myscript.js"></script>
    <style>
      <!-- css goes here -->
    </style>
  </head>
  <h2>Welcome to the your project!</h2>
</lift:surround>

Will ultimately be rendered like:

<html>
  <head>
    <title>foo</title>
    <script src="myscript.js"></script>
    <style>
      <!-- css goes here -->
    </style>
  </head>
  <body>
    <h2>Welcome to the your project!</h2>
  </body>
</html>

CSS

Use to automatically add blueprint CSS styling:

Usage examples:

<style class="lift:CSS.blueprint"></style>

or

<style class="lift:CSS.fancyType"></style>

Msg & Msgs

Used for rendering messages set through S.notice, S.warning or S.error API’s.

Rendering messages that are associated with given ID’s. For instance the error set by S.error(“email_field_error”, Text(“Email is invalid”)) will be rendered in the place where the below tag appears in the page.

<span class="lift:msg?id=email_field_error"></span>

To render messages generated by calling the S.error(errors: List[FieldError]) method you need to know what field id was used in generating the FieldError. FieldErrors are constructed from classes that implement the FieldIdentifier trait, and such classes must implement the uniqueFieldId method. It is this method that generates the id you must use when rendering the error message.

For example, when you call ‘validate’ on a MappedField instance (e.g. MappedString), the field FieldErrors generated by default use the uniqueFieldId method implementation in the MappedField class, which gives an id of <table name> + "_" + <field name>. So

<span class="lift:msg?id=<table name>_<field name>"></span>

will render FieldErrors generated by MappedField classes, unless you have otherwise overridden the uniqueFieldId method.

You can also style messages by providing attributes like errorClass, warningClass and/or noticeClass. Such as:

<span class="lift:msg?id=email_field_error;errorClass=edit_error_class"></span>

The id that is used when a message is generated is set by FieldIdentifier.uniqueFieldId method. Messages generated by FieldError (e.g. Mapper’s MappedFields have an id equal to value set by MappedField.uniqueFieldId. By default this is

Rendering messages that are not associated with any ID. For instance S.error(Text(“Session is invalid”)) will be rendered in the place where the tag below appears in the page.

<div class = "lift:msgs"></div>

Setting the attribute showAll to true will render all messages, with and without an ID. This will lead to duplicate messages if additionally the Msg built in snippet is used to show messages associated with an ID.

<div class="lift:msgs?showAll=true"></div>

msgs can also be styled like:

<div class = "lift:msgs">
  <lift:error_msg>Error!  The details are:</lift:error_msg>
  <lift:error_class>errorBox</lift:error_class>
  <lift:warning_msg>Whoops, I had a problem:</lift:warning_msg>
  <lift:warning_class>warningBox</lift:warning_class>
  <lift:notice_msg>Note:</lift:notice_msg>
  <lift:notice_class>noticeBox</lift:notice_class>
</div>

HTML5

Use this in your page so that Lift can render a valid HTML 5 page by setting the proper DocType.

<lift:html5/>

lazy-load

You can render asynchronously page fragments like:

.. markup 1 ...
<lift:lazy-load>
   ... markup 2 ...
</lift:lazy-load>
... markup 3 ...

Above the code inside lazy-load will be rendered after the page was rendered. Here you can place any valid xhtml content, lift snippets etc.. This is handy where in some snippet you are rendering markup that contains information coming from remote services, etc. If those operations are taking more time to retrieve, using lazy-load can lead to a better user experience as the rest of the page can still render pretty quick without depending on the remote service responsiveness. See example.

To override ajax-spinner′s default code <img src="/images/ajax-loader.gif" alt="Loading"/> the template attribute can be used:

<lift:lazy-load template="customtemplate">
   ... markup 2 ...
</lift:lazy-load>

test_cond

Used to render content if the user is logged in or logged out

<lift:test_cond.loggedin>
  ... markup here
</lift:test_cond.loggedin>

or

<lift:test_cond.loggedout>
  ... markup here
</lift:test_cond.loggedout>

The test if a user is logged in or not is a user functions set in LiftRules like:
In boot set:

LiftRules.loggedInTest = Full( 
  () => {
    // add here some code that returns a Boolean
  }
)