RXNT/react-jsonschema-form-conditionals

Remove "hidden" elements of schema from form data

donalmurtagh opened this issue · 2 comments

Given this schema

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "nameHider": {
      "type": "boolean"
    }
  },
  "required": ["name", "nameHider"]
} 

And the following rule which hides the name field if nameHider is true

  const rules = [{
    conditions: {
      nameHider: {is: true}
    },
    event: {
      type: "remove",
      params: {
        field: "name"
      }
    }
  }];

If the following actions are performed

  1. Set the name field to "Bob"
  2. Set the nameHider field to true

I would expect the form data to be:

{"nameHider": true}

But instead it is:

{"nameHider": true, "name": "Bob"}

I guess I could implement this as a custom action, but IMO this ought to be performed by the remove action.

@donalmurtagh remove only changes the schema and uiSchema, it does not change formData, so that in case condition change again user would not have to input something he already specified before.

Custom action is the right way to go here.

I implemented this as a custom action

import remove from "react-jsonschema-form-conditionals/lib/actions/remove"
import ObjectUtils from "../ObjectUtils"
import {validateFields} from "react-jsonschema-form-conditionals/lib/actions/validateAction"
import PropTypes from "prop-types"

/**
 * This adds a custom "removeAll" action to react-jsonschema-form-conditionals.
 * The difference between "remove" and "removeAll" is that the former removes hidden conditional fields from the schema,
 * whereas the latter also deletes their values them from the model.
 */
function removeAll (params, schema, uiSchema, formData) {
  remove(...arguments);
  ObjectUtils.deletePropertyPath(formData, params.field);
}

removeAll.propTypes = {
  field: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.arrayOf(PropTypes.string),
  ]).isRequired,
};

removeAll.validate = validateFields("removeAll", function ({field}) {
  return field;
});

export default {
  removeAll: removeAll
}