react-jsonschema-form icon indicating copy to clipboard operation
react-jsonschema-form copied to clipboard

oneOf/anyOf schema can't enter in data with omitExtraData and liveOmit

Open FunJim opened this issue 5 years ago • 5 comments

Prerequisites

Description

When setting omitExtraData and liveOmit prop to true, form field can't be filled in with data.

Steps to Reproduce

  1. Go to rjsf playground. The oneOf schema is provided by the playground
  2. Notice that Omit extra data and Live omit are set to true.
  3. Try to fill in the form field and nothing can be entered in.
  4. Same thing if you choose anyOf schema.

Expected behavior

Data can be filled in when using oneOf/anyOf schema with omitExtraData and liveOmit.

Version

Current rjsf playground https://rjsf-team.github.io/react-jsonschema-form/

FunJim avatar Mar 03 '20 14:03 FunJim

Looks like the problem is in the toPathSchema method, where there is no logic for anyOf/oneOf cases. Try this patch - it works for me:

diff --git a/node_modules/@rjsf/core/dist/cjs/utils.js b/node_modules/@rjsf/core/dist/cjs/utils.js
index 138e5d8..196f7a6 100644
--- a/node_modules/@rjsf/core/dist/cjs/utils.js
+++ b/node_modules/@rjsf/core/dist/cjs/utils.js
@@ -1141,6 +1141,14 @@ function toPathSchema(schema) {
       // array item has just been added, but not populated with data yet
       (formData || {})[property]);
     }
+  } else if (Array.isArray(schema.anyOf)) {
+    schema.anyOf.forEach((_schema) => {
+      Object.assign(pathSchema, toPathSchema(_schema, name, rootSchema, formData));
+    });
+  } else if (Array.isArray(schema.oneOf)) {
+    schema.oneOf.forEach((_schema) => {
+      Object.assign(pathSchema, toPathSchema(_schema, name, rootSchema, formData));
+    });
   }
 
   return pathSchema;

AlimovSV avatar Mar 13 '22 09:03 AlimovSV

@epicfaace
Hi, is there a fix for this issue?

bysph avatar Jun 08 '22 08:06 bysph

bump, any known workaround?

ksbrar avatar Jun 08 '22 15:06 ksbrar

@AlimovSV maybe you can raise this in a PR for approval and merge?

benjdlambert avatar Aug 10 '22 11:08 benjdlambert

An additional example of the wrong behavior liveOmit/omitExtraData. When array field identifier contains .:

  • Go to rjsf playground.
  • Notice that Omit extra data and Live omit are set to true.
  • Try to fill in the form field and nothing can be entered in.

Code to reproduce the issue:

const { default: Form, utils } = require('@rjsf/core');

const schema = {
  type: 'object',
  properties: {
    'a.b': {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          name: {
            type: 'string',
          },
        },
      },
      minItems: 1,
    },
  },
};

const form = new Form({ schema, uiSchema: {} });

const formData = { 'a.b': [{ name: '123' }] };

const retrievedSchema = utils.retrieveSchema(schema, schema, formData);

const pathSchema = utils.toPathSchema(retrievedSchema, '', schema, formData);

console.log('Path Schema', pathSchema);

const fieldNames = form.getFieldNames(pathSchema, formData);

console.log('Field Names', fieldNames);

const newFormData = form.getUsedFormData(formData, fieldNames);

console.log('New Form Data', newFormData);

Result

Path Schema {
  '$name': '',
  'a.b': { '0': { '$name': 'a.b.0', name: [Object] }, '$name': 'a.b' }
}
Field Names [ 'a.b.0', 'a.b.0.name' ]
New Form Data {}

Conclusion

As we can see, the Field Names definitely wrong. So I think the problem is in getFieldNames function, which returns joined identifiers instead of an array sequence, because form.getUsedFormData(formData, [['a.b', 0, 'name']]) returns correct data: { 'a.b': [ { name: '123' } ] }

AlimovSV avatar Aug 25 '22 06:08 AlimovSV

Looks like v5 has fixed the previous example but I found yet another one: playground. In this example I can't check the "c" checkbox until liveOmit is true

UPD: Found the solution

AlimovSV avatar Mar 02 '23 07:03 AlimovSV

Looks like v5 has fixed the previous example but I found yet another one: playground. In this example I can't check the "c" checkbox until liveOmit is true

UPD: Found the solution

Can we close this then?

heath-freenome avatar Mar 03 '23 16:03 heath-freenome

The mentioned solution doesn't work properly too. If you check the schema you will see a default: false for the "c" prop. But when you check the "b" prop, the "c" prop stays undefined.

AlimovSV avatar Mar 03 '23 16:03 AlimovSV

The mentioned solution doesn't work properly too. If you check the schema you will see a default: false for the "c" prop. But when you check the "b" prop, the "c" prop stays undefined.

Are you wanting the value to be entirely removed? Isn't undefined considered no value? i.e.

const object = {};
const object1 = { c: undefined };

console.log(object.c) => undefined
console.log(object1.c) => undefined

heath-freenome avatar Mar 03 '23 16:03 heath-freenome

Schema UI Data

As you can see, the schema has "c".default = false, UI renders the "c" checkbox, but data doesn't contain any value for "c"

I guess that this issue is related to the liveOmit/omitExtraData logic. So I expected to see a data:

{
  "a": true,
  "group": {
    "b": true,
    "c": false
  }
}

UPD: I was wrong about liveOmit/omitExtraData - the same behavior presents when liveOmit and omitExtraData are turned off. So it may be related to generating default data. Need to deep into the sources of v5.

AlimovSV avatar Mar 03 '23 18:03 AlimovSV

This issue was closed because of lack of recent activity. Reoopen if you still need assistance.

stale[bot] avatar May 12 '23 17:05 stale[bot]

Fixed by #3627

heath-freenome avatar Jun 30 '23 15:06 heath-freenome