Problem/Motivation
The module currently lacks (a widget and) standardized mechanisms for Dynamic Options and Dependent Fields.
- Widget: Make it available to the masses. :)
- Static Options: Users are currently limited to hardcoding
enumvalues in the schema or using simple Taxonomy terms without filtering capabilities. - No Interdependency: There is no built-in way to filter one field's options based on the value of another (e.g., "Car Model" depends on "Brand"), which is a critical requirement for complex forms.
Proposed resolution
Implement a modular "Option Source" plugin system and refactor the main widget structure.
- Option Source Plugins: Introduce a plugin manager to allow options to be fetched from various backends.
- Views Source: Fetch options from any Drupal View, enabling advanced filtering and display logic.
- Taxonomy Source: (Enhanced) Fetch terms from a vocabulary with robust validation.
- Dependent Fields: Implement lightweight Client-side JSON API triggers to reload dependent Options.
- Frontend: Uses
fetch()to get filtered options from a custom controller when a trigger field changes. - Backend: Dedicated
JsonOptionsControllerthat returns a simple JSON array (avoiding full form rebuilds).
- Frontend: Uses
- Widget Split: Create two distinct plugins:
- JSON Schema Form (Static): Simple text area for raw schema input.
- JSON Schema Form (From Reference): Dynamic AJAX-driven configuration to select "Schema Entity Reference" and "Schema Source Field".
Configuration Reference
This patch introduces advanced configuration via ui:options for dynamic sources.
1. Views-Based Options (Dynamic)
You can now populate a dropdown using a View. The source object now accepts a view parameter (format: view_id:display_id).
"product_type": { "type": "string", "ui:options": { "widget": "tagify", "source": { "plugin": "views", "config": { "view": "my_products_view:entity_reference_1" } } } }
2. Dependent Fields (Filtering)
To filter options based on another field's value, add the array arguments key to the source config. This allows to watch a specified field name or use the @ prefix for a config value and pass their values as Contextual Filters to the View.
"brand": { "type": "string", "title": "Brand" }, "model": { "type": "string", "title": "Model Name/Number", "ui:options": { "widget": "tagify", "allowCreate": true, "placeholder": "Select or type new...", "source": { "plugin": "taxonomy", "config": { "vocabulary": "car_models", "view": "my_view:car_models_filtered", "arguments": [ "@vocabulary", // Resolves to "car_models" from config "brand" // Resolves to the value of the "brand" field ] } }, } },
Remaining tasks
- [ ] Fix failing tests (Note: Testing environment currently unavailable).
- [ ] Rewrite documentation.
- [ ] Final functional testing of complex View arguments.
User interface changes
- Widget Selection: "Manage Form Display" now offers two distinct widgets: Static and From Reference.
- Configuration Form: The "From Reference" widget features a responsive AJAX form where selecting a Reference field dynamically loads available Source fields (Text or JSON) from the target entity.
- Frontend: Forms now support real-time updates for dependent fields using a client-side JSON API. Changing a "Trigger" field (e.g., Brand) fetches new options for the "Target" field (e.g., Model) without reloading the page.
- Almost forgot... tested and working with Inline Entity Form too :)
API changes
- New Plugin Manager:
JsonFormOptionSourceManagerto handle option sources (views,taxonomy). - New Base Class:
JsonSchemaWidgetBaseabstracts common logic (libraries, value handling) for both Static and Reference widgets. - Added:
json_form_widget.get_optionsroute and controller for AJAX option fetching.
Data model changes
None. The schema storage format remains the same, only the widget configuration and option fetching logic have changed.
| Comment | File | Size | Author |
|---|---|---|---|
| #12 | json_form_widget-3565788-12.patch | 210.08 KB | viappidu |
| #12 | interdiff-7-12.txt | 129.04 KB | viappidu |
| #7 | json_form_widget-3565788-7.patch | 131.51 KB | viappidu |
| #7 | interdiff-6-7.txt | 21.77 KB | viappidu |
Issue fork json_form_widget-3565788
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
viappidu commentedPatch for composer :)
Closes (eventually):
#3563296: Undefined array key warnings in ValueHandler::flattenValues() when schema has new properties
#3564474: Drupal 11.3: Add void return type to UploadOrLink::submit() for PHP compatibility
#3565343: Refactor Object and Array Nesting Logic and support boolean and number (float) specs
#3565448: Drupal 11 and CMS Compatibility: Replace Select2 and Select_or_Other with Tagify
Comment #4
viappidu commentedComment #5
viappidu commentedComment #6
viappidu commentedfixed an regression introduc with last commit, and some code cleanup
Comment #7
viappidu commentedRealized I had most of the work done in different modules. Ready to be tested thoroughly :)
Remaining tasks
Comment #8
viappidu commentedComment #9
dafederHi @viappidu, I appreciate your ambition here but I think this is too much change to review or safely merge in a single MR. The scope has really expanded here and it introduces way too many things. I'm going to focus on reviewing the two earlier MRs that are included in this, and I'd encourage you to work on splitting the work here into more focused issues/MRs.
The following all deserve their own issues IMO:
- Enhanced Taxonomy source plugin
- Views source plugin
- Dependent fields feature
- Static JSON Schema form - this is next on my own list of things to do, I might "steal" some of your work from this MR (with credit of course!) if I get to it before you can make a focused MR
- JSON Schema references - I don't exactly understand the concept here, but it seems big enough to warrant its own issue/MR. I don't think it's dependent on any of the other work here?
Comment #10
dafederComment #11
dafeder3565788 test
Comment #12
viappidu commented@dafeder, I don't really see the point of splitting the issue in all the sub issues you created. Or at least I do not have the conditions to do so.
- Replace select2 (critical) I completely removed select2 from my systems. NOT going to reinstall it.
- As I explained before working on the (major) array nesting issue solution I needed to implement the number/boolean (critical) changes.
- the external reference (taxonomy/view), does not make sense (my opinion) to keep them separated
As per your question. at #9, I will try to simplify how I approached the 2 widgets
the static one: the same schema is valid/applied to all entities making use of the schema
the reference one: the schema is coming from an "external source" eg. a taxonomy vocabulary where each term has a different schema. when the entity reference changes the form is loaded from it's source field and recreated. This gives the option to have unlimited schemas availability
Your other question in #3565448-13: Drupal 11 and CMS Compatibility: Replace Select2 and Select_or_Other with Tagify regarding the creation of a "new item" in a list, the entity is saved with the new value but the enum list is not updated, by choice, that is why I introduced the use of taaxonomies.
Honestly I think this module has great potential and for the moment very little use. I do not see the point in delaying major issues at this stage.
(added tests)
Comment #13
dafederI'll respond to the other points in a bit but regarding:
You're right, there's a bit of code involved in my use-case that is specific to DKAN and its implementation of the option source plugin. I think that using taxonomy for this is the better option but I'll need to think a bit on how to reconcile with some existing implementations.
Comment #14
dafederAnyway @viappidu thanks again for your enthusiasm for this module. I think you'll find in most Drupal modules or open source projects in general, it's vital to keep both MRs and issue threads focused and tightly scoped, and you'll find very few examples of multi-issue MRs like this begin accepted, even if the work on each issue is of high quality on its own (as seems to be the case here). Even just on the side of issue threads, you can see discussion is already getting difficult, when the subject of the thread moves from one focused on the specifics of moving to tagify to "all the things @viappidu wants to see changed in this module".
Finally, I'd ask you to be sensitive to the fact that the low adoption statistics for this module are a bit misleading. JSON Form Widget was only recently released as a standalone module on Drupal.org but has been in production for years on several government websites as part of the DKAN package. We need to balance our desire to make it useful for people beyond the DKAN user base with our responsibilities to existing users. I understand that contributing to MRs is time-consuming; if you're not willing or able to split this one up our team will likely incorporate the relevant code from your MR (with full credit of course) into MRs that meet our requirements and on our own timeline.
I'll keep this open until we have specific issues to represent all its pieces. Thanks for your understanding.
Comment #15
viappidu commented@dafeder ,lol, "all the things @viappidu wants to see changed in this module", lol.
Don't get me wrong, I was in a rush commenting back so I might have been lost in translation. I do agree with you, that is why I did open the other issues/MR though I currently have very little time to spare for reviewing each one separately.
And I do understand that your user base is government via civicactions (kudos) hence the problematics of aligning any change here with the slow cogs there. I am Italian, you honestly cannot have a fraction of an idea of how hard it would be here... So let me correct your statement with: "All the things @viappidu WISH to see changed in this module".
Glad if you have a team that can manage the multiple @viappidu wishes :)
PS If you are looking to hire I am available :)
Comment #16
dafederHeh well we do have a great team but this module is unfortunately not our top priority most of the time, so I don't want to give the wrong impression about our capacity. And glad to hear we're on the same page! It sounds like you did get the module to the place you need it with this fork so hopefully that can tide you over till we're able to incorporate some of this into an official release.
Comment #17
dafederI have started trying to isolate the static widget in the branch for #3572908: Include default working widget, hope to get that in in not too long.