SHtml.idMemoize -- Simple Ajax Updating February 23, 2011
Let's take a look at an example, let's say you have some HTML:
<div class="lift:ShowMemoize">
<button name="refresh_all">Refresh All</button>
<div name="one">
<span>The current time is: </span>
<button>Click Me</button>
</div>
<div name="two">
<button>Update this</button>
<ul>
<li>Count: </li>
</ul>
</div>
</div>
Basically, a <div> that contains two sub-<div>s. We want to be able to click on the buttons and have either or both of the <div>s updated (depending on which button we press). Let's look at the Lift snippet that allows you to redraw part or all of the above HTML:
object ShowMemoize {
def render =
"div" #> SHtml.idMemoize(
outer =>
// redraw the whole div when this button is pressed
"@refresh_all [onclick]" #> SHtml.ajaxInvoke(outer.setHtml _) &
// deal with the "one" div
"@one" #> SHtml.idMemoize(
one =>
"span *+" #> now.toString & // display the time
"button [onclick]" #> SHtml.ajaxInvoke(one.setHtml _)) & // redraw
// deal with the "two" div
"@two" #> SHtml.idMemoize(
two => // the "two" div
// display a bunch of items
"ul *" #> (0 to randomInt(6)).map(i => "li *+" #> i) &
// update the "two" div on button press
"button [onclick]" #> SHtml.ajaxInvoke(two.setHtml _)))
}
This code does the following:
- Selects the outer <div>
- SHtml.idMemoize is a method that takes IdMemoizeTransform => NodeSeqFuncOrSeqNodeSeqFunc as a parameter. That type signature may look weird, so let's break it down:
- It's a function that takes an IdMemoizeTransform as an input and
- returns a NodeSeqFuncOrSeqNodeSeqFunc. "What's a NodeSeqFuncOrSeqNodeSeqFunc?" you ask. It's a NodeSeq => NodeSeq or a Seq[NodeSeq => NodeSeq]... it's basically what you get with a CSS Selector Transform... and there's an implicit conversion from either NodeSeq => NodeSeq or Seq[NodeSeq => NodeSeq] to NodeSeqFuncOrSeqNodeSeqFunc.
- Basically, it's a function that takes the IdMemoizeTransform and returns a CSS Selector Transform
- We capture the outer variable which is the IdMemoizeTransform and the do our normal CSS Selector Transform with it
- We set the onclick attribute of the <button> with id refresh_all to an Ajax invocation of the outer.setHtml() method. So, when the button is clicked, the body of the outer <div> will be redrawn based on the CSS Selector Transform and the template that was used in the transform.
- Each of the inner <div>s get the same treatment and each has a <button> that will redraw just that part of the screen
You can see an example at https://github.com/dpp/starting_point/tree/idMemoize