Repository: mozilla-services/react-jsonschema-form
Pull request #453 (2017-01-27 18:27:39)

Ref #452: Support recursively referenced definitions.
WiP, refs #452.


Patch:
diff --git a/playground/samples/index.js b/playground/samples/index.js
index 8eba6cc82..1527696cc 100644
--- a/playground/samples/index.js
+++ b/playground/samples/index.js
@@ -29,5 +29,5 @@ export const samples = {
   Validation: validation,
   Files: files,
   Single: single,
-  "Custom Array": customArray
+  "Custom Array": customArray,
 };
diff --git a/playground/samples/references.js b/playground/samples/references.js
index 5131c4b98..2cf8dcd11 100644
--- a/playground/samples/references.js
+++ b/playground/samples/references.js
@@ -9,6 +9,18 @@ module.exports = {
           state:          { type: "string" }
         },
         required: ["street_address", "city", "state"]
+      },
+      node: {
+        type: "object",
+        properties: {
+          name: {type: "string"},
+          children: {
+            type: "array",
+            items: {
+              $ref: "#/definitions/node"
+            }
+          }
+        }
       }
     },
     type: "object",
@@ -20,11 +32,15 @@ module.exports = {
       shipping_address: {
         title: "Shipping address",
         $ref: "#/definitions/address"
+      },
+      tree: {
+        title: "Recursive references",
+        $ref: "#/definitions/node"
       }
     }
   },
   uiSchema: {
-    "ui:order": ["shipping_address", "billing_address"]
+    "ui:order": ["shipping_address", "billing_address", "tree"]
   },
   formData: {
     billing_address: {
@@ -36,6 +52,12 @@ module.exports = {
       street_address: "221B, Baker Street",
       city: "London",
       state: "N/A"
+    },
+    tree: {
+      name: "root",
+      children: [
+         {name: "leaf"}
+      ]
     }
   }
 };
diff --git a/src/components/widgets/TextareaWidget.js b/src/components/widgets/TextareaWidget.js
index 70aa3d9f4..7bcb03b26 100644
--- a/src/components/widgets/TextareaWidget.js
+++ b/src/components/widgets/TextareaWidget.js
@@ -15,7 +15,7 @@ function TextareaWidget({
 }) {
   const _onChange = ({target: {value}}) => {
     return onChange(value === "" ? undefined : value);
-  };  
+  };
   return (
     <textarea
       id={id}
@@ -27,7 +27,7 @@ function TextareaWidget({
       readOnly={readonly}
       autoFocus={autofocus}
       onBlur={onBlur && (event => onBlur(id, event.target.value))}
-      onChange={_onChange} />
+      onChange={_onChange}/>
   );
 }
 
diff --git a/src/utils.js b/src/utils.js
index cb927c8a8..b051dbee7 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -395,9 +395,9 @@ export function toIdSchema(schema, id, definitions) {
   };
   if ("$ref" in schema) {
     const _schema = retrieveSchema(schema, definitions);
-    return toIdSchema(_schema, id, definitions);
+    return toIdSchema(_schema, id, definitions, schema.$ref);
   }
-  if ("items" in schema) {
+  if ("items" in schema && !schema.items.$ref) {
     return toIdSchema(schema.items, id, definitions);
   }
   if (schema.type !== "object") {


Test patch:
diff --git a/test/Form_test.js b/test/Form_test.js
index 7aff92cdf..f60ce5524 100644
--- a/test/Form_test.js
+++ b/test/Form_test.js
@@ -313,6 +313,36 @@ describe("Form", () => {
         .eql("hello");
     });
 
+    it("should recursively handles referenced definitions", () => {
+      const schema = {
+        $ref: "#/definitions/node",
+        definitions: {
+          node: {
+            type: "object",
+            properties: {
+              name: {type: "string"},
+              children: {
+                type: "array",
+                items: {
+                  $ref: "#/definitions/node"
+                }
+              }
+            }
+          }
+        }
+      };
+
+      const {node} = createFormComponent({schema});
+
+      expect(node.querySelector("#root_children_0_name"))
+        .to.not.exists;
+
+      Simulate.click(node.querySelector(".array-item-add button"));
+
+      expect(node.querySelector("#root_children_0_name"))
+        .to.exists;
+    });
+
     it("should priorize definition over schema type property", () => {
       // Refs bug #140
       const schema = {