diff --git a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormTagLib.groovy b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormTagLib.groovy index aaf3089e3d..a1a1381572 100644 --- a/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormTagLib.groovy +++ b/grails-plugin-gsp/src/main/groovy/org/grails/plugins/web/taglib/FormTagLib.groovy @@ -19,6 +19,7 @@ import grails.artefact.TagLibrary import grails.config.Config import grails.core.support.GrailsConfigurationAware import grails.gsp.TagLib +import grails.web.mapping.LinkGenerator import groovy.transform.CompileStatic import groovy.util.logging.Commons import org.grails.plugins.web.GrailsTagDateHelper @@ -30,7 +31,6 @@ import java.text.DateFormatSymbols import org.grails.core.artefact.DomainClassArtefactHandler import org.grails.encoder.CodecLookup import org.grails.encoder.Encoder -import grails.web.mapping.LinkGenerator import org.grails.buffer.FastStringWriter import org.grails.web.servlet.mvc.SynchronizerTokensHolder import org.grails.buffer.GrailsPrintWriter @@ -519,6 +519,7 @@ class FormTagLib implements ApplicationContextAware, InitializingBean, TagLibrar * @attr action The name of the action to be executed, otherwise it is derived from the value. * @attr disabled Makes the button to be disabled. Will be interpreted as a Groovy Truth */ + @Deprecated Closure actionSubmit = { attrs -> if (!attrs.value) { throwTagError("Tag [actionSubmit] is missing required attribute [value]") @@ -548,6 +549,57 @@ class FormTagLib implements ApplicationContextAware, InitializingBean, TagLibrar out << '/>' } + /** + * Creates a submit button that submits to an action generated by the various link attributes.
+ * + * <g:formActionSubmit action="myaction" value="Submit"/>
+ * <g:formActionSubmit controller="myctrl" action="myaction" value="ButtonName"/>
+ * + * @attr action the name of the action to use in the submit action, if not specified the default action will be linked + * @attr controller the name of the controller to use in the submit action, if not specified the current controller will be linked + * @attr id the id attribute of the formActionSubmit tag + * @attr url A map containing the action,controller,id etc. + * @attr value the button's show value + */ + def formActionSubmit = { Map attrs -> + if (!attrs.value) { + throwTagError("Tag [formActionSubmit] is missing required attribute [value]") + } + + def elementId = attrs.remove('id') + + // Reserved + attrs.remove('type') + attrs.remove('formAction') + attrs.remove('method') // specified by the controller + + out << "' + } + /** * Creates a an image submit button that submits to an action in the controller specified by the form action. * The name of the action attribute is translated into the action name, for example "Edit" becomes diff --git a/grails-plugin-gsp/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy b/grails-plugin-gsp/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy index 8ae3df8751..9294a50e27 100644 --- a/grails-plugin-gsp/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy +++ b/grails-plugin-gsp/src/test/groovy/org/grails/web/taglib/FormTagLibTests.groovy @@ -300,6 +300,51 @@ class FormTagLibTests extends Specification implements TagLibUnitTest\n' } + def testFormActionSubmitWithController() { + when: + String output = tagLib.formActionSubmit([controller:'con', id:'formElementId', value: 'Submit']) + + then: + output == '' + } + + def testFormActionSubmitWithControllerAndAction() { + when: + String output = tagLib.formActionSubmit([controller:'con', action: 'act', id:'formElementId', value: 'Submit']) + + then: + output == '' + } + + def testFormActionSubmitWithURLAndNoParams() { + when: + unRegisterRequestDataValueProcessor() + String output = tagLib.formActionSubmit(new TreeMap([url:[controller:'con', action:'action'], id:'formElementId', value: 'Submit'])) + + then: + output == '' + } + + def testFormActionSubmitWithAURLAndRequestDataValueProcessor() { + + when: + String output = tagLib.formActionSubmit(new TreeMap([url:[controller:'con', action:'action', params: [requestDataValueProcessorParamName: 'paramValue']], id:'formElementId', value: 'My Button'])) + + then: + output == '' + } + + def testFormActionSubmitWithAURLAndWithoutRequestDataValueProcessor() { + given: + unRegisterRequestDataValueProcessor() + + when: + String output = tagLib.formActionSubmit(new TreeMap([url:[controller:'con', action:'action', params: [requestDataValueProcessorParamName: 'paramValue']], id:'formElementId', value: 'My Button'])) + + then: + output == '' + } + def testActionSubmitWithoutAction() { when: diff --git a/src/main/docs/guide/tags/formsAndFields.adoc b/src/main/docs/guide/tags/formsAndFields.adoc index 55a47aa332..c87b3efe63 100644 --- a/src/main/docs/guide/tags/formsAndFields.adoc +++ b/src/main/docs/guide/tags/formsAndFields.adoc @@ -37,9 +37,9 @@ GSP also contains extended helper versions of the above tags such as xref:../ref ==== Multiple Submit Buttons -The age-old problem of dealing with multiple submit buttons is also handled elegantly with Grails using the xref:../ref/Tags/actionSubmit.adoc[actionSubmit] tag. It is just like a regular submit, but lets you specify an alternative action to submit to: +The age-old problem of dealing with multiple submit buttons is also handled elegantly with Grails using the xref:../ref/Tags/formActionSubmit.adoc[formActionSubmit] tag. It is just like a regular submit, but lets you specify an alternative controller & action to submit to: [source,xml] ---- - + ---- diff --git a/src/main/docs/ref/Tags/actionSubmit.adoc b/src/main/docs/ref/Tags/actionSubmit.adoc index b60392b910..d49c256c00 100644 --- a/src/main/docs/ref/Tags/actionSubmit.adoc +++ b/src/main/docs/ref/Tags/actionSubmit.adoc @@ -8,6 +8,8 @@ Generates a submit button that maps to a specific action, which lets you have multiple submit buttons in a single form. JavaScript event handlers can be added using the same parameter names as in HTML. +_Note: this tag is being replaced by the tag formActionSubmit_ + === Examples diff --git a/src/main/docs/ref/Tags/formActionSubmit.adoc b/src/main/docs/ref/Tags/formActionSubmit.adoc new file mode 100644 index 0000000000..21126e1ad6 --- /dev/null +++ b/src/main/docs/ref/Tags/formActionSubmit.adoc @@ -0,0 +1,59 @@ + +== formActionSubmit + + + +=== Purpose + + +Creates a submit button that submits to an `formaction` generated by the various link attributes. + + +=== Examples + + +[,xml] +---- + + + + + + + + + + + + + + + + + +---- + + +=== Description + + +Attributes + +* `action` (optional) - The name of the action to use in the formaction; if not specified the default action will be used +* `controller` (optional) - The name of the controller to use in the formaction; if not specified the current controller will be used +* `namespace` (optional) - the namespace of the controller to use in the formaction +* `plugin` (optional) - the name of the plugin which provides the controller +* `id` (optional) - The element id of the input element +* `fragment` (optional) - The link fragment (often called anchor tag) to use in the formaction +* `mapping` (optional) - The {grailsdocs}guide/theWebLayer.html#namedMappings[named URL mapping] to use to rewrite the formaction +* `params` (optional) - A Map of request parameters for the formaction +* `url` (optional) - A Map containing the action,controller,id etc for the for the formaction. +* `uri` (optional) - A string for a relative path in the running app +* `relativeUri` (optional) - Used to specify a uri relative to the current path for the formaction +* `absolute` (optional) - If `true` will prefix the formaction target address with the value of the `grails.serverURL` property from the application configuration, or http://localhost: if there is no setting in the config and not running in production. +* `base` (optional) - Sets the prefix to be added to the formaction target address, typically an absolute server URL. This overrides the behaviour of the `absolute` property if both are specified. +* `event` (optional) - The name of a Webflow event to trigger for the flow associated with the given `action`. Requires the Webflow plugin. +* `value` (required) - The caption of the button and name of action when not explicitly defined. + +When you use a normal submit button inside a form, it is the form itself that determines what URL the request is sent to, and therefore what action is executed. However, this tag overrides that behaviour and determines which action is executed by the specified attributes. This tag supports any controller & action.