Re: [Lift] Re: A better approach to ajax forms?
Those names seem counterintuitive to me. ajaxSubmit submits an ajax form but submitAjaxForm submits a non-ajax form? submitAjaxForm implies that it should be the reverse, no? - Mariusmarius.dan...@gmail.com wrote: Instead of submit - SHtml.submit(Parse, () = ()) use: submit - SHtml.ajaxSubmit(Parse, () = ()) you can also send normal forms via ajax like: SHtml.submitAjaxForm(formId, () = { /// Do your stuff here. This function will be called after form field functions are executed. Noop }) Br's, Marius On Jan 21, 9:03 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: *thump* *thump* Hello, is this thing on? :) On Wed, Jan 20, 2010 at 10:20 AM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Wed, Jan 20, 2010 at 9:51 AM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Wed, Jan 20, 2010 at 9:39 AM, Kris Nuttycombe kris.nuttyco...@gmail.com 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 lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: A better approach to ajax forms?
On Thu, Jan 21, 2010 at 12:23 PM, Marius marius.dan...@gmail.com wrote: Instead of submit - SHtml.submit(Parse, () = ()) use: submit - SHtml.ajaxSubmit(Parse, () = ()) you can also send normal forms via ajax like: SHtml.submitAjaxForm(formId, () = { /// Do your stuff here. This function will be called after form field functions are executed. Noop }) Br's, Marius Thanks, Marius. I've just updated from M1 to the snapshot to get ajaxSubmit; however, it doesn't address my question as to why the function passed to AjaxSubmit doesn't return a JsCmd that can be used to refresh the page. Also, any thoughts on my proposal? Kris On Jan 21, 9:03 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: *thump* *thump* Hello, is this thing on? :) On Wed, Jan 20, 2010 at 10:20 AM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Wed, Jan 20, 2010 at 9:51 AM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Wed, Jan 20, 2010 at 9:39 AM, Kris Nuttycombe kris.nuttyco...@gmail.com 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 lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: A better approach to ajax forms?
On Jan 21, 11:15 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 12:23 PM, Marius marius.dan...@gmail.com wrote: Instead of submit - SHtml.submit(Parse, () = ()) use: submit - SHtml.ajaxSubmit(Parse, () = ()) you can also send normal forms via ajax like: SHtml.submitAjaxForm(formId, () = { /// Do your stuff here. This function will be called after form field functions are executed. Noop }) Br's, Marius Thanks, Marius. I've just updated from M1 to the snapshot to get ajaxSubmit; however, it doesn't address my question as to why the function passed to AjaxSubmit doesn't return a JsCmd that can be used to refresh the page. The ajaxSubmit has the signature: def ajaxSubmit(value: String, func: () = Any, attrs: (String, String) *) returns an Any because Lift looks for the following: JsCmd, NodeSeq JsCommands LiftResponse however for consistency reasons I think I should change it to func: () = JsCmd Also, any thoughts on my proposal? I don't really see the benefits in doing that. Kris On Jan 21, 9:03 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: *thump* *thump* Hello, is this thing on? :) On Wed, Jan 20, 2010 at 10:20 AM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Wed, Jan 20, 2010 at 9:51 AM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Wed, Jan 20, 2010 at 9:39 AM, Kris Nuttycombe kris.nuttyco...@gmail.com 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 lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group athttp://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to
Re: [Lift] Re: A better approach to ajax forms?
On Thu, Jan 21, 2010 at 2:43 PM, Marius marius.dan...@gmail.com wrote: On Jan 21, 11:15 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 12:23 PM, Marius marius.dan...@gmail.com wrote: Instead of submit - SHtml.submit(Parse, () = ()) use: submit - SHtml.ajaxSubmit(Parse, () = ()) you can also send normal forms via ajax like: SHtml.submitAjaxForm(formId, () = { /// Do your stuff here. This function will be called after form field functions are executed. Noop }) Br's, Marius Thanks, Marius. I've just updated from M1 to the snapshot to get ajaxSubmit; however, it doesn't address my question as to why the function passed to AjaxSubmit doesn't return a JsCmd that can be used to refresh the page. The ajaxSubmit has the signature: def ajaxSubmit(value: String, func: () = Any, attrs: (String, String) *) returns an Any because Lift looks for the following: JsCmd, NodeSeq JsCommands LiftResponse however for consistency reasons I think I should change it to func: () = JsCmd Also, any thoughts on my proposal? I don't really see the benefits in doing that. The benefit is predictability; with the current functionality, as I understand it, the order of evaluation of closures associated with form elements is dependent upon the order in which those elements are added to the form. What my proposal does is (1) eliminate the need to close over local vars and (2) eliminate the dependence upon order of declaration. In essence, my proposal is to give the user the ability to, in addition to having those closures invoked automatically on the processing of a form, be able to explicitly invoke them during form processing. I really dislike the pattern: def mySnippet(xhtml: NodeSeq) { var a: Option[String] = None bind(a, xhtml, value - text(. s = a = Some(s)), submit - submit(Submit, () = a.foreach(doSomething _) ) } With my proposal, this would become: def mySnippet(xhtml: NodeSeq) { val aField = text(s, s = s) bind(a, xhtml, value - aField, submit - submit(Submit, () = doSomething(a!)) ) } This becomes really advantageous, I think, when you're talking about 15 or 20 different form elements. The var solution in that case becomes totally unwieldy because of the unwrapping of all of the Options. Kris Kris On Jan 21, 9:03 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: *thump* *thump* Hello, is this thing on? :) On Wed, Jan 20, 2010 at 10:20 AM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Wed, Jan 20, 2010 at 9:51 AM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Wed, Jan 20, 2010 at 9:39 AM, Kris Nuttycombe kris.nuttyco...@gmail.com 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
Re: [Lift] Re: A better approach to ajax forms?
On Thu, Jan 21, 2010 at 2:43 PM, Marius marius.dan...@gmail.com wrote: On Jan 21, 11:15 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 12:23 PM, Marius marius.dan...@gmail.com wrote: Instead of submit - SHtml.submit(Parse, () = ()) use: submit - SHtml.ajaxSubmit(Parse, () = ()) you can also send normal forms via ajax like: SHtml.submitAjaxForm(formId, () = { /// Do your stuff here. This function will be called after form field functions are executed. Noop }) Br's, Marius Thanks, Marius. I've just updated from M1 to the snapshot to get ajaxSubmit; however, it doesn't address my question as to why the function passed to AjaxSubmit doesn't return a JsCmd that can be used to refresh the page. The ajaxSubmit has the signature: def ajaxSubmit(value: String, func: () = Any, attrs: (String, String) *) returns an Any because Lift looks for the following: JsCmd, NodeSeq JsCommands LiftResponse I think I must be misunderstanding something - should I expect the following to work? var text: Option[String] = None ajaxForm( bind(plan, xhtml, dsl - textarea(, s = text = Some(s), id - dsl_text, rows - 40, cols - 120), submit - ajaxSubmit(Create Plan, () = SetHtml(results, buildPlan(text.get))) ) ) where there is div id=results/ in the rendered page? I don't seem to get the expected results back, though it's clear from logging that this is being processed correctly. Kris -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: A better approach to ajax forms?
On Thu, Jan 21, 2010 at 4:36 PM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 2:43 PM, Marius marius.dan...@gmail.com wrote: On Jan 21, 11:15 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 12:23 PM, Marius marius.dan...@gmail.com wrote: Instead of submit - SHtml.submit(Parse, () = ()) use: submit - SHtml.ajaxSubmit(Parse, () = ()) you can also send normal forms via ajax like: SHtml.submitAjaxForm(formId, () = { /// Do your stuff here. This function will be called after form field functions are executed. Noop }) Br's, Marius Thanks, Marius. I've just updated from M1 to the snapshot to get ajaxSubmit; however, it doesn't address my question as to why the function passed to AjaxSubmit doesn't return a JsCmd that can be used to refresh the page. The ajaxSubmit has the signature: def ajaxSubmit(value: String, func: () = Any, attrs: (String, String) *) returns an Any because Lift looks for the following: JsCmd, NodeSeq JsCommands LiftResponse I think I must be misunderstanding something - should I expect the following to work? var text: Option[String] = None ajaxForm( bind(plan, xhtml, dsl - textarea(, s = text = Some(s), id - dsl_text, rows - 40, cols - 120), submit - ajaxSubmit(Create Plan, () = SetHtml(results, buildPlan(text.get))) ) ) where there is div id=results/ in the rendered page? I don't seem to get the expected results back, though it's clear from logging that this is being processed correctly. Kris A bit more, intriguing information: is SetHtml size-limited? It seems to work fine if what I'm passing back is just a URL or something, but if I pass back a 1.5k error message, the message never seems to appear. Kris -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: A better approach to ajax forms?
On Thu, Jan 21, 2010 at 4:04 PM, Kris Nuttycombe kris.nuttyco...@gmail.comwrote: On Thu, Jan 21, 2010 at 4:36 PM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 2:43 PM, Marius marius.dan...@gmail.com wrote: On Jan 21, 11:15 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 12:23 PM, Marius marius.dan...@gmail.com wrote: Instead of submit - SHtml.submit(Parse, () = ()) use: submit - SHtml.ajaxSubmit(Parse, () = ()) you can also send normal forms via ajax like: SHtml.submitAjaxForm(formId, () = { /// Do your stuff here. This function will be called after form field functions are executed. Noop }) Br's, Marius Thanks, Marius. I've just updated from M1 to the snapshot to get ajaxSubmit; however, it doesn't address my question as to why the function passed to AjaxSubmit doesn't return a JsCmd that can be used to refresh the page. The ajaxSubmit has the signature: def ajaxSubmit(value: String, func: () = Any, attrs: (String, String) *) returns an Any because Lift looks for the following: JsCmd, NodeSeq JsCommands LiftResponse I think I must be misunderstanding something - should I expect the following to work? var text: Option[String] = None ajaxForm( bind(plan, xhtml, dsl - textarea(, s = text = Some(s), id - dsl_text, rows - 40, cols - 120), submit - ajaxSubmit(Create Plan, () = SetHtml(results, buildPlan(text.get))) ) ) where there is div id=results/ in the rendered page? I don't seem to get the expected results back, though it's clear from logging that this is being processed correctly. Kris A bit more, intriguing information: is SetHtml size-limited? It seems to work fine if what I'm passing back is just a URL or something, but if I pass back a 1.5k error message, the message never seems to appear. It's not size limited AFAIK. Some browsers may have a limit on String length or the ability to parse super-long JavaScript, but you're probably looking at 16M (24 bits). Kris -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.comliftweb%2bunsubscr...@googlegroups.com . For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- Lift, the simply functional web framework http://liftweb.net Beginning Scala http://www.apress.com/book/view/1430219890 Follow me: http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: A better approach to ajax forms?
Okay, I think I may have found a bug. My returned content contains unescaped braces. In one failure case (this is parsing a DSL) I was testing a parse of a missing end brace - and part of the error message is the original text passed in (with mismatched braces). Figured it out by passing in content with a superfluous end brace - that error returns fine. :) Thought I was going nuts. Kris On Thu, Jan 21, 2010 at 5:08 PM, David Pollak feeder.of.the.be...@gmail.com wrote: On Thu, Jan 21, 2010 at 4:04 PM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 4:36 PM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 2:43 PM, Marius marius.dan...@gmail.com wrote: On Jan 21, 11:15 pm, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Thu, Jan 21, 2010 at 12:23 PM, Marius marius.dan...@gmail.com wrote: Instead of submit - SHtml.submit(Parse, () = ()) use: submit - SHtml.ajaxSubmit(Parse, () = ()) you can also send normal forms via ajax like: SHtml.submitAjaxForm(formId, () = { /// Do your stuff here. This function will be called after form field functions are executed. Noop }) Br's, Marius Thanks, Marius. I've just updated from M1 to the snapshot to get ajaxSubmit; however, it doesn't address my question as to why the function passed to AjaxSubmit doesn't return a JsCmd that can be used to refresh the page. The ajaxSubmit has the signature: def ajaxSubmit(value: String, func: () = Any, attrs: (String, String) *) returns an Any because Lift looks for the following: JsCmd, NodeSeq JsCommands LiftResponse I think I must be misunderstanding something - should I expect the following to work? var text: Option[String] = None ajaxForm( bind(plan, xhtml, dsl - textarea(, s = text = Some(s), id - dsl_text, rows - 40, cols - 120), submit - ajaxSubmit(Create Plan, () = SetHtml(results, buildPlan(text.get))) ) ) where there is div id=results/ in the rendered page? I don't seem to get the expected results back, though it's clear from logging that this is being processed correctly. Kris A bit more, intriguing information: is SetHtml size-limited? It seems to work fine if what I'm passing back is just a URL or something, but if I pass back a 1.5k error message, the message never seems to appear. It's not size limited AFAIK. Some browsers may have a limit on String length or the ability to parse super-long JavaScript, but you're probably looking at 16M (24 bits). Kris -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- Lift, the simply functional web framework http://liftweb.net Beginning Scala http://www.apress.com/book/view/1430219890 Follow me: http://twitter.com/dpp Surf the harmonics -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en. -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: A better approach to ajax forms?
On Wed, Jan 20, 2010 at 9:39 AM, Kris Nuttycombe kris.nuttyco...@gmail.com 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 } } Kris -- You received this message because you are subscribed to the Google Groups Lift group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: A better approach to ajax forms?
On Wed, Jan 20, 2010 at 9:51 AM, Kris Nuttycombe kris.nuttyco...@gmail.com wrote: On Wed, Jan 20, 2010 at 9:39 AM, Kris Nuttycombe kris.nuttyco...@gmail.com 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 lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.