Semantic CSS styles with Lift

4 views
Skip to first unread message

Jon Brisbin

unread,
Aug 6, 2010, 10:53:28 AM8/6/10
to Liftweb
I'm just learning lift and I'm having a hard time figuring out how to translate something I did in Rails very easily to the equivalent in Lift.

I want to generate semantic CSS style names. In Rails I would do something like:

<body class="<%= @body_class || 'main' %>">

I really can't figure out how to do this in Lift. I suppose I need to wrap it with a helper of some sort:

<lift:semantic_styles.body>
...other XHTML goes here...
</lift:semantic_styles.body>

Or I need to do a bind or something? I'm just not sure. Any suggestions here would be greatly appreciated.

Thanks!

J. Brisbin
http://jbrisbin.com/

Marius

unread,
Aug 6, 2010, 11:11:20 AM8/6/10
to Lift
You can have attribute snippets see https://liftweb.assembla.com/wiki/show/liftweb/More_on_Snippets

Marius

Alex Black

unread,
Aug 6, 2010, 1:48:17 PM8/6/10
to Lift
Attribute snippets as Marius suggested looks like a good idea, here
are two more:

1. Use attribute binding

<lift:MySnippet.mymethod>
<body foo:class="">
</lift:MySnippet.mymethod>

class MySnippet {
def mymethod( xhtml: NodeSeq ): NodeSeq = {
bind("foo", xhtml,
AttrBindParam("class", Text("put-class-here"), "class")
)
}
}

2. Return the body tag from a snippet

<lift:MySnippet.body>
<h1>hello world</h1>
</lift:MySnippet.body>

class MySnippet {
def body(xhtml: NodeSeq): NodeSeq = {
var cls: String = "main"
<body class={cls}>
{ xhtml }
</body>

Alex Black

unread,
Aug 6, 2010, 1:58:41 PM8/6/10
to Lift
The key difference that took me a while to pick up on between Lift and
other template systems i'd used (JSP, ASP, ASP.net) is that Lift is
just transforming XML.

The snippet methods take XML as input, and return XML. Things get
interesting because:

1. the snippet can ignore the input XML and return whatever it wants,

def foo(xhtml: NodeSeq): NodeSeq = <h1>foo</h1>

2. the snippet can repeat the input xml out many times using flatmap
and bind, e.g.

def foo(xhtml: NodeSeq): NodeSeq = List(1,2,3).flatMap { n =>
bind("foo", xhtml, "number" -> n.toString) }

usage:

<lift:MySnippet.foo>
<b><foo:number/></b>
</lift:MySnippet.foo>

output:

<b>1</b>
<b>2</b>
<b>3</b>

3. The snippet can wrap the input as I showed before

def foo(xhtml: NodeSeq): NodeSeq = <p> {xhtml} </p>

4. The snippet can even read the input as parameters if it wanted (not
recommended)

def foo(xhtml: NodeSeq): NodeSeq = { <b>Input contained { (xhtml\
\"div").length } divs</b> }

5. you can also do multiple levels of binding and repeating

def foo(xhtml: NodeSeq): NodeSeq = {
val items = List((1,"a"), (2,"b"), (3,"c"))
def bindItems(xhtml: NodeSeq): NodeSeq = {
items.flatMap { case (number, letter) =>
bind("item", xhtml,
"number" -> number.toString,
"letter" -> letter
}
}
bind("stuff", xhtml,
"label" -> "MyStuff",
"items" -> { (node: NodeSeq) => bindItems(items) }
)
}

usage:

<lift:MySnippet.foo>
<h1><stuff:label/><h1>
<ul>
<stuff:items>
<li><b><item:number></b>: <item:letter></li>
</stuff:items>
</ul>
</lift:MySnippet.foo>

output

<h1>MyStuff</h1>
<ul>
<li><b>1</b>: a</li>
<li><b>2</b>: b</li>
<li><b>3</b>: c</li>
</ul>

Marius

unread,
Aug 6, 2010, 3:57:35 PM8/6/10
to Lift
yup .. the true power comes from simplicity of NodeSeq => NodeSeq
functions
Reply all
Reply to author
Forward
0 new messages