Repository: mozilla-services/react-jsonschema-form (js)

Issue:
Allow adding a custom validation error at a given array index
There's currently no way to declare a custom validation error at a given position in an array value. Would be nice to expose an API for that, eg.:

``` js
function validate({myArray}, errors) {
  if (myArray[1] !== "foo") {
    errors.myArray[1].addError("Nope.");
  }
  return errors;
}
```


Pull request description:
Fix #223: Allow adding a custom validation error at a given array index
### Reasons for making this change

For #223

### Checklist

* [ ] **I'm updating documentation**
  - [ ] I've checked the rendering of the Markdown text I've added
  - [ ] If I'm adding a new section, I've updated the Table of Content
* [x] **I'm adding or updating code**
  - [x] I've added and/or updated tests
  - [ ] I've updated docs if needed
  - [x] I've run `npm run cs-format` on my branch to conform my code to [prettier](https://github.com/prettier/prettier) coding style
* [ ] **I'm adding a new feature**
  - [ ] I've updated the playground with an example use of the feature


Patch:
diff --git a/src/validate.js b/src/validate.js
index 08228f386..d641122db 100644
--- a/src/validate.js
+++ b/src/validate.js
@@ -88,6 +88,14 @@ function createErrorHandler(formData) {
       handler
     );
   }
+  if (Array.isArray(formData)) {
+    return formData.reduce(
+      (acc, value, key) => {
+        return { ...acc, [key]: createErrorHandler(value) };
+      },
+      handler
+    );
+  }
   return handler;
 }
 


Test patch:
diff --git a/test/validate_test.js b/test/validate_test.js
index ab03df79c..fa8733afa 100644
--- a/test/validate_test.js
+++ b/test/validate_test.js
@@ -368,6 +368,62 @@ describe("Validation", () => {
         });
       });
 
+      it("should validate an array of object", () => {
+        const schema = {
+          type: "array",
+          items: {
+            type: "object",
+            properties: {
+              pass1: { type: "string" },
+              pass2: { type: "string" },
+            },
+          },
+        };
+
+        const formData = [
+          { pass1: "a", pass2: "b" },
+          { pass1: "a", pass2: "a" },
+        ];
+
+        function validate(formData, errors) {
+          formData.forEach(({ pass1, pass2 }, i) => {
+            if (pass1 !== pass2) {
+              errors[i].pass2.addError("Passwords don't match");
+            }
+          });
+          return errors;
+        }
+
+        const { comp } = createFormComponent({
+          schema,
+          validate,
+          liveValidate: true,
+        });
+        comp.componentWillReceiveProps({ formData });
+
+        expect(comp.state.errorSchema).eql({
+          0: {
+            pass1: {
+              __errors: [],
+            },
+            pass2: {
+              __errors: ["Passwords don't match"],
+            },
+            __errors: [],
+          },
+          1: {
+            pass1: {
+              __errors: [],
+            },
+            pass2: {
+              __errors: [],
+            },
+            __errors: [],
+          },
+          __errors: [],
+        });
+      });
+
       it("should validate a simple array", () => {
         const schema = {
           type: "array",
@@ -393,6 +449,9 @@ describe("Validation", () => {
         comp.componentWillReceiveProps({ formData });
 
         expect(comp.state.errorSchema).eql({
+          0: { __errors: [] },
+          1: { __errors: [] },
+          2: { __errors: [] },
           __errors: ["Forbidden value: bbb"],
         });
       });