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
}

implicit def formElem2NodeSeq[T](e: FormElement[T]) = e.toNodeSeq

Then, the SHtml methods would have signatures like this instead:

def textarea[T](contents: String, onSubmit: (String) => T, attrs :
(String, String)*): FormElement[T]
def submit[T](label: String, onSubmit: () => T, attrs: (String,
String)*): FormElement[T]

With the implicit conversion in scope, these could be used exactly
like their current counterparts, but there's another way they could be
used as well. Here's what the problem I'm facing might look like with
this construction, along with the ability for ajaxForm to take a
closure as above:

val text: FormElement[NodeSeq] = SHtml.textArea("", s => parse(s),
"rows" -> "40", "cols" -> "120")
val submit: FormElement[JsCmd] = SHtml.submit("Parse", () =>
SetHtml("results", text!))

ajaxForm(
  bind("plan", xhtml, "dsl" -> text, "submit" -> submit),
  () => submit!
)

What do you think?

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