Up: Part I

5 Snippets

Put simply, a snippet is a Scala method that transforms input XML into output XML. Snippets act as independent (or dependent, if you want) pieces of logic that you insert into your page to perform rendering. As such, snippets form the backbone of Lift’s View-First rendering architecture. Although snippets aren’t the only mechanism Lift has for rendering page views (see Views, Section 4.4 on page 1↑, Custom Dispatch, Section 3.8 on page 1↑, or even the REST API, Chapter 15↓), they’re so widely used and so important that we feel they warrant their own chapter.
In this chapter we will cover the ins and outs of snippets, from the snippet tag that you place in your templates, through how the snippet method is resolved, to the snippet method definition itself. We’ll also cover related topics and some advanced functionality in snippets for those looking to push Lift’s boundaries.

5.1 The Snippet Tag

Usage: <lift:snippet type="snippetName" ...options... />
       <lift:snippetName ...options... />
       <div class=”lift:snippetName?opt1=...;opt2=...;opt3=...” />
The snippet tag is what you use to tell Lift where and how to invoke a snippet method on given XML content. The most important part of the tag is the snippet name, which is used to resolve which snippet method will process the snippet tag contents. We’ll cover how the snippet name is resolved to a concrete method in section 5.2↓.
Note that there is a shorthand for the type attribute simply by appending the snippet name after the lift: prefix. If you use this shorthand, make sure to avoid naming your snippets the same as Lift’s built-in tags, such as surround, children, embed, etc.
In addition to the the type attribute, Lift will process several other options:
form If the form attribute is included with a value of either “POST” or “GET”, then an appropriate form tag will be emitted into the XHTML using the specified submission method. If you omit this tag from a snippet that generates a form, the form elements will display but the form won’t submit.
multipartThe multipart attribute is a boolean (the default is false, specify “yes”, “true” or “1” to enable) that specifies whether a generated form tag should be set to use multipart form submission. This is most typically used for file uploads (Section 6.4↓). If you don’t also specify the form attribute then this won’t do anything.
eager_evalThe eager_eval attribute is a boolean (the default is false, specify “yes”, “true” or “1” to enable) that controls the order of processing for the snippet tag contents. Normally, the snippet is processed and then the XML returned from the snippet is further processed for Lift tags. Enabling eager_eval reverses this order so that the contents of the snippet tag are processed first. We cover this in more detail with an example in Section 5.3.4↓.
With Lift 2.2’s Designer-Friendly Templates (Section 4.2 on page 1↑), you can also specify a snippet tag as part of the class attribute for a given element. Attributes for snippets invoked in this manner are passed via a query string. Listing 5.1↓ shows an example of how we can use the standard lift:surround processing by modiying the class of our content element.
Invoking Snippets Via the Class Attribute
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
   <head>
	<title>Not really</title>
   </head>
   <body class="lift:content_id=real_content">
     <div class="lift:surround?with=default;at=content" id="real_content">
       <h1>Welcome to your project!</h1>
     </div>
   </body>
 </html>

5.2 Snippet Dispatch

The first step taken by Lift when evaluating a snippet tag is to resolve what snippet method will actually process the content. There are several mechanisms that are used to resolve the method, but they can be broken down into two main approaches: dispatch via reflection and explicit dispatch. In addition, Lift allows per-request remapping of snippet names via S.mapSnippet. We’ll cover each in the following sections.

5.2.1 Implicit Dispatch Via Reflection

The simplest, and default, approach to resolving snippet names is to use implicit dispatch via reflection. When using implicit dispatch, Lift will use the snippet name specified in the snippet tag to first locate a class. Lift will then either instantiate a class, or if it’s a stateful snippet (we’ll cover stateful snippets in Section 5.3.3↓), retrieve the current instance. One Lift has a class instance, it uses the snippet name to further determine which method in the class to execute. There are three ways to specify this:
  1. Via the type attribute on the snippet tag. The value should be “ClassName:method” for the particular snippet method you want to have handle the tag
  2. Via a tag suffix of Class.method. This is the same as specifying the type=”Class:method” attribute
  3. Via a tag suffix of just Class. This will use the render method on the specified class to handle the tag
