react-jsonschema-form
react-jsonschema-form copied to clipboard
Nested oneOf/anyOf not rendered
Prerequisites
- [x] I have searched the existing issues
- [x] I understand that providing a SSCCE example is tremendously useful to the maintainers.
- [x] I have read the documentation
- [x] Ideally, I'm providing a sample JSFiddle, Codesandbox.io or preferably a shared playground link demonstrating the issue.
What theme are you using?
antd
Version
5.x
Current Behavior
This is a bit of a mix of a bug report and a feature request. A bug report in that a nested oneOf/anyOf don't work, and a feature request to make them work in a certain way.
The issue is that currently RJSF does not handle nested oneOf/anyOf lists. When doing so, the nested list fails to render in any way. So making this functionality work at all is the bug report.
Expected Behavior
The simple way of doing it would be to render the first drop down, and then when the option for the nested list is selected, to render another drop down.
The feature request is to instead allow merging/concatenating nested lists. For example if you have a oneOf inside a oneOf, to allow merging of all the options as if they were a single oneOf list.
Steps To Reproduce
{
"type": "object",
"properties": {
"myprop": {
"oneOf": [
{
"title": "none",
"type": "object"
},
{
"$ref": "#/$defs/some"
},
{
"$ref": "#/$defs/mylist"
}
]
}
},
"$defs": {
"some": {
"title": "some",
"const": "some"
},
"mylist": {
"oneOf": [
{
"const": "foo"
},
{
"const": "bar"
}
]
}
}
}
In the above, if you select "Option 3", there is no drop-down presented to select foo or bar. However the following are all valid against the schema:
{"myprop": {}}
{"myprop": "some"}
{"myprop": "foo"}
{"myprop": "bar"}
Environment
- OS:
- Node:
- npm:
Anything else?
As a side note, one of the main reasons for this was I wanted to prevent RJSF from automatically selecting the first item in the oneOf list (for myprop) and rendering it. And all the options for the list are defined in $defs. "none" isn't meant to be a valid option in the list, and is only applicable to the property, so I didn't want to put it in the list itself, and instead keep it on the property definition. Thus the property with a oneOf containing none, and then a reference to the real list.
However that said, it is not my only use case for this functionality. I also have other lists, where sometimes I want to only allow a subset of options, and other times I want to allow all options. For example think of a country selector. You might have a list in $defs for all the countries in Europe, and another list for North America. Sometimes you only want to allow selecting the European countries, but sometimes you want to allow selecting all countries. So the solution would be to define an "all" list, which contains references to each of the continental lists.
@phemmer You're missing "type" properties, so RJSF has no idea how to render these nested oneOf fields. If you annotate your subschemas with "type", then the fields properly render.
Here's a fixed playground.
Is this closer to what you had in mind?
@phemmer A slight modification to the schema that @nickgros provided will allow the none choice to not have an input field. And when you select it an submit you are given an error
Here the alternate playground
That explanation doesn't seem to hold up. Few reasons:
- The first
oneOfdoesn't have a type either, yet it renders fine. - What if you want your items to have different types?
- I didn't notice at first, but the problem actually seems to be restricted to having options of the same type. For example this works fine, while this doesn't. This doesn't make sense to me. Why would the first two items work when the third is present, but then when you remove the third, those first two which were working fine no longer do?
That explanation doesn't seem to hold up. Few reasons:
- The first
oneOfdoesn't have a type either, yet it renders fine.- What if you want your items to have different types?
- I didn't notice at first, but the problem actually seems to be restricted to having options of the same type. For example this works fine, while this doesn't. This doesn't make sense to me. Why would the first two items work when the third is present, but then when you remove the third, those first two which were working fine no longer do?
@phemmer If you add type to the second example like this It works. So adding the type property is important and is consistent with what @nickgros mentioned.
Barring an example that shows a real bug, I expect this will be closed soon
Yes, I understood that if you put a type outside of the oneOf definition it works. That's exactly what all three of the points I mentioned are about.
Ok, so basically to summarize, today RJSF can handle the schema (playground)
{ "const": "someString" }
but it cannot handle the schema (playground)
{
"oneOf": [
{
"const": "someString"
}
]
}
A workaround exists where if you provide the type, it works (playground)
{
"type": "string",
"oneOf": [
{
"const": "someString"
}
]
}
The oneOf case without the type is technically a valid JSON schema, so we could probably support it, but since a workaround exists, this is probably pretty low on our priority list. We would be happy to review and merge a PR from @phemmer or any other community member interested in investigating and providing a fix. Thanks.