medusa-ui/medusa

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 present
  • Object when a single option selected
  • Object[] 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