Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
3 tasks done
FunJim opened this issue Mar 3, 2020 · 12 comments
Closed
3 tasks done

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

FunJim opened this issue Mar 3, 2020 · 12 comments
Labels
any-one-all-of Related to fixing anyOf, oneOf or allOf bug

Comments

@FunJim
Copy link

FunJim commented Mar 3, 2020

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/

@AlimovSV
Copy link
Contributor

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;

@bysph
Copy link

bysph commented Jun 8, 2022

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

@ksbrar
Copy link

ksbrar commented Jun 8, 2022

bump, any known workaround?

@benjdlambert
Copy link
Contributor

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

@AlimovSV
Copy link
Contributor

AlimovSV commented Aug 25, 2022

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' } ] }

kilosonc pushed a commit to horizoncd/horizon-web that referenced this issue Jan 14, 2023
@AlimovSV
Copy link
Contributor

AlimovSV commented Mar 2, 2023

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

@heath-freenome
Copy link
Member

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 heath-freenome added the possibly close To confirm if this issue can be closed label Mar 3, 2023
@AlimovSV
Copy link
Contributor

AlimovSV commented Mar 3, 2023

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.

@heath-freenome
Copy link
Member

heath-freenome commented Mar 3, 2023

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

@AlimovSV
Copy link
Contributor

AlimovSV commented Mar 3, 2023

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.

heath-freenome added a commit to heath-freenome/react-jsonschema-form that referenced this issue Apr 28, 2023
heath-freenome added a commit that referenced this issue May 2, 2023
…ema functions (#3627)

* feature: Add two new APIs and a schema parser refactor of retrieveSchema functions
First part of the process to support precompiled AJV8 validators
- Updated `@rjsf/utils` to support precompiled AJV8 validators as follows:
  - Refactored `getDiscriminatorFieldFromSchema()` from inside of `MultiSchemaField`, using it everywhere that `getClosestMatchingOption()` and `getFirstMatchingOption()` are called
    - This included changing `getDefaultFormState.ts` and `toPathSchema.ts`
    - Added 100% unit tests for the new functions
  - Added a new `hashForSchema()` function that returns a hash string for the given schema
    - Added 100% unit tests for the new functions
  - Did a major refactor of the functions in `retrieveSchema.ts` to have them all support returning lists of schemas and for most of them to take a `expandAllBranches` flag
    - Added renamed the original `retrieveSchema()` to `retrieveSchemaInternal()` function that is used as the entry point into the returning lists of schemas worlds
      - This function added the optional `expandAllBranches` flag with the default value set to false
    - Added a new default exported function `retrieveSchema()` that calls `retrieveSchemaInternal()` without the optional value, returning the first element in the list
    - Also added two new helpers, `getAllPermutationsOfXxxOf()` and `resolveAnyOrOneOfSchemas()` to support the new schema array return values
    - Updated the `retrieveSchemaTests.ts` file to extract a bunch of schemas into the `testData.ts` file while making sure all lines of new code are tested
  - Added a new `parser` subdirectory that contains the `ParserValidator` implementation of the `ValidatorType` interface for the new `schemaParser()` function
    - This new function uses the `expandAllBranches()` to capture and return the map of schema $id -> schema/sub-schema as captured by the `ParserValidator`
    - Added 100% unit testing for the new `schemaParser()` function
    - NOTE: while this function is being exported from `@rjsf/utils` it is meant to be kept undocument in the `docs`
- Updated `@rjsf/core` to use the new `getDiscriminatorFieldFromSchema()` function in `MultiSchemaField`
- Updated the `utility-functions` docs to add documentation for `getDiscriminatorFieldFromSchema()` and `hashForSchema()`
- Updated the `CHANGELOG.md` accordingly

* - Fixed #3628 and #1628

* - Responded to reviewer feedback

* Update packages/utils/src/parser/ParserValidator.ts

Co-authored-by: Nick Grosenbacher <[email protected]>

* Update packages/utils/test/parser/ParserValidator.test.ts

---------

Co-authored-by: Nick Grosenbacher <[email protected]>
@stale
Copy link

stale bot commented May 12, 2023

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

@stale stale bot closed this as completed May 12, 2023
@heath-freenome heath-freenome added bug any-one-all-of Related to fixing anyOf, oneOf or allOf and removed possibly close To confirm if this issue can be closed labels May 12, 2023
@heath-freenome
Copy link
Member

Fixed by #3627

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
any-one-all-of Related to fixing anyOf, oneOf or allOf bug
Projects
None yet
Development

No branches or pull requests

6 participants