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.


Reply via email to