diff --git a/CHANGELOG.md b/CHANGELOG.md index fc8fc2344d..2ca652d278 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ should change the heading of the (upcoming) version to include a major version b - **BREAKING CHANGE** Fix overriding core submit button className (https://github.com/rjsf-team/react-jsonschema-form/issues/2979) - Fix `ui:field` with anyOf or oneOf no longer rendered twice (#2890) - **BREAKING CHANGE** Fixed `anyOf` and `oneOf` getting incorrect, potentially duplicate ids when combined with array (https://github.com/rjsf-team/react-jsonschema-form/issues/2197) +- `formContext` is now passed properly to `SchemaField`, fixes (https://github.com/rjsf-team/react-jsonschema-form/issues/2394, https://github.com/rjsf-team/react-jsonschema-form/issues/2274) ## @rjsf/semantic-ui - Fix missing error class on fields (https://github.com/rjsf-team/react-jsonschema-form/issues/2666) diff --git a/packages/core/src/components/fields/ArrayField.tsx b/packages/core/src/components/fields/ArrayField.tsx index 330078c7fe..2be245f460 100644 --- a/packages/core/src/components/fields/ArrayField.tsx +++ b/packages/core/src/components/fields/ArrayField.tsx @@ -802,6 +802,7 @@ class ArrayField extends Component< readonly, uiSchema, registry, + formContext, } = this.props; const { fields: { SchemaField }, @@ -825,6 +826,7 @@ class ArrayField extends Component< schema={itemSchema} uiSchema={itemUiSchema} formData={itemData} + formContext={formContext} errorSchema={itemErrorSchema} idPrefix={idPrefix} idSeparator={idSeparator} diff --git a/packages/core/src/components/fields/MultiSchemaField.tsx b/packages/core/src/components/fields/MultiSchemaField.tsx index f7082a98e7..02921b3f40 100644 --- a/packages/core/src/components/fields/MultiSchemaField.tsx +++ b/packages/core/src/components/fields/MultiSchemaField.tsx @@ -151,6 +151,7 @@ class AnyOfField extends Component< hideError = false, errorSchema = {}, formData, + formContext, idPrefix, idSeparator, idSchema, @@ -199,6 +200,7 @@ class AnyOfField extends Component< value={selectedOption} options={{ enumOptions }} registry={registry} + formContext={formContext} {...uiOptions} label="" /> @@ -213,6 +215,7 @@ class AnyOfField extends Component< idPrefix={idPrefix} idSeparator={idSeparator} formData={formData} + formContext={formContext} onChange={onChange} onBlur={onBlur} onFocus={onFocus} diff --git a/packages/core/src/components/fields/ObjectField.tsx b/packages/core/src/components/fields/ObjectField.tsx index 0dda51c774..e0ab7204dc 100644 --- a/packages/core/src/components/fields/ObjectField.tsx +++ b/packages/core/src/components/fields/ObjectField.tsx @@ -286,6 +286,7 @@ class ObjectField extends Component< idPrefix={idPrefix} idSeparator={idSeparator} formData={get(formData, name)} + formContext={formContext} wasPropertyKeyModified={this.state.wasPropertyKeyModified} onKeyChange={this.onKeyChange(name)} onChange={this.onPropertyChange( diff --git a/packages/core/src/components/fields/SchemaField.tsx b/packages/core/src/components/fields/SchemaField.tsx index 2c0d31974e..fbcb6fd795 100644 --- a/packages/core/src/components/fields/SchemaField.tsx +++ b/packages/core/src/components/fields/SchemaField.tsx @@ -313,6 +313,7 @@ function SchemaFieldRender(props: FieldProps) { hideError={hideError} errorSchema={errorSchema} formData={formData} + formContext={formContext} idPrefix={idPrefix} idSchema={idSchema} idSeparator={idSeparator} @@ -341,6 +342,7 @@ function SchemaFieldRender(props: FieldProps) { hideError={hideError} errorSchema={errorSchema} formData={formData} + formContext={formContext} idPrefix={idPrefix} idSchema={idSchema} idSeparator={idSeparator} diff --git a/packages/core/test/ArrayField_test.js b/packages/core/test/ArrayField_test.js index ddf8e41b94..65819f2b9a 100644 --- a/packages/core/test/ArrayField_test.js +++ b/packages/core/test/ArrayField_test.js @@ -5,6 +5,7 @@ import { Simulate } from "react-dom/test-utils"; import sinon from "sinon"; import { createFormComponent, createSandbox, submitForm } from "./test_utils"; +import SchemaField from "../src/components/fields/SchemaField"; const ArrayKeyDataAttr = "data-rjsf-itemkey"; const ExposedArrayKeyTemplate = function (props) { @@ -2177,4 +2178,46 @@ describe("ArrayField", () => { expect(inputsNoError).to.have.length.of(0); }); }); + describe("FormContext gets passed", () => { + const schema = { + type: "array", + items: [ + { + type: "string", + title: "Some text", + }, + { + type: "number", + title: "A number", + }, + ], + }; + it("should pass form context to schema field", () => { + const formContext = { + root: "root-id", + root_0: "root_0-id", + root_1: "root_1-id", + }; + function CustomSchemaField(props) { + const { formContext, idSchema } = props; + return ( + <> + Ha + + + ); + } + const { node } = createFormComponent({ + schema, + formContext, + fields: { SchemaField: CustomSchemaField }, + }); + + const codeBlocks = node.querySelectorAll("code"); + expect(codeBlocks).to.have.length(3); + Object.keys(formContext).forEach((key) => { + expect(node.querySelector(`code#${formContext[key]}`)).to.exist; + }); + }); + }); }); diff --git a/packages/core/test/ObjectField_test.js b/packages/core/test/ObjectField_test.js index c150c92629..c94d7d21a5 100644 --- a/packages/core/test/ObjectField_test.js +++ b/packages/core/test/ObjectField_test.js @@ -3,6 +3,7 @@ import { expect } from "chai"; import { Simulate } from "react-dom/test-utils"; import sinon from "sinon"; +import SchemaField from "../src/components/fields/SchemaField"; import { createFormComponent, createSandbox, submitForm } from "./test_utils"; describe("ObjectField", () => { @@ -190,6 +191,34 @@ describe("ObjectField", () => { expect(node.querySelector("input[type=text]").id).eql("root_foo"); expect(node.querySelector("input[type=checkbox]").id).eql("root_bar"); }); + + it("should pass form context to schema field", () => { + const formContext = { + root: "root-id", + root_foo: "foo-id", + root_bar: "bar-id", + }; + function CustomSchemaField(props) { + const { formContext, idSchema } = props; + return ( + <> + Ha + + + ); + } + const { node } = createFormComponent({ + schema, + formContext, + fields: { SchemaField: CustomSchemaField }, + }); + + const codeBlocks = node.querySelectorAll("code"); + expect(codeBlocks).to.have.length(3); + Object.keys(formContext).forEach((key) => { + expect(node.querySelector(`code#${formContext[key]}`)).to.exist; + }); + }); }); describe("fields ordering", () => { diff --git a/packages/core/test/allOf_test.js b/packages/core/test/allOf_test.js index f3644dbbac..a3a4ad0e6b 100644 --- a/packages/core/test/allOf_test.js +++ b/packages/core/test/allOf_test.js @@ -1,6 +1,8 @@ import { expect } from "chai"; +import React from "react"; import { createFormComponent, createSandbox } from "./test_utils"; +import SchemaField from "../src/components/fields/SchemaField"; describe("allOf", () => { let sandbox; @@ -46,4 +48,36 @@ describe("allOf", () => { expect(node.querySelectorAll("input")).to.have.length.of(0); }); + it("should pass form context to schema field", () => { + const schema = { + type: "object", + properties: { + foo: { + allOf: [{ type: "string" }, { type: "boolean" }], + }, + }, + }; + const formContext = { root: "root-id", root_foo: "foo-id" }; + function CustomSchemaField(props) { + const { formContext, idSchema } = props; + return ( + <> + Ha + + + ); + } + const { node } = createFormComponent({ + schema, + formData: { userId: "foobarbaz" }, + formContext, + fields: { SchemaField: CustomSchemaField }, + }); + + const codeBlocks = node.querySelectorAll("code"); + expect(codeBlocks).to.have.length(2); + Object.keys(formContext).forEach((key) => { + expect(node.querySelector(`code#${formContext[key]}`)).to.exist; + }); + }); }); diff --git a/packages/core/test/oneOf_test.js b/packages/core/test/oneOf_test.js index 650d502772..12abfdbb65 100644 --- a/packages/core/test/oneOf_test.js +++ b/packages/core/test/oneOf_test.js @@ -4,6 +4,7 @@ import { Simulate } from "react-dom/test-utils"; import sinon from "sinon"; import { createFormComponent, createSandbox, setProps } from "./test_utils"; +import SchemaField from "../src/components/fields/SchemaField"; describe("oneOf", () => { let sandbox; @@ -394,6 +395,46 @@ describe("oneOf", () => { expect(node.querySelectorAll("#custom-oneof-field")).to.have.length(1); }); + it("should pass form context to schema field", () => { + const schema = { + type: "object", + properties: { + userId: { + oneOf: [ + { + type: "number", + }, + { + type: "string", + }, + ], + }, + }, + }; + const formContext = { root: "root-id", root_userId: "userId-id" }; + function CustomSchemaField(props) { + const { formContext, idSchema } = props; + return ( + <> + Ha + + + ); + } + const { node } = createFormComponent({ + schema, + formData: { userId: "foobarbaz" }, + formContext, + fields: { SchemaField: CustomSchemaField }, + }); + + const codeBlocks = node.querySelectorAll("code"); + expect(codeBlocks).to.have.length(3); + Object.keys(formContext).forEach((key) => { + expect(node.querySelector(`code#${formContext[key]}`)).to.exist; + }); + }); + it("should select the correct field when the form is rendered from existing data", () => { const schema = { type: "object",