From 51d403ab448326183f58b5cc7c2c750c200f0242 Mon Sep 17 00:00:00 2001 From: Edgar Hipp Date: Sat, 13 Jan 2018 16:26:52 +0100 Subject: [PATCH] Add idPrefix option (Fix #796) (#806) --- README.md | 13 +++++++++++++ src/components/Form.js | 3 ++- src/components/fields/ArrayField.js | 8 ++++++-- src/components/widgets/TextWidget.js | 1 + src/utils.js | 22 +++++++++++++++++----- test/Form_test.js | 24 ++++++++++++++++++++++++ test/StringField_test.js | 1 - test/utils_test.js | 23 +++++++++++++++++++++++ 8 files changed, 86 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 57d4b883e1..9326e64c15 100644 --- a/README.md +++ b/README.md @@ -997,6 +997,19 @@ The following props are passed to `ErrorList` - `uiSchema`: The uiSchema that was passed to `Form`. - `formContext`: The `formContext` object that you passed to Form. +### Id prefix + +To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids (the default is `root`). + +```jsx +render(( +
, +), document.getElementById("app")); +``` + +This will render `` instead of `` + ### Custom widgets and fields The API allows to specify your own custom *widget* and *field* components: diff --git a/src/components/Form.js b/src/components/Form.js index 163fc33fe9..603ae6a357 100644 --- a/src/components/Form.js +++ b/src/components/Form.js @@ -52,7 +52,8 @@ export default class Form extends Component { retrievedSchema, uiSchema["ui:rootFieldId"], definitions, - formData + formData, + props.idPrefix ); return { schema, diff --git a/src/components/fields/ArrayField.js b/src/components/fields/ArrayField.js index 67f433394d..a71bbaa51e 100644 --- a/src/components/fields/ArrayField.js +++ b/src/components/fields/ArrayField.js @@ -330,6 +330,7 @@ class ArrayField extends Component { formContext, onBlur, onFocus, + idPrefix, } = this.props; const title = schema.title === undefined ? name : schema.title; const { ArrayFieldTemplate, definitions, fields } = registry; @@ -345,7 +346,8 @@ class ArrayField extends Component { itemSchema, itemIdPrefix, definitions, - item + item, + idPrefix ); return this.renderArrayFieldItem({ index, @@ -464,6 +466,7 @@ class ArrayField extends Component { uiSchema, formData, errorSchema, + idPrefix, idSchema, name, required, @@ -508,7 +511,8 @@ class ArrayField extends Component { itemSchema, itemIdPrefix, definitions, - item + item, + idPrefix ); const itemUiSchema = additional ? uiSchema.additionalItems || {} diff --git a/src/components/widgets/TextWidget.js b/src/components/widgets/TextWidget.js index 027e4e26f1..128eab1cb8 100644 --- a/src/components/widgets/TextWidget.js +++ b/src/components/widgets/TextWidget.js @@ -9,6 +9,7 @@ function TextWidget(props) { if (process.env.NODE_ENV !== "production") { TextWidget.propTypes = { value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + id: PropTypes.string, }; } diff --git a/src/utils.js b/src/utils.js index ec00332847..e741510f10 100644 --- a/src/utils.js +++ b/src/utils.js @@ -619,16 +619,22 @@ export function shouldRender(comp, nextProps, nextState) { return !deepEquals(props, nextProps) || !deepEquals(state, nextState); } -export function toIdSchema(schema, id, definitions, formData = {}) { +export function toIdSchema( + schema, + id, + definitions, + formData = {}, + idPrefix = "root" +) { const idSchema = { - $id: id || "root", + $id: id || idPrefix, }; if ("$ref" in schema) { const _schema = retrieveSchema(schema, definitions, formData); - return toIdSchema(_schema, id, definitions, formData); + return toIdSchema(_schema, id, definitions, formData, idPrefix); } if ("items" in schema && !schema.items.$ref) { - return toIdSchema(schema.items, id, definitions, formData); + return toIdSchema(schema.items, id, definitions, formData, idPrefix); } if (schema.type !== "object") { return idSchema; @@ -636,7 +642,13 @@ export function toIdSchema(schema, id, definitions, formData = {}) { for (const name in schema.properties || {}) { const field = schema.properties[name]; const fieldId = idSchema.$id + "_" + name; - idSchema[name] = toIdSchema(field, fieldId, definitions, formData[name]); + idSchema[name] = toIdSchema( + field, + fieldId, + definitions, + formData[name], + idPrefix + ); } return idSchema; } diff --git a/test/Form_test.js b/test/Form_test.js index d1cbfdb51a..ec26583948 100644 --- a/test/Form_test.js +++ b/test/Form_test.js @@ -44,6 +44,30 @@ describe("Form", () => { }); }); + describe("Option idPrefix", function() { + it("should change the rendered ids", function() { + const schema = { + type: "object", + title: "root object", + required: ["foo"], + properties: { + count: { + type: "number", + }, + }, + }; + const comp = renderIntoDocument(); + const node = findDOMNode(comp); + const inputs = node.querySelectorAll("input"); + const ids = []; + for (var i = 0, len = inputs.length; i < len; i++) { + const input = inputs[i]; + ids.push(input.getAttribute("id")); + } + expect(ids).to.eql(["rjsf_count"]); + }); + }); + describe("Custom field template", () => { const schema = { type: "object", diff --git a/test/StringField_test.js b/test/StringField_test.js index ef65f72daf..af02df60ba 100644 --- a/test/StringField_test.js +++ b/test/StringField_test.js @@ -237,7 +237,6 @@ describe("StringField", () => { }, }); - console.log(node.querySelectorAll(".field option")[0].innerHTML); expect(node.querySelectorAll(".field option")[0].textContent).eql("Test"); }); diff --git a/test/utils_test.js b/test/utils_test.js index 09b9d8dea0..1e3b0141e3 100644 --- a/test/utils_test.js +++ b/test/utils_test.js @@ -1028,6 +1028,29 @@ describe("utils", () => { bar: { $id: "root_bar" }, }); }); + + it("should handle idPrefix parameter", () => { + const schema = { + definitions: { + testdef: { + type: "object", + properties: { + foo: { type: "string" }, + bar: { type: "string" }, + }, + }, + }, + $ref: "#/definitions/testdef", + }; + + expect(toIdSchema(schema, undefined, schema.definitions, {}, "rjsf")).eql( + { + $id: "rjsf", + foo: { $id: "rjsf_foo" }, + bar: { $id: "rjsf_bar" }, + } + ); + }); }); describe("parseDateString()", () => {