rjsf-team / react-jsonschema-form

A React component for building Web forms from JSON Schema.

Home Page:https://rjsf-team.github.io/react-jsonschema-form/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

  1. 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).
  2. 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?