jsonforms
jsonforms copied to clipboard
Enhance enum support (defaults and unsetting)
Describe the bug
If having a enum property with values [foo, bar], the rendered drop-down control will offer values foo, bar or an empty string. I can understand that if a property is optional, using an empty value to signal "not a value" may be fine, but when marking the property as required it's still possible to choose an empty value, making for a very strange user experience.
To Reproduce Steps to reproduce the behavior:
Schema:
type: object
required: [mode]
properties:
mode:
type: string
enum: [foo, bar]
UI schema:
type: VerticalLayout
elements:
- type: Control
scope: "#/properties/mode"
Expected behavior
The enum should offer only foo and bar values, no empty value should be possible to pick since this will violate the schema.
Screenshots
Browser (please complete the following information):
- Browser: Chrome
- Version: 76.0.3809.132
Used Setup (please complete the following information):
Standard seed test app
Additional context
Thanks for this feature request. Handling enums requires some care. There are multiple things to think about.
When forcing the user to choose one of the enums we need to think about the case where it is not yet set. I would prefer to not choose one by default for the user, as this would modify the data object simply by rendering the form. Therefore we would need to support the empty initial state with a forced selection afterwards.
In general validation errors have different meanings/consequences per application. There are use cases where validation errors might be ignored, for example when saving a WIP state of a form to continue working on it later. In this case I want to be able to unset an enum I'm not yet sure about.
Ideally we would support both use cases (forced and non-forced selection) via an option. Until this option is available we should keep the current behavior as it is the more flexible one.
Thanks! Those are some valid concerns, and I agree. If there's no default value set, how to handle that opens up questions. However, I'd claim that a very important and common case is the combination "enum + is required + has default", such as
type: object
required: [mode]
properties:
mode:
type: string
enum: [foo, bar]
default: bar
If the schema fulfills these constraints, removing the empty option from the control would be very useful I think.
The problem with the default annotation in JSON Schema is that it has no properly defined semantics. Strictly speaking it is not even necessary to be valid, for example default: whatever would be perfectly fine JSON Schema in your code snippet, although not recommended ;)
Coming back to your example: The empty option could still be useful here by simply renaming it to "Default". Maybe even more useful would be to add "(default)" behind the default option and then removing the empty option.
In general I think we should drive the behavior via options as there will always be some use case where someone would like a different behavior.
Just to clarify: The suggestions are great and I think they would be a good default behavior. So if you or anyone else would like to contribute them (ideally with options support) we would definitely appreciate that ;)
I'd love to contribute if I find the time. Thanks for the analysis so far!
any update on this?
No update.
If you (or someone else) would like to contribute I think the following behavior would be most flexible:
- When the property is not set always render the "empty" option
- When the property is set, only offer the "empty" option when it's part of the enum
If someone would like a default value used they can use the existing default support.
- When the property is set, only offer the "empty" option when it's part of the enum
One case where I would require an empty option even if the property is currently set to some value is when clearing the properties of an object that is itself an optional property. If I can't clear the enum then I can't remove all of the properties of the object and remove it. An alternative would be to provide some UI to clear/remove the entire object.