Rewrite: form submit action
Closed this issue ยท 10 comments
Will need a custom Thymeleaf tag that triggers on a form submit.
- Actual form submits have to be cancelled
- The form must become available as parameter to the controller method as a Map<String, Object> or map onto a POJO.
- (Optional) A common pattern is to disable a button after button press until the message is resolved, to prevent double-clicking to fire an event twice. Perhaps this should be an option with this default on?
- (Optional) Validation of forms is a very common pattern. Is there a way we can make this easier in Medusa?
Implemented the basics of form tag: https://medusa-showcase.herokuapp.com/detail/form-submit
Would still need to think about validation/button disabling
For Validation, consider integration with https://github.com/making/yavi which seems to have traction on github.
Validation should likely work on both JS side and backend. The validation messages should be able to deal with internationalization/maybe just different strings.
One thing I noticed: when adding Session
in the submit method, it needs to be the last argument of that method.
Note: for other calls like m:click
the position of the session argument can be first or last...
ref: #304
Failed to use multi-select in form ref: sample in medusa-ui path: '/multi-select'
Failed to use multi-select in form ref: sample in medusa-ui path: '/multi-select'
Issue above is fixed. ๐
But handling multi-select in the controller is still cumbersome:
null
when not presentObject
when a single option selectedObject[]
when multiple options selected
public List<Attribute> options( Map<String, Object> form) {
...
// handle multi-select
// value is null when not present
if (null != form && form.containsKey("options")) {
Object options= form.get("selected");
if (options instanceof String) {
// handle single select
} else {
for (Object option: (Object[]) options) {
// handle multiple selections
... option.toString();
}
}
}
....
}
Any easier now? I've made it resolve to a dynamic List instead of an Object[] now.
So you should be able to do something like:
Map<String, List<String>> form
if you only expect multi lists to show up in the form.
I'm not really sure how I could make a map that does both single values and multi values easier otherwise. That's kind of what the POJO mapping is for.
The problem is not Object
versus String
, but Object
versus Object[]
(or String
versus String[]
)
The multi-select has no problems when multiple options are selected, but occurs when only a single option is selected.
One would expect an Array with one Object, but instead, the selected option is an Object.
When using a map, you can use the workaround like in the above example.
When using a POJO there is no workaround, you get an error:
MismatchedInputException: Cannot construct instance of
java.util.ArrayList
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value
Ref: multi-select in medusa-ui
Sample application
Applied JS fix as discussed, maybe this will solve the problem?
Select multiple works fine now! ๐
Included detection for input fields with an identical name #326
These too must send data as an Array.
For now only look at checkboxes with identical names