Version 10, last updated by geir.hedemark at August 07, 2011 13:13 UTC
Todo Sample Application
This is based on the existing v1 getting started page. The example below uses the Mapper component. It should probably be updated to use Record.
this page is outdated as of Lift version 2.3. The getting started page does no longer coincide with the instructions in this page, and the updated getting started page at liftweb.net (linked below) should be used instead.
Create a new blank application
Create a new lift project using the basic archetype, groupId set to com.liftworkshop and artifactId set to todo.
run the application to ensure that all is working.
Conditional display
Because a todo list is specific to a user, we must ensure that the user is logged in before displaying their todo list. We do this by only rendering the application if the user is logged in. In this first iteration we will display a welcome banner to a logged in user, later we will update this to present the todo application when a user is logged in.
We achieve this by creating a snippet of code that has utility functions within it.
These functions (called loggedIn and loggedOut) return the passed in child nodes if the condition is met, or an empty sequence otherwise. The template can then use these snippets to surround the appropriate content.
For more information about these concepts, please read Templates_and_Binding
Create a new file src/main/scala/com/liftworkshop/snippet/Util.scala with the following code.
package com.liftworkshop.snippet
import scala.xml.{NodeSeq}
import com.liftworkshop._
import model._
class Util {
def loggedIn(html: NodeSeq) =
if (User.loggedIn_?) html else NodeSeq.Empty
def loggedOut(html: NodeSeq) =
if (!User.loggedIn_?) html else NodeSeq.Empty
}
We can then use this snippet inside the html template to display either a message asking the user to login, or a welcome message.
Update src/main/webapp/index.html to contain the following.
<lift:surround with="default" at="content">
<lift:Util.loggedOut>Please
<lift:menu.item name="Login">Log In</lift:menu.item>
</lift:Util.loggedOut>
<lift:Util.loggedIn>
Welcome. You may
<lift:menu.item name="Logout">Log Out</lift:menu.item> if you wish
</lift:Util.loggedIn>
</lift:surround>
Reload the application in your web browser, you should be asked to login. 
Create an account and login and you should see the welcome banner.
Create a model
The next step is to create a model to store the ToDo objects. For more details about models and the Mapper persistence layer, please read Mapper.
Create the file src/main/scala/com/liftworkshop/model/ToDo.scala with the following code.
package com.liftworkshop.model
import net.liftweb._
import mapper._
import http._
import SHtml._
import util._
class ToDo extends LongKeyedMapper[ToDo] with IdPK {
def getSingleton = ToDo
object done extends MappedBoolean(this)
object owner extends MappedLongForeignKey(this, User)
object priority extends MappedInt(this) {
override def defaultValue = 5
}
object desc extends MappedPoliteString(this, 128)
}
object ToDo extends ToDo with LongKeyedMetaMapper[ToDo]
The next step is to add our model to the Schemifier
Update src/main/scala/boostrap/liftweb/Boot.scala so that the Schemifier.schemify line contains a reference to the ToDo model.
Schemifier.schemify(true, Log.infoF _, User, ToDo)
Restart jetty and you should see the following message in the jetty comsole:
INFO - CREATE TABLE todo (desc_c VARCHAR(128) , priority INTEGER , owner BIGINT , done BOOLEAN , id BIGINT NOT NULL AUTO_INCREMENT) INFO - ALTER TABLE todo ADD CONSTRAINT todo_PK PRIMARY KEY(id) INFO - CREATE INDEX todo_owner ON todo ( owner )
Basic persistence
Now that we have created a model to store our ToDo data, it’s time to create the form that will allow users to enter todo data and the code that will insert it into the database. Create the file src/main/scala/com/liftworkshop/snippet/TD.scala with the following code.
package com.liftworkshop.snippet
import com.liftworkshop._
import model._
import net.liftweb._
import http._
import SHtml._
import S._
import js._
import JsCmds._
import mapper._
import util._
import Helpers._
import scala.xml.{NodeSeq, Text}
class TD {
def add(form: NodeSeq) = {
val todo = ToDo.create.owner(User.currentUser)
def checkAndSave(): Unit =
todo.validate match {
case Nil => todo.save ; S.notice("Added "+todo.desc)
case xs => S.error(xs) ; S.mapSnippet("TD.add", doBind)
}
def doBind(form: NodeSeq) =
bind("todo", form,
"priority" -> todo.priority.toForm,
"desc" -> todo.desc.toForm,
"submit" -> submit("New", checkAndSave))
doBind(form)
}
}
Now update src/main/webapp/index.html to contain the following code.
<lift:surround with="default" at="content">
<lift:Util.loggedOut>
Please <lift:menu.item name="Login">Log In</lift:menu.item>
</lift:Util.loggedOut>
<lift:Util.loggedIn>
<lift:TD.add form="post">
<table>
<tr>
<td>Description:</td>
<td><todo:desc>To Do</todo:desc></td>
</tr>
<tr>
<td>
Priority
</td>
<td>
<todo:priority>
<select><option>1</option></select>
</todo:priority>
</td>
</tr>
<tr>
<td> </td>
<td>
<todo:submit>
<button>New</button>
</todo:submit>
</td>
</tr>
</table>
</lift:TD.add>
</lift:Util.loggedIn>
</lift:surround>
Reload the webpage and you should be presented with a textbox for Description and another for Priority. This form is functional, you can enter text and it will be saved, however we have not yet created the code to display the list of todo items.

Show the list of todo items
TODO