Support dynamic presence of properties
mfulton26 opened this issue · comments
Prerequisites
- I have read the documentation;
- In the case of a bug report, I understand that providing a SSCCE example is tremendously useful to the maintainers.
Description
I would like a way to define a schema where some properties should be present if and only if another property has some value(s) and not present otherwise.
Steps to Reproduce
- Define a JSON Schema defining properties that sometimes should be present and sometimes should not be (e.g. using dependencies with oneOf, not, and required).
- Render the schema on a react-jsonschema-form and attempt and try it out.
https://jsfiddle.net/07fm4n1b/
Expected behavior
react-jsonschema-form reacts to the "oneOf" array in the "dependencies" and intelligently displays only the relevant properties and when values change and some properties become relevant or no longer relevant they are shown or hidden appropriately.
Actual behavior
All of the properties are displayed requiring the user to understand which properties they need to fill and which ones they must leave blank.
Version
0.44.0
That seems very complicated to implement properly and efficiently, no mention of maintainability. We usually recommend to process the schema when onChange
is triggered to contextually augment the initial one with new definitions. This has worked great for us so far, so I'm having a hard time justifying spending a possibly huge amount of time implementing what you suggest.
I'm closing for now, though if you're willing to work on this, feel free to reopen.
I've recently implemented something like this using a custom field template. I've added additional entries to the uiSchema
:
{
"ConditionallyEnabledfield": {
"ui:options": {
"enabledIf": "SomeOtherField",
"hasValue": "yes"
}
}
and then check them in the custom field rendering:
export class CustomFieldTemplate extends React.PureComponent {
render() {
const {id, label, displayLabel, rawHelp, description, rawErrors, children, schema, uiSchema} = this.props
let childrenProps = children.props
let disabled = false
if(schema && schema.type === "object") {
const { formData, uiSchema } = children.props
childrenProps = {
...childrenProps,
uiSchema: Object.keys(uiSchema).reduce((newUiSchema, key) => {
const uiOptions = (uiSchema[key] || {})['ui:options']
if(uiOptions
&& uiOptions.enabledIf
&& uiOptions.hasValue
&& formData[uiOptions.enabledIf] !== uiOptions.hasValue) {
newUiSchema[key] = {
...uiSchema[key],
'ui:options': {
...uiOptions,
disabled: true,
}
}
} else {
newUiSchema[key] = uiSchema[key]
}
return newUiSchema
}, {})
}
} else {
if(uiSchema && uiSchema['ui:options'] && uiSchema['ui:options'].disabled) {
disabled = true
childrenProps = {
...childrenProps,
disabled,
}
}
}
return (
<Form.Field disabled={disabled} >
...
{{...children, props: childrenProps}}
</Form.Field>
)
}
}
I apologize for the code, it really looks ugly so any improvements are more than welcome.
This also looks related to #430, which is also closed until someone wants to implement it.
@misto Where is the Form.Field
component defined? I'm not seeing it in this package. Is it your own?