Classes are resolved as specified in Section 3.2.1↑.
The most important thing to remember when using implicit dispatch is that your snippet classes must be members of a snippet subpackage as registered by LiftRules.addToPackages. For example, if you have LiftRules.addToPackages(“com.foo”) in your Boot.boot method, snippets should be members of com.foo.snippet.
Listing 5.2.1↓ shows three equivalent snippet tags. Note: these are only equivalent because the method name is “render.” If we had chosen a different method, e.g., “list,” then the third example below will still call a “render” method.
It’s important to note that with pure implicit dispatch, Java’s reflection allows access to any method on the enclosing class, no matter what the protection on the method is set to (e.g. private, protected). Because of this, it’s possible to invoke private and protected methods via implicit dispatch, which could be a security concern.This is one reason that we recommend using either DispatchSnippet or explicit dispatch for production sites. We’ll cover both of these approaches momentarily.
Another important note is that lookup via reflection is relatively expensive [U]  [U] See http://www.jguru.com/faq/view.jsp?EID=246569 for a more thorough explanation operation, yet another reason that we recommend explicit dispatch for production sites.
Snippet Tag Equivalence
<lift:snippet type="MyClass:render" />
<lift:MyClass.render />
<lift:MyClass />
In addition to “pure” implicit dispatch, you can exert a little more control on which method in a given class handles a snippet by implementing the net.liftweb.http.DispatchSnippet trait. This trait contains a single method, dispatch, of type PartialFunction[String, NodeSeq ⇒ NodeSeq] that maps the method name (the “method” part of “Class.method” or “Class:method” as described above) to a particular method. Only method names defined in the dispatch PartialFunction can be executed; any methods that aren’t covered by the partial function will result in a snippet failure. Listing 5.2.1↓ shows how you can control the dispatch by providing a custom dispatch def.
Using DispatchSnippet to Control Snippet Method Selection
package com.foo.snippet
​
import scala.xml.{NodeSeq,Text}
import net.liftweb.http.DispatchSnippet
​
class SomeSnippetClass extends DispatchSnippet {
  def dispatch : DispatchIt = {
    // We have to use a partially-applied (trailing "_") version
    // of the functions that we dispatch to
    case "foo" => myFooMethod _ 
    case "bar" => someOtherBarMethod _
    case _ => catchAllMethod _
  }
​
  def myFooMethod (xhtml : NodeSeq) : NodeSeq = { ... }
  def someOtherBarMethod (xhtml : NodeSeq) : NodeSeq = { ... }
  def catchAllMethod(xhtml : NodeSeq) : NodeSeq = Text("You’re being naughty!")
}
To summarize, implicit dispatch is the default method by which Lift resolves snippet tag names to the actual class and method that will process the snippet tag contents. Although implicit dispatch is simple to use and works well, security concerns lead us to recommend the use of the DispatchSnippet trait. Even with DispatchSnippet, however, the implicit class resolution still uses reflection, so if you’re trying to make things performant you should use explicit dispatch instead.

5.2.2 Explicit Dispatch

