jsonform / jsonform

Build forms from JSON Schema. Easily template-able. Compatible with Bootstrap 3 out of the box.
https://jsonform.github.io/jsonform/playground/index.html
MIT License
2.72k stars 553 forks source link

Select input does not support selecting multiple options #421

Closed rkroll closed 1 year ago

rkroll commented 1 year ago

We have need for a select list which supports selecting multiple items. This is typically managed via the "multiple" attribute on a select list. I attempted to modify the underlying select template to test if it was possible by adding the multiple attribute to the select template if it is present in the schema like so: <select name="<%= node.name %>" id="<%= id %>" <%= node.formElement.multiple ? "multiple" + " " : "" %>'. This allowed support for selecting multiple items in the list, but when the form is submitted, only the last item selected is returned.

sdetweil commented 1 year ago

yeh, that's a problem of jQuery on input returning only one value for the select list , even if multiple is enabled.

jsonform would have to find all the select w multiple(special classname), and get the values (.val()) for each and add it to the returned form inputs

something like this https://www.techiedelight.com/get-selected-values-multi-select-drop-down-list-jquery/

rkroll commented 1 year ago

Couldn't you inspect metadata on the schema/form element to identify those items that needed alternate processing? Can you help me to understand why you would need to look for a special class name?

sdetweil commented 1 year ago

well, we need to get the data from the form

the code does

  var formArray = $(':input', this.el).serializeArray();]   // line 2572

which gets all the non-empty input fields with names and it got the select/last checked

and then it gets all the unchecked checkboxes

formArray = formArray.concat(     // line 2576

now we need to find all the places we COULD get more data so select with multiple attribute set...

and we need to resolve the one field returned vs all/only fields

but that gets us the data, not where it goes in the schema..

there is a bunch of code following this that tries to locate the place in the schema.. I haven't gone thru that myself yet. but if we had the select element classname, we could match. and we HAVE the element to get the values..

sdetweil commented 1 year ago

in the short term, you could try the multiple checkboxes approach I submitted as a PR

https://github.com/jsonform/jsonform/pull/419

sdetweil commented 1 year ago

well, after a little investigation.. when the submit is fired we DO get all the values. so, its the code loading them into the result..

of course it doesn't see 'multiple' yet ... so uses the last one in the list

rkroll commented 1 year ago

Thanks for the pointer! I did some digging and was able to find what you mentioned, that the values are all coming back, but as individual objects in the array. Since the select is defined as a "string", whichever item is last in wins and is what is returned. I spent some time debugging and was able to add the following to get all the items to process:

var formEl = $("[name='" + name + "']")[0];
if(formEl && formEl.tagName == 'SELECT' && formEl.multiple == true) {
        cval = jsonform.util.getObjKey(values, name) || [];
        enumIndex = eltSchema['enum'].indexOf(formArray[i].value);
        cval.push(eltSchema['enum'][enumIndex]);
        jsonform.util.setObjKey(values, name, cval);
        continue;
  }

Once these process, the issue becomes that the elements fail validation as the select is defined as a string and not an array. It feels like there should be a "select" form type similar to checkboxes and radios. If I disable validation, I am able to retrieve the results as expected. I am going to keep digging, but would welcome feedback on how to transition a select field to support arrays so that validation could be enabled.

It may make sense as part of a larger refactoring to iterate through the identified form elements and not the serialized form so that decisions and processing could be done on an input by input basis. Just a thought.

sdetweil commented 1 year ago

there is a special flag for arrays of checkboxes

_jsonform_checkboxes_as_array

but the select submit data doesnt work there..

will look a little more. I had validation turned off to be able pass a file object back to the form user to handle uploaded file

sdetweil commented 1 year ago

your code above, yeh, see what happens after input.

each data type is checked, cause the 'form' returned string, work has to be done for number, integer and boolean for sure. hate to dup code...

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.