diff --git a/src/components/fields/ArrayField.js b/src/components/fields/ArrayField.js index 97a04a5de2..94fbabac6d 100644 --- a/src/components/fields/ArrayField.js +++ b/src/components/fields/ArrayField.js @@ -366,6 +366,7 @@ class ArrayField extends Component { onBlur, onFocus, idPrefix, + rawErrors, } = this.props; const title = schema.title === undefined ? name : schema.title; const { ArrayFieldTemplate, definitions, fields, formContext } = registry; @@ -411,6 +412,7 @@ class ArrayField extends Component { TitleField, formContext, formData, + rawErrors, }; // Check if a custom render function was passed in @@ -430,6 +432,7 @@ class ArrayField extends Component { onBlur, onFocus, registry = getDefaultRegistry(), + rawErrors, } = this.props; const items = this.props.formData; const { widgets, definitions, formContext } = registry; @@ -454,6 +457,7 @@ class ArrayField extends Component { readonly={readonly} formContext={formContext} autofocus={autofocus} + rawErrors={rawErrors} /> ); } @@ -470,6 +474,7 @@ class ArrayField extends Component { onBlur, onFocus, registry = getDefaultRegistry(), + rawErrors, } = this.props; const title = schema.title || name; const items = this.props.formData; @@ -491,6 +496,7 @@ class ArrayField extends Component { readonly={readonly} formContext={formContext} autofocus={autofocus} + rawErrors={rawErrors} /> ); } @@ -511,6 +517,7 @@ class ArrayField extends Component { registry = getDefaultRegistry(), onBlur, onFocus, + rawErrors, } = this.props; const title = schema.title || name; let items = this.props.formData; @@ -579,6 +586,7 @@ class ArrayField extends Component { title, TitleField, formContext, + rawErrors, }; // Check if a custom template template was passed in @@ -600,6 +608,7 @@ class ArrayField extends Component { autofocus, onBlur, onFocus, + rawErrors, } = props; const { disabled, @@ -636,6 +645,7 @@ class ArrayField extends Component { disabled={this.props.disabled} readonly={this.props.readonly} autofocus={autofocus} + rawErrors={rawErrors} /> ), className: "array-item", diff --git a/test/ArrayField_test.js b/test/ArrayField_test.js index 9dc22e21c1..4dba969d64 100644 --- a/test/ArrayField_test.js +++ b/test/ArrayField_test.js @@ -7,7 +7,9 @@ import { createFormComponent, createSandbox } from "./test_utils"; describe("ArrayField", () => { let sandbox; - const CustomComponent = () =>
; + const CustomComponent = props => { + return
{props.rawErrors}
; + }; beforeEach(() => { sandbox = createSandbox(); @@ -98,6 +100,29 @@ describe("ArrayField", () => { expect(node.querySelector("#custom")).to.exist; }); + it("should pass rawErrors down to custom array field templates", () => { + const schema = { + type: "array", + title: "my list", + description: "my description", + items: { type: "string" }, + minItems: 2, + }; + + const { node } = createFormComponent({ + schema, + ArrayFieldTemplate: CustomComponent, + formData: [1], + liveValidate: true, + }); + + const matches = node.querySelectorAll("#custom"); + expect(matches).to.have.length.of(1); + expect(matches[0].textContent).to.eql( + "should NOT have less than 2 items" + ); + }); + it("should contain no field in the list by default", () => { const { node } = createFormComponent({ schema }); @@ -660,6 +685,23 @@ describe("ArrayField", () => { expect(node.querySelector("select").id).eql("root"); }); + + it("should pass rawErrors down to custom widgets", () => { + const { node } = createFormComponent({ + schema, + widgets: { + SelectWidget: CustomComponent, + }, + formData: ["foo", "foo"], + liveValidate: true, + }); + + const matches = node.querySelectorAll("#custom"); + expect(matches).to.have.length.of(1); + expect(matches[0].textContent).to.eql( + "should NOT have duplicate items (items ## 0 and 1 are identical)" + ); + }); }); describe("CheckboxesWidget", () => { @@ -729,6 +771,35 @@ describe("ArrayField", () => { expect(node.querySelectorAll(".checkbox-inline")).to.have.length.of(3); }); + + it("should pass rawErrors down to custom widgets", () => { + const schema = { + type: "array", + title: "My field", + items: { + enum: ["foo", "bar", "fuzz"], + type: "string", + }, + minItems: 3, + uniqueItems: true, + }; + + const { node } = createFormComponent({ + schema, + widgets: { + CheckboxesWidget: CustomComponent, + }, + uiSchema, + formData: [], + liveValidate: true, + }); + + const matches = node.querySelectorAll("#custom"); + expect(matches).to.have.length.of(1); + expect(matches[0].textContent).to.eql( + "should NOT have less than 3 items" + ); + }); }); }); @@ -809,6 +880,33 @@ describe("ArrayField", () => { expect(node.querySelector("input[type=file]").id).eql("root"); }); + + it("should pass rawErrors down to custom widgets", () => { + const schema = { + type: "array", + title: "My field", + items: { + type: "string", + format: "data-url", + }, + minItems: 5, + }; + + const { node } = createFormComponent({ + schema, + widgets: { + FileWidget: CustomComponent, + }, + formData: [], + liveValidate: true, + }); + + const matches = node.querySelectorAll("#custom"); + expect(matches).to.have.length.of(1); + expect(matches[0].textContent).to.eql( + "should NOT have less than 5 items" + ); + }); }); describe("Nested lists", () => { @@ -840,6 +938,51 @@ describe("ArrayField", () => { expect(node.querySelectorAll("fieldset fieldset")).to.have.length.of(1); }); + + it("should pass rawErrors down to every level of custom widgets", () => { + const CustomItem = props =>
{props.children}
; + const CustomTemplate = props => { + return ( +
+ {props.items && + props.items.map((p, i) => )} +
+ {props.rawErrors && props.rawErrors.join(", ")} +
+
+ ); + }; + + const schema = { + type: "array", + title: "A list of arrays", + items: { + type: "array", + title: "A list of numbers", + items: { + type: "number", + }, + minItems: 3, + }, + minItems: 2, + }; + + const { node } = createFormComponent({ + schema, + ArrayFieldTemplate: CustomTemplate, + formData: [[]], + liveValidate: true, + }); + + const matches = node.querySelectorAll("#custom-error"); + expect(matches).to.have.length.of(2); + expect(matches[0].textContent).to.eql( + "should NOT have less than 3 items" + ); + expect(matches[1].textContent).to.eql( + "should NOT have less than 2 items" + ); + }); }); describe("Fixed items lists", () => {