json-editor / json-editor

JSON Schema Based Editor
MIT License
4.46k stars 660 forks source link

How to display a popup with dynamic values instead of Enum? #1363

Open eduo opened 1 year ago

eduo commented 1 year ago

I have a form where multiple addresses can be input. Each address requires at least one postal code (5 digit code) and one "registry office".

The "registry office" main data file is over 5 thousand rows, with three columns each: two digits (which match the first two digits of the postal code), then an office name and then an office ID.

I need to be able to populate the "registry office" popup with the subset of registry offices that apply for the specific postal code.

I tried using enums, but you have to destroy and rebuild the form each time. This becomes jarring but also makes the user lose their position in tabs.

I thought maybe I could create an empty popup menu and populate it via javascript, but it seems select menus require enums.

Is it possible to have a "string" field map to a select menu, so I can populate it via JavaScript? Default value would be a disabled "please enter a zip code" and the postal code field would be watched for changes to change the popup menu as necessary.

Or maybe I'm overthinking it and there's an obvious way to do it I'm just missing.

germanbisurgi commented 1 year ago

Hello @eduo, I don't quite understand. What is meant by popup? a select input?

schmunk42 commented 1 year ago

How about using autocomplete? https://github.com/json-editor/json-editor/blob/master/README_ADDON.md#autocomplete

eduo commented 1 year ago

Hello @eduo, I don't quite understand. What is meant by popup? a select input?

Sorry. Yes. English is not my native language and I sometimes mix the "colloquial" names with the proper ones.

I meant a popup menu, a select input. I was avoiding the whole "select" name for some reason I can't remember :)

How about using autocomplete? https://github.com/json-editor/json-editor/blob/master/README_ADDON.md#autocomplete

I thought about it (since I already use it for other things), but autocomplete usually requires the user to start typing and the possible values can be written in multiple ways (particularly in Spain, where there're four official languages) so depending on how you type it you might not see results, but a human would pick the right value from a select menu immediately.

I will be using autocomplete in the meantime, but it's not ideal.

Having a "string" field that maps to a dynamically built select menu (format:select, for example) I could build the menu according to existing data could solve it but I don't think there's a way to "format" a field to be a select when it's of type "string".

I might be able to just search for all string properties (text inputs) for this and change them to selects and set a watcher to modify them but before I open that can f worms I wanted to exhaust potentially better solutions.

eduo commented 1 year ago

How about using autocomplete? https://github.com/json-editor/json-editor/blob/master/README_ADDON.md#autocomplete

Quick question: I need autocomplete results to be prefiltered by the contents of a previous field (postal code). Is it possible to pass the schema path of the autocomplete input field, so the search function can look for the corresponding prefiltering field?

I may be wrong, but we're not passing over the element or any indicator of which field we're modifying so unless I'm missing something if I want to make the contents of auto-complete be dependant o sibling field it's currently not possible.

schmunk42 commented 1 year ago

but autocomplete usually requires the user to start typing

From autocomplete example

Just remove input.length check

    // Lookup using data from form
    "search_local": function search(jseditor_editor, input) {
      var ed = jseditor_editor.jsoneditor.getEditor('root.possibleFonts');
      if (!ed) {
        return [];
      }
      var data = ed.getValue();
      return data.filter(function(item) {
        return item.toLowerCase().startsWith(input.toLowerCase());
      });
    },

and you'll see example instantly:

Bildschirmfoto vom 2023-07-03 11-53-15

eduo commented 1 year ago

but autocomplete usually requires the user to start typing

Just remove input.length check

Thanks, I didn't explain myself well but it doesn't matter. I tried clarifying later: The menu is unwieldily large and autocomplete doesn't lend itself easily to large menus.

Unless I can prefilter the listing (based on a sibling field in the same form) I can't make it usable. Problem is we don't seem to pass the path to the schema the autocomplete is for which means I can't find for that specific row what pre-filter to use.

Presenting an autocomplete with a few items is acceptable. Presenting one with potentially 5 thousand is not.

schmunk42 commented 1 year ago

Bildschirmfoto vom 2023-07-03 14-47-47

You can use another field to filter, see quick and dirty example:

https://is.gd/nZ0Poj

PS: autocomplete filter needs to filter again by it's own input, above is just a test for a "pre-filter" from another field.

eduo commented 1 year ago

Unless I'm misunderstanding, I can't do this. The autocomplete is in an array, and a sibling field for the same row of that array is the one that is used as pre-filter.

Your suggestion (which I appreciate, but I had tried already) implies I have a path already for the sibling but the point is that the field is a sibling in the same array row. You can create new rows and the sibling would be dependant of each one.

Hence why I think it should be possible to send the path of the autocomplete field to the autocomplete functions.

I can't write an example from where I am right now, but maybe it's easy to explain with a sample (as soon as I can get to a computer I can try making an example):

Array of potential districts: [ ["03","District A"], ["03","District B"], ["12", "District C"], ["12","District D"] ]

Form: Addresses (Array object):

Row 0: Name: "Address One", PostalCode: "03005", District: (Autocomplete should suggest District A and B, prefilter would be need editor.getEditor('root.addresses.0.CP'))

Row 1: "Address Two", PostalCode: "28027", District: (Autocomplete should not suggest anything, prefilter would be need editor.getEditor('root.addresses.1.CP'))

Row 2: "Address Three", PostalCode: "12123", District: (Autocomplete should suggest Districts C and D, prefilter would need editor.getEditor('root.addresses.2.CP'))

schmunk42 commented 1 year ago

@eduo Yeah, a concrete example would be helpful, but I can't promise to find time to dig into a specific implementation.

I think overall it's not really a json-editor issue. Actually you should be able to access all values from the editor or an external source from within your autocomplete callbacks.

eduo commented 1 year ago

Actually you should be able to access all values from the editor or an external source from within your autocomplete callbacks.

I can access all of them. What I can't is access this specific one. I need to prefilter by the one that I'm editing and I can't tell which one it is.

I've put this on hold while I confirm I've found a bug with watchers when dependencies exist. I can't have both watchers and dependencies active, which is weird. But my schema is so complex I must rule out something else causing conflicts.

Thanks!