Explicit dispatch allows you to have direct control over which methods will be executed for a given snippet name. There are two ways that you can define snippet name to method mappings: via LiftRules.snippetDispatch, which points Lift to DispatchSnippet instances, and LiftRules.snippets, which points Lift directly at methods.
Let’s first take a look at LiftRules.snippetDispatch, the more generic option. When a snippet tag is encountered with a snippet name of the form A.B or A:B, Lift will take the first portion (A) and use that as the lookup for snippetDispatch. The PartialFunction needs to return an instance of DispatchSnippet, so typically you will implement your explicit dispatch snippets using an object instead of a class. Listing 5.2.2↓ shows how we define our object. Note that the dispatch method will be executed with the “B” portion of the snippet name (as we defined above) as its argument. Other than the fact that it’s an object, the definition is essentially identical to our implicit dispatch class in Listing 5.2.1↑.
Defining an Explicit Snippet Object
// The package *doesn’t* need to be "snippet" because there’s
// no reflection involved here
package com.foo.logic
​
import scala.xml.{NodeSeq,Text}
import net.liftweb.http.DispatchSnippet
​
object HelloWorld extends DispatchSnippet {
  // We define dispatch as a val so that it doesn’t get re-created
  // on each request 
  val dispatch : DispatchIt = {
    case name => render(name) _
  }
​
  def render (name : String)(ignore : NodeSeq) : NodeSeq = 
    Text("Hello, world! Invoked as " + name)
}
Now that we have our snippet object, we can bind it to a particular snippet name in our Boot.boot method, as shown in Listing 5.2.2↓. It’s interesting to note that this is actually how Lift defines many of its tags, such as <lift:embed/>, <lift:surround/>, and <lift:comet/>. In our case, we’ve bound our snippet object to <lift:HelloWorld/>, and because our DispatchSnippet uses a simple variable binding for its dispatch method case, we can invoke the same snippet with <lift:HelloWorld.hey />, <lift:HelloWorld.useless/>, or even <lift:HelloWorld.this_is_getting_silly/>, and the snippet will tell us what name it was invoked with (<lift:HelloWorld/> will invoke with the name “render”, following Lift’s normal snippet tag conventions). Noe that if you’re setting up a dispatch for a StatefulSnippet, return a new instance of your StatefulSnippet class. StatefulSnippet instances will properly register themselves ahead of the snippetDispatch partial function on each successive request.
Binding Our Explicit Snippet Object
class Boot {
  def boot {
    ...
    LiftRules.snippetDispatch.append {
      case "HelloWorld" => com.foo.logic.HelloWorld
      // For StatefulSnippets, return a *new instance*
      case "HelloConversation" => 
        new com.foo.logic.StatefulHelloWorld
    }
  }
}
Now let’s look at LiftRules.snippets. This is a more fine-grained approach to explicit dispatch that doesn’t require the DispatchSnippet trait. Instead, we bind a list of snippet name components corresponding to the parts of the snippet name separated by either “:” or “.”, and point it directly at a given snippet method. Assuming we’re using the same snippet object in Listing 5.2.2↑, we can bind the <lift:HelloWorld/> tag by setting up LiftRules.snippets in our Boot.boot method as shown in Listing 5.2.2↓. Notice that in order to bind the same way that we did with snippetDispatch, we need two lines to match the un-suffixed and suffixed versions. If you omit the un-suffixed line you will get a snippet failure.
Explicitly Binding a Snippet Method
import com.foo.logic
class Boot {
  def boot {
    ...
    LiftRules.snippets.append {
      // Matches a tag without a suffix (<lift:HelloWorld />)
      case List("HelloWorld") => HelloWorld.render("no name") _
      case List("HelloWorld", name) => HelloWorld.render(name) _
    }
  }
}

5.2.3 Per-request Remapping

The final piece of snippet mapping that we want to discuss is per-request remapping. The S.mapSnippet method allows you to modify which snippet method will service a given snippet tag within your page processing. For example, Listing 5.2.3↓ shows how we can conditionally “blank” a snippet based on logic in a second snippet. This functionality isn’t used frequently as the other types of snippet dispatch, but it’s here in case you need it.
Remapping A Snippet
import scala.xml.NodeSeq
import net.liftweb.http.S
​
class Display {
  def header (xhtml : NodeSeq) : NodeSeq = {
    ...
    // If simple is set, we don’t display complexStuff
    S.param("simple").foreach {
      S.mapSnippet("complexStuff", ignore => Text(""))
    }
  }
​
  def complexStuff (xhtml : NodeSeq) : NodeSeq = {
    ...
  }
}

