Skip to content
This repository was archived by the owner on Mar 10, 2025. It is now read-only.

Add g:formActionSubmit for client submission to multiple form urls #551

Closed
jdaugherty opened this issue Nov 29, 2024 · 7 comments
Closed

Comments

@jdaugherty
Copy link
Contributor

jdaugherty commented Nov 29, 2024

As of HTML5, the input attribute formaction is the accepted way to submit to different URLs for a form on the client side with no javascript. This attribute is widely supported across all browsers:

image

I'd like to propose we adopt a tag formActionSubmit instead of implementing a server side solution via the tag actionSubmit (it uses a parameter with the format action_${actionName} to submit to different actions for the same controller).

@jdaugherty jdaugherty changed the title Support for formaction Change g:actionSubmit - use input attribute formaction instead of property name Nov 29, 2024
@jdaugherty
Copy link
Contributor Author

This change would have the added benefit of not relying on custom url mappings per the documentation here: https://gsp.grails.org/latest/ref/Tags/actionSubmit.html or default actions.

jdaugherty added a commit to jdaugherty/grails-gsp that referenced this issue Nov 29, 2024
jdaugherty added a commit to jdaugherty/grails-gsp that referenced this issue Nov 29, 2024
jdaugherty added a commit to jdaugherty/grails-gsp that referenced this issue Nov 29, 2024
@codeconsole
Copy link
Contributor

@jdaugherty perhaps you could provide more detail in this ticket description on how existing behavior works and how it will be changed. Specifically, how existing html is generated by the tag. I don't use this tag. It currently works by generating inline javascript?

@jdaugherty
Copy link
Contributor Author

jdaugherty commented Nov 29, 2024

Prior to HTML5, an HTML form without any JavaScript could only submit to the URL specified in it's action attribute. Since it's useful to have a form submit to multiple actions depending on the button clicked, the actionSubmit tag was implemented so that the form action could have one URL and depending on a submitted parameter, Grails would call the desired action.

This allows for submitting multiple actions depending on the button clicked via server side code. It's implemented server side via DefaultUrlMappingInfo#checkDispatchAction in grails/grails-core. The button clicked will set a parameter with the prefix _action_ so the DefaultUrlMappingInfo knows to return a different action. This did not allow for calling another controller, only actions in the same controller as the form.

Given this example gsp template:

 <g:form name="testForm" controller="begin" action="update">
      <g:submitButton name="update" value="Call the update action" />
      <g:actionSubmit action="testAction" value="Call the other Test Action"/>
 </g:form>

This will generate the following HTML code:

 <form action="/begin/update" method="post" name="testForm" id="testForm" >
      <input type="submit" name="update" value="Call the update action" id="update" />
      <input type="submit" name="_action_testAction" value="Call the other Test Action" />
 </form>

When the user clicks on the button "Call the update action", the form will submit to /begin/update and on the server side the begin controller's action update will be called.

When the user clicks on the button "Call the other Test Action", the form will be submitted to /begin/update and the server will see the parameter _action_testAction. It will parse out the action of testAction and invoke that action instead of the update action on the begin controller.

Now that HTML5 has a valid way to invoke different URLs for a form, it makes sense to add a tag that supports the client side mechanism. I propose we deprecate the tag actionSubmit and if no major objections remove it in a future major release of Grails (post 7.0). It's possible there are implementations that rely on the _action_ prefix behavior. Deprecation would allow us to identify these cases as people update to later Grails versions and then decide if the legacy server side behavior should be maintained.

@jdaugherty jdaugherty changed the title Change g:actionSubmit - use input attribute formaction instead of property name Add g:formActionSubmit for client submission to multiple form urls Nov 29, 2024
@jdaugherty
Copy link
Contributor Author

An example project of the existing behavior is here: https://github.com/jdaugherty/grails-dual-action-submit-example

You can open the url http://localhost:8080/begin after starting this project to see this behavior.

@jdaugherty
Copy link
Contributor Author

jdaugherty commented Nov 29, 2024

For this proposal, given this code:

 <g:form name="testForm" controller="begin" action="update">
      <g:submitButton name="update" value="Call the update action" />
      <g:formActionSubmit name="otherAction" action="testAction" value="Call the other Test Action"/>
 </g:form>

It would generate this html:

 <form action="/begin/update" method="post" name="testForm" id="testForm" >
      <input type="submit" name="update" value="Call the update action" id="update" />
      <input type="submit" formaction="/begin/testAction" name="otherAction" value="Call the other Test Action" />
 </form>

Clicking Call the update action would submit to /begin/update, clicking Call the other Test Action would submit to /begin/testAction

@codeconsole
Copy link
Contributor

Ok, but won't you need a PR in grails-core deprecating the Url Mapping functionality?

@jdaugherty
Copy link
Contributor Author

@codeconsole apache/grails-core#13905 will mark the grails-core code deprecated

jdaugherty added a commit to jdaugherty/grails-gsp that referenced this issue Dec 1, 2024
jdaugherty added a commit to jdaugherty/grails-gsp that referenced this issue Dec 1, 2024
@jdaugherty jdaugherty moved this to Done in Grails 7 Dec 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Status: Done
Development

No branches or pull requests

2 participants