The total chat app, including the ask/answer component for soliciting a name comments, etc. is listed on this page. There is no special code to support AJAX/Comet (all the wrapping is done automatically by Lift).
When the Chat comet widget is added to the page, it needs to solict the user for a "chat name". It asks the "AskName" comet widget for the name. Until the AskName comet widget provides a name, all rendering messages are forwarded to AskName. Here's the code for the "AskName":
class Chat extends CometActor with CometListener { private var userName = "" private var chats: List[ChatLine] = Nil /* need these vals to be set eagerly, within the scope * of Comet component constructor */ private val ulId = S.attr("ul_id") openOr "some_ul_id" private val liId = S.attr("li_id") private lazy val li = liId. flatMap{ Helpers.findId(defaultXml, _) } openOr NodeSeq.Empty private val inputId = Helpers.nextFuncName // handle an update to the chat lists // by diffing the lists and then sending a partial update // to the browser override def lowPriority = { case ChatServerUpdate(value) => { val update = (value -- chats).reverse. map(b => AppendHtml(ulId, line(b))) partialUpdate(update) chats = value } } // render the input area by binding the // appropriate dynamically generated code to the // view supplied by the template override lazy val fixedRender: Box[NodeSeq] = S.runTemplate("_chat_fixed" :: Nil, "postit" -> Helpers.evalElemWithId { (id, elem) => SHtml.onSubmit((s: String) => { ChatServer ! ChatServerMsg(userName, s.trim) SetValById(id, "") })(elem) } _) // display a line private def line(c: ChatLine) = { ("name=when" #> hourFormat(c.when) & "name=who" #> c.user & "name=body" #> c.msg)(li) } // display a list of chats private def displayList: NodeSeq = chats.reverse.flatMap(line) // render the whole list of chats override def render = { "name=chat_name" #> userName & ("#"+ulId+" *") #> displayList } // setup the component override def localSetup { askForName super.localSetup } // register as a listener def registerWith = ChatServer // ask for the user's name private def askForName { if (userName.length == 0) { ask(new AskName, "what's your username") { case s: String if (s.trim.length > 2) => userName = s.trim reRender(true) case _ => askForName reRender(false) } } } }
This example demonstrates the power of Scala's Actors and Lift. With very few lines of code, we've got a complete AJAX/Comet app that has Seaside style Ask/Answer for building modal dialogs.