5.3 Snippet Methods

Now that we’ve examined how Lift determines which snippet to execute, let’s look at what a snippet method actually does. A snippet method is essentially a transform, taking a single scala.xml.NodeSeq argument and returning a NodeSeq.
Note: Although Scala can often infer return types, it’s important to explicitly specify the return type of your snippet methods as NodeSeq. Failure to do so may prevent Lift from locating the snippet method if you’re using implicit dispatch (Section 5.2.1↑), in which case the snippet won’t execute!
The argument passed to the snippet method is the XML content of the snippet tag. Because Lift processes XML from the root element down to the child elements (outside-in), the contents of the snippet tag aren’t processed until after the snippet method processes them. You may reverse the order of processing by specifying the eager_eval attribute on the tag (Section 5.3.4↓). As an example, let’s say we wanted a snippet that would output the current balance of our ledger, shown in Listing 5.3↓. We simply return an XML Text node with the formatted balance. Note that the XML result from a snippet is itself processed recursively, so the lift:Util.time snippet will be processed after our snippet method returns.
Returning Tags from a Snippet
class Ledger {
  def balance (content : NodeSeq) : NodeSeq = 
    <p>{currentLedger.formattedBalance}
      as of <lift:Util.time /></p>
}
It is this hierarchical processing of template tags that makes Lift so flexible. For those of you coming to Lift with some JSP experience, Lift is designed to let you write something similar to tag libraries, but that are much more powerful and much simpler to use.

5.3.1 Binding Values in Snippets

So far we’ve shown our snippets generating complete output and ignoring the input to the method. Lift actually provides some very nice facilities for using the input NodeSeq within your snippet to help keep presentation and code separate. First, remember that the input NodeSeq consists of the child elements for the snippet tag in your template.
Snippet Tag Children
<lift:Ledger.balance>
  <ledger:balance/> as of <ledger:time />
</lift:Ledger.balance>
For example, given a template containing the snippet tag shown in Listing 5.3.1↑, the Ledger.balance method receives
<ledger:balance/> as of <ledger:time />
as its input parameter. This is perfectly correct XML, although it may look a little strange at first unless you’ve used prefixed elements in XML before. The key is that Lift allows you to selectively “bind”, or replace, these elements with data inside your snippet. The Helpers.bind [V]  [V] net.liftweb.util.Helpers. Technically the bind method is overloaded, and can even fill in values for the lift:bind tag, but this is advanced usage and we’re not going to cover that here. method takes three arguments:
  1. The prefix for the tags you wish to bind, in this instance, “ledger”
  2. The NodeSeq that contains the tags you wish to bind
  3. One or more BindParam elements that map the tag name to a replacement value
While you can create your own BindParam instances by hand, we generally recommend importing Helpers._, which among other things contains a convenient implicit conversion to BindParam using the “->” operator. With this knowledge in hand, we can change our previous definition of the balance method in Listing 5.3↑ to that in Listing 5.3.1↓ below.
Binding the Ledger Balance
class Ledger {
  def balance (content : NodeSeq ) : NodeSeq = 
    bind ("ledger", content,
          "balance" -> Text(currentLedger.formattedBalance),
          "time" -> Text((new java.util.Date).toString))
}
As you can see here, we actually gain a line of code over our previous effort, but the trade-off makes it far simpler for us to change the layout just by editing the template.
One last aspect of binding that we want to discuss is that any attributes set on the input elements that are being bound will be discarded if you use the “->” binding operator. See Section 5.4↓ for more details on how you manipulate attributes in bindings, including how you can retain attributes on binding elements from your templates by using the “-%>” binding operator instead.

5.3.2 CSS Selector Transforms

