Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add ajaxOnSubmit to SHtml #1414

Closed
wants to merge 2 commits into from

3 participants

@Shadowfiend
Owner

ajaxOnSubmit should be used similarly to onSubmit/onSubmitUnit, to
add proper attributes for AJAX submission to a submit input or button element
without changing the element itself. It should take a ()=>JsCmd like ajaxSubmit
and transform the element it's applied to by adding the right name and onclick
attributes (the same ones that ajaxSubmit puts on the element it generates).

@Shadowfiend Shadowfiend Add ajaxOnSubmit as an AJAX complement to onSubmit.
This is meant to be applied to a button or input type="submit" element,
and adds the attributes needed to correctly run an AJAX form submission
using that button.
f6ea85d
@fmpwizard
Owner

+1
This one will go in for 2.6 (and 3.0)

@farmdawgnation farmdawgnation commented on the diff
web/webkit/src/main/scala/net/liftweb/http/SHtml.scala
@@ -1580,6 +1580,43 @@ trait SHtml {
}
/**
+ * Add appropriate attributes to an input type="submit" or button
+ * element to make it submit an ajaxForm correctly and return a JsCmd
+ * to the client.
+ *
+ * Example:
+ *
+ * <pre>"type=submit" #> ajaxOnSubmit(() => Alert("Done!"))</pre>
+ */
+ def ajaxOnSubmit(func: () => JsCmd): (NodeSeq)=>NodeSeq = {
+ val fgSnap = S._formGroup.get
+
+ (in: NodeSeq) => S._formGroup.doWith(fgSnap) {
+ def runNodes(ns: NodeSeq): NodeSeq = {
+ def addAttributes(elem: Elem, name: String) = {
+ val clickJs = "liftAjax.lift_uriSuffix = '" + name + "=_'; return true;"
@farmdawgnation Collaborator

This feels like a magic string that may exist in multiple places in the Lift codebase. Might be worth building a helper function if there isn't one already. Not going to block your PR on it personally, but seemed worth mentioning.

@Shadowfiend Owner

Probably true. May want to wait for a heavier refactoring though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@farmdawgnation farmdawgnation commented on the diff
web/webkit/src/main/scala/net/liftweb/http/SHtml.scala
@@ -1580,6 +1580,43 @@ trait SHtml {
}
/**
+ * Add appropriate attributes to an input type="submit" or button
+ * element to make it submit an ajaxForm correctly and return a JsCmd
+ * to the client.
@farmdawgnation Collaborator

Do you tink we should mention in the docs the contrast between this behavior and ajaxSubmit?

@Shadowfiend Owner

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@farmdawgnation farmdawgnation commented on the diff
web/webkit/src/main/scala/net/liftweb/http/SHtml.scala
((12 lines not shown))
+ def ajaxOnSubmit(func: () => JsCmd): (NodeSeq)=>NodeSeq = {
+ val fgSnap = S._formGroup.get
+
+ (in: NodeSeq) => S._formGroup.doWith(fgSnap) {
+ def runNodes(ns: NodeSeq): NodeSeq = {
+ def addAttributes(elem: Elem, name: String) = {
+ val clickJs = "liftAjax.lift_uriSuffix = '" + name + "=_'; return true;"
+
+ elem % ("name" -> name) % ("onclick" -> clickJs)
+ }
+
+ ns.flatMap {
+ case Group(nodes) => runNodes(nodes)
+
+ case e: Elem if (e.label == "button") ||
+ (e.label == "input" && e.attribute("type").map(_.text) == Some("submit")) =>
@farmdawgnation Collaborator

Should we really lock this into only being used by an <input type="submit">? I could imagine some uses for other types of inputs having such an onclick handler attached to them (e.g. radios). Unless there's a reason other than our expectation of how this will be useful, why not drop the type="submit" requirement?

@Shadowfiend Owner

This is behavior specifically for form submission. Other inputs should not be used to submit forms. I'm tempted to limit it only to button type="submit"s, too, in fact.

@Shadowfiend Owner

Keep in mind the purpose of this is specifically to append the input name to the outgoing data because AJAX serialization does not include the input name. If you click a radio button, you can attach an event handler client-side that makes it submit the form, and the radio button will be included by virtue of regular serialization.

@farmdawgnation Collaborator

Sounds good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@farmdawgnation
Collaborator

If you have a chance to sow up / respond to my remaining comments we could roll this into the 2.6 development branch. :)

@Shadowfiend
Owner

Try 'er again.

@farmdawgnation
Collaborator

Rebased lift_26_dev onto this branch. Closing 'er out.

@farmdawgnation farmdawgnation deleted the asc_issue_1414 branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 26, 2013
  1. @Shadowfiend

    Add ajaxOnSubmit as an AJAX complement to onSubmit.

    Shadowfiend authored
    This is meant to be applied to a button or input type="submit" element,
    and adds the attributes needed to correctly run an AJAX form submission
    using that button.
Commits on Apr 14, 2013
  1. @Shadowfiend
This page is out of date. Refresh to see the latest.
Showing with 40 additions and 0 deletions.
  1. +40 −0 web/webkit/src/main/scala/net/liftweb/http/SHtml.scala
View
40 web/webkit/src/main/scala/net/liftweb/http/SHtml.scala
@@ -1580,6 +1580,46 @@ trait SHtml {
}
/**
+ * Add appropriate attributes to an input type="submit" or button
+ * element to make it submit an ajaxForm correctly and return a JsCmd
+ * to the client. Note that the key difference between this and ajaxSubmit
@farmdawgnation Collaborator

Do you tink we should mention in the docs the contrast between this behavior and ajaxSubmit?

@Shadowfiend Owner

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ * is that ajaxSubmit returns a complete input type="submit" element, while
+ * ajaxOnSubmit applies the right attributes to any input type="submit" *or*
+ * button element.
+ *
+ * Example:
+ *
+ * <pre>"type=submit" #> ajaxOnSubmit(() => Alert("Done!"))</pre>
+ */
+ def ajaxOnSubmit(func: () => JsCmd): (NodeSeq)=>NodeSeq = {
+ val fgSnap = S._formGroup.get
+
+ (in: NodeSeq) => S._formGroup.doWith(fgSnap) {
+ def runNodes(ns: NodeSeq): NodeSeq = {
+ def addAttributes(elem: Elem, name: String) = {
+ val clickJs = "liftAjax.lift_uriSuffix = '" + name + "=_'; return true;"
@farmdawgnation Collaborator

This feels like a magic string that may exist in multiple places in the Lift codebase. Might be worth building a helper function if there isn't one already. Not going to block your PR on it personally, but seemed worth mentioning.

@Shadowfiend Owner

Probably true. May want to wait for a heavier refactoring though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ elem % ("name" -> name) % ("onclick" -> clickJs)
+ }
+
+ ns.flatMap {
+ case Group(nodes) => runNodes(nodes)
+
+ case e: Elem if (e.label == "button") ||
+ (e.label == "input" && e.attribute("type").map(_.text) == Some("submit")) =>
@farmdawgnation Collaborator

Should we really lock this into only being used by an <input type="submit">? I could imagine some uses for other types of inputs having such an onclick handler attached to them (e.g. radios). Unless there's a reason other than our expectation of how this will be useful, why not drop the type="submit" requirement?

@Shadowfiend Owner

This is behavior specifically for form submission. Other inputs should not be used to submit forms. I'm tempted to limit it only to button type="submit"s, too, in fact.

@Shadowfiend Owner

Keep in mind the purpose of this is specifically to append the input name to the outgoing data because AJAX serialization does not include the input name. If you click a radio button, you can attach an event handler client-side that makes it submit the form, and the radio button will be included by virtue of regular serialization.

@farmdawgnation Collaborator

Sounds good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ _formGroup.is match {
+ case Empty =>
+ formGroup(1)(fmapFunc(func)(addAttributes(e, _)))
+ case _ => fmapFunc(func)(addAttributes(e, _))
+ }
+ }
+ }
+
+ runNodes(in)
+ }
+ }
+
+ /**
* Generates a form submission button with a default label.
*
* @param func The function that will be executed on form submission
Something went wrong with that request. Please try again.