On Wed, Jan 20, 2010 at 9:51 AM, Kris Nuttycombe <[email protected]> wrote: > On Wed, Jan 20, 2010 at 9:39 AM, Kris Nuttycombe > <[email protected]> wrote: >> Hi, all, >> >> I'm working on an AJAX form and feel like I'm missing something: >> namely, how to update the page based upon the result of the form >> submission. >> >> The three ajaxForm methods in SHtml have the following signatures: >> >> def ajaxForm(body : NodeSeq) >> def ajaxForm(body : NodeSeq, onSubmit : JsCmd) >> def ajaxForm(body : NodeSeq, onSubmit : JsCmd, postSubmit : JsCmd) >> >> In these signatures, onSubmit is called by the client prior to form >> submission, and postSubmit is called by the client after successful >> submission. My question is, why is there not a signature like this: >> >> def ajaxForm(body: NodeSeq, result: () => JsCmd) >> >> for which the specified result function will be called, and the JsCmd >> returned to the browser for evaluation after processing of the form >> contents on the server? >> >> Right now, I'm using the following to achieve this effect, but it >> seems really hacky: >> >> val (psId, psJs) = ajaxCall(JsRaw("dsl_text.value"), text => >> After(20, SetHtml("results", parse(text)))) >> >> ajaxForm( >> bind("plan", xhtml, >> "dsl" -> SHtml.textarea("", s => (), "id" -> >> "dsl_text", "rows" -> "40", "cols" -> "120"), >> "submit" -> SHtml.submit("Parse", () => ()) >> ), >> psJs.cmd >> ) >> >> Here, JsCmd is actually doing the heavy lifting prior to form >> submission, with noop implementations for handling of the form >> elements. Seems really hacky. >> >> I feel like I've got to be missing something here, like there's got to >> be a better way to implement this such that the parsing of the >> textarea contents can be done by the closure passed to the >> SHtml.textarea call. How can I do this? >> >> Here's an idea I've been toying with for a while; it would be a >> somewhat significant change to Lift but I feel like there would be >> some benefits. >> >> Instead of SHtml.* having signatures like (String, () => Any, (String, >> String)*) => NodeSeq, imagine that there was a parameterized class >> (call it FormElement) that all of the SHtml methods returned, and then >> an implicit conversion from FormElement to NodeSeq. Might look >> something like this: >> >> trait FormElement[T] { >> def !: T >> def toNodeSeq: NodeSeq >> } > > An addendum: there's an obvious extension available here: > > trait FormElement[T] { self => > def !: T > > def toNodeSeq: NodeSeq > > def map[U](f: T => U): FormElement[U] = new FormElement[U] { > lazy val !: U = f(self!) > lazy val toNodeSeq: NodeSeq = self.toNodeSeq > } > > def flatMap[U](f: T => FormElement[U]): FormElement[U] = new > FormElement[U] { > private lazy val cache = f(self!) > lazy val !: U = cache! > lazy val toNodeSeq = self.toNodeSeq ++ cache.toNodeSeq > } > }
On second thought, that FormElement implementation as a monad is wrong because toNodeSeq would cause strict evaluation of the closure when used in the SHtml.* case. Maybe FormElement just has to be a functor and not a monad. Kris
-- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