In addition to the binding support detailed in Section 5.3.1↑, Lift 2.2 introduces binding via CSS transforms as part of its support for designer friendly templates. These allow you to bind values into template XHTML (or HTML5, see Section 4.3 on page 1↑) by using the attributes on specific elements. Let’s start by looking at a basic example, corresponding to the examples in Section 5.3.1↑.
Listing 5.3.2↓ shows a Designer-Friendly version of Listing 5.3.1↑. You can see that we’re invoking the Ledger.balance snippet via the class attribute, and we’ve specified the binding elements as normal <span/> elements with id attributes.
A Simple CSS Snippet
<div class="lift:Ledger.balance">
  <span id="balance">$0</span> as of <span id="time">midnight</span>
</div>
Now, we need to perform the CSS transform within our snippet. The binding implicits for CSS transforms are found on the net.liftweb.util.BindHelpers object/trait, so you should import it (in particular, the strToCssBindPromoter method). Listing 5.3.2↓ shows how we modify the snippet in Listing 5.3.1↑ to utilize the new CSS transform.
Binding the Ledger Balance with CSS
import net.liftweb.util.BindHelpers._
​
class Ledger {
  def balance = "#balance" #> currentLedger.formattedBalance &
    "#time" #> (new java.util.Date).toString
}
As you can see in this example, CSS transforms are comprised of three parts: the transform selector, the transform operator (#>), and the right hand side value. This value can be a number of different things, which we’ll cover in Section 5.3.2.2↓, but in our case we’re using a MappedField and a String. Additionally, you can chain transforms together with the & operator.

5.3.2.1 CSS Selector Syntax

The selector syntax is based on a subset of CSS, so if you already know that you’re well on your way. The syntax can operate on elements based on id or class, and can also operate on attributes of those elements. Let’s look at the basic syntax:
The element matching the selector is replaced by the result of processing the replacement. That means that in the example of Listing 5.3.2↑ the span elements will be replaced with straight Text elements, resulting in the markup shown in Listing 5.3.2.1↓ (in other words, no remaining markup).
Sample CSS Transform Result
$12.42 as of Fri Jan 14 08:29:50 MST 2011
You can further refine the replacement with an optional qualifier. We’ve already seen how omitting the qualifer results in wholesale replacement of the matching element, but there are a few additional options:

5.3.2.2 Right Hand Side Values

The right hand side of a CSS transform operates on the selected element to either transform or replace it. It can be one of:

5.3.3 Stateless versus Stateful Snippets

The lifecycle of a snippet is stateless by default. That means that for each request, Lift creates a new instance of the snippet class to execute (or uses the same staic method if using explicit dispatch, Section 5.2.2↑). Any changes you make to instance variables will be discarded after the request is processed. If you want to keep some state around, you have a couple of options:
Using a StatefulSnippet is very similar to using a normal snippet but with the addition of a few mechanisms. First, the StatefulSnippet trait extends DispatchSnippet (see Section 5.2.1↑), allowing you to define which methods handle which snippets based on the dispatch method. Because Scala allows defs to be implemented by vars in subclasses, we can redefine the dispatch behavior as a result of snippet processing.
Another thing to remember when using StatefulSnippets is that when you render a form, a hidden field is added to the form that permits the same instance of the StatefulSnippet that created the form to be the target of the form submission. If you need to link to a different page, but would like the same snippet instance to handle snippets on that page, use the StatefulSnippet.link method (instead of SHtml.link); similarly, if you need to redirect to a different page, the StatefulSnippet trait defines a redirectTo method. In either of these instances, a function map is added to the link or redirect, respectively, that causes the instance to be reattached.
When might you use a stateful snippet? Consider a multi-part form where you’d like to have a user enter data over several pages. You’ll want the application to maintain the previously entered data while you validate the current entry, but you don’t want to have to deal with a lot of hidden form variables. Using a StatefulSnippet instance greatly simplifies writing the snippet because you can keep all of your pertinent information around as instance variables instead of having to insert and extract them from every request, link, etc.
Listing 5.3.3↓ shows an example of a stateful snippet that handles the above example. Note that for this example, the URL (and therefore, the template) don’t change between pages. The template we use is shown in Listing 5.3.3↓. Remember to call unregisterThisSnippet() when you’re finished with your workflow in order to stop the current instance from being used.
Using a StatefulSnippet
... standard Lift imports ...
import scala.xml.Text
​
class BridgeKeeper extends StatefulSnippet {
  // Define the dispatch for snippets. Note that we are defining
  // it as a var so that the snippet for each portion of the 
  // multi-part form can update it after validation.
  var dispatch : DispatchIt = {
    // We default to dispatching the "challenge" snippet to our
    // namePage snippet method. We’ll update this below
    case "challenge" => firstPage _
  }
​
  // Define our state variables:
  var (name,quest,color) = ("","","")
​
  // Our first form page
  def firstPage (xhtml : NodeSeq) : NodeSeq = {
    def processName (nm : String) {
      name = nm
      if (name != "") {
        dispatch = { case "challenge" => questPage _ }
      } else {
        S.error("You must provide a name!")
      }
    }
    bind("form", xhtml,
         "question" -> Text("What is your name?"),
         "answer" -> SHtml.text(name, processName))
  }
​
  def questPage (xhtml : NodeSeq) : NodeSeq = {
    def processQuest (qst : String) {
      quest = qst
      if (quest != "") {
        dispatch = { 
          case "challenge" if name == "Arthur" => swallowPage _
          case "challenge" => colorPage _ 
        }
      } else {
        S.error("You must provide a quest!")
      }
    }
    bind("form", xhtml,
         "question" -> Text("What is your quest?"),
         "answer" -> SHtml.text(quest, processQuest))
  }
​
  def colorPage (xhtml : NodeSeq) : NodeSeq = {
    def processColor (clr : String) {
      color = clr
      if (color.toLowercase.contains "No,") {
        // This is a cleanup that removes the mapping for this
        // StatefulSnippet from the session. This will happen 
        // over time with GC, but it’s best practice to manually 
        // do this when you’re finished with the snippet
        this.unregisterThisSnippet()
        S.redirectTo("/pitOfEternalPeril")
      } else if (color != "") {
        this.unregisterThisSnippet()
        S.redirectTo("/scene24")
      } else {
        S.error("You must provide a color!")
      }
    }
    bind("form", xhtml,
         "question" -> Text("What is your favorite color?"),
         "answer" -> SHtml.text(color, processColor))
  }
  // and so on for the swallowPage snippet
  ...
}
The StatefulSnippet Example Template
<lift:surround with="default" at="content">
  <lift:BridgeKeeper.challenge form="POST">
    <form:question /> : <form:answer /> <br />
    <input type="submit" value="Answer" />
  </lift:BridgeKeeper.challenge>
</lift:surround>
If you’re using implicit dispatch (Section 5.2.1↑), then you’re done. If you want to use explicit dispatch, however, you need to do a little more work than usual in the LiftRules.snippetDispatch setup. Listing 5.3.3↓ shows how we can bind our own StatefulSnippet classes without using reflection.
Explicit Dispatch with Stateful Snippets
// In your boot method:
LiftRules.snippetDispatch.append {
  // S.snippetForClass checks to see if an instance has already
  // registered. This is the case after form submission or when
  // we use the StatefulSnippet.link or .redirectTo methods
  case "BridgeKeeper" => S.snippetForClass("TestHello") openOr {
    // If we haven’t already registered an instance, create one
    val inst = new com.test.TestHello
    // The name is what Lift uses to locate an instance (S.snippetForClass)
    // We need to add it so that the Stateful callback functions can
    // self-register
    inst.addName("TestHello")
    // Register this instance for the duration of the request
    S.overrideSnippetForClass("TestHello", inst)
    inst
  }

5.3.4 Eager Evaluation

As we mentioned in Section 5.3↑, Lift processes the contents of a snippet tag after it processes the tag itself. If you want the contents of a snippet tag to be processed before the snippet, then you need to specify the eager_eval attribute on the tag:
<lift:Hello.world eager_eval=”true”>...</lift:Hello.world>
This is especially useful if you’re using an embedded template (Section 4.5.7↑). Consider Listing 5.3.4↓: in this case, the eager_eval parameter makes Lift process the <lift:embed /> tag before it executes the Hello.world snippet method. If the “formTemplate” template looks like Listing 5.3.4↓, then the Hello.world snippet sees the <hello:name /> and <hello:time /> XML tags as its NodeSeq input. If the eager_eval attribute is removed, however, the Hello.world snippet sees only a <lift:embed /> tag that will be processed after it returns.
Embedding and eager evaluation
<lift:Hello.world eager_eval="true">
  <lift:embed what="formTemplate" />
</lift:Hello.world>
The formTemplate template
<lift:children>
<hello:name />
<hello:time />
</lift:children>

5.4 Handling XHTML Attributes in Snippets

It’s a common requirement that elements contain XHTML attributes to control things like style, provide an id, register javascript event handlers, and other functionality. Lift provides two main approaches to applying attributes to elements either in your snippet code or directly in the XHTML template.

5.4.1 Direct Manipulation in Code

You can apply attributes directly to XHTML elements using the “%” operator to apply a
scala.xml.UnprefixedAttribute instance [W]  [W] there’s a corresponding PrefixedAttribute as well to an element. Lift’s net.liftweb.util.Helpers trait contains an implicit conversion from a Pair[String,_] to an UnprefixedAttribute called pairToUnprefixed that allows you to use a simpler syntax. You may chain invocations of “%” to apply multiple attributes. For example, Listing 5.4.1↓ shows how you can apply an “id” and “class” attribute to a text box and to a normal paragraph.
Applying Attributes with %
val myInput = SHtml.text("", processText(_)) % ("id" -> "inputField") % 
  ("class" -> "highlighted")
Note that the % metadata mechanism is actually part of the Scala XML library. Specifically, scala.xml.Elem has a % method that allows the user to update the attributes on a given XML element by passing in a scala.xml.UnprefixedAttribute. We suggest reading more about this in the Scala API documents, or in the Scala XML docbook at http://burak.emir.googlepages.com/scalaxbook.docbk.html.

5.4.2 XHTML Attribute Pass-through

The second main approach to modifying XHTML attributes is to specify them directly in your templates. This has the benefit of allowing your template designers to directly manipulate things like style-related attributes and keeping the markup and the logic separate. Listing 5.4.2↓ shows how you can utilize the “-%>” binding operator instead of “->” to preserve attributes.
Snippet mixin attributes
// the markup
<lift:Ledger.balance>
  <ledger:time id="myId"/>
</lift:Ledger.balance>
​
// The snippet class
​
class Ledger {
  def balance (content : NodeSeq ) : NodeSeq = {
    bind ("ledger", content,
          "time" -%> <span>{(new java.util.Date).toString}</span>)
  }
}
The resulting node will be something like
<span id=”myId”>Sat Mar 28 16:43:48 EET 2009</span>
In addition to the “-%>” binding operator, there is also the “_id_>” operator, which uses the element’s name as its “id” attribute. Listing shows a snippet method using the “_id_>” attribute and Listing shows the resulting markup.
Binding with the _id_> operator
def idByName (xhtml : NodeSeq) : NodeSeq = 
  bind("example", xhtml, "name" _id_> <span>Fred</span>)
Markup bound using _id_>
<!-- Input: -->
<lift:HelloWorld.idByName>
  Hi, <example:name /> 
</lift:HelloWorld.idByName>
​
<!-- Output: -->
Hi, <span id="name">Fred</span> 
Up: Part I

(C) 2012 Lift 2.0 EditionWritten by Derek Chen-Becker, Marius Danciu and Tyler Weir