diff --git a/README.md b/README.md
index aeb3048c08..02b5e85981 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@ A [live playground](https://mozilla-services.github.io/react-jsonschema-form/) i
- [Form error event handler](#form-error-event-handler)
- [Form data changes](#form-data-changes)
- [Form field blur events](#form-field-blur-events)
+ - [Form field focus events](#form-field-focus-events)
- [Form customization](#form-customization)
- [The uiSchema object](#the-uischema-object)
- [Alternative widgets](#alternative-widgets)
@@ -42,7 +43,8 @@ A [live playground](https://mozilla-services.github.io/react-jsonschema-form/) i
- [removable option](#removable-option)
- [Custom CSS class names](#custom-css-class-names)
- [Custom labels for enum fields](#custom-labels-for-enum-fields)
- - [Disabled enum fields](#disabled-attribute-for-enum-fields)
+ - [Alternative JSON-Schema compliant approach](#alternative-json-schema-compliant-approach)
+ - [Disabled attribute for enum fields](#disabled-attribute-for-enum-fields)
- [Multiple choices list](#multiple-choices-list)
- [Autogenerated widget ids](#autogenerated-widget-ids)
- [Form action buttons](#form-action-buttons)
@@ -60,11 +62,12 @@ A [live playground](https://mozilla-services.github.io/react-jsonschema-form/) i
- [Array Field Template](#array-field-template)
- [Object Field Template](#object-field-template)
- [Error List template](#error-list-template)
+ - [Id prefix](#id-prefix)
- [Custom widgets and fields](#custom-widgets-and-fields)
- [Custom widget components](#custom-widget-components)
- [Custom component registration](#custom-component-registration)
- [Custom widget options](#custom-widget-options)
- - [Customizing widgets' text input](#customizing-widgets-text-input)
+ - [Customizing widgets text input](#customizing-widgets-text-input)
- [Custom field components](#custom-field-components)
- [Field props](#field-props)
- [The registry object](#the-registry-object)
@@ -84,11 +87,11 @@ A [live playground](https://mozilla-services.github.io/react-jsonschema-form/) i
- [Styling your forms](#styling-your-forms)
- [Schema definitions and references](#schema-definitions-and-references)
- [Property dependencies](#property-dependencies)
- - [Unidirectional](#unidirectional)
- - [Bidirectional](#bidirectional)
+ - [Unidirectional](#unidirectional)
+ - [Bidirectional](#bidirectional)
- [Schema dependencies](#schema-dependencies)
- - [Conditional](#conditional)
- - [Dynamic](#dynamic)
+ - [Conditional](#conditional)
+ - [Dynamic](#dynamic)
- [JSON Schema supporting status](#json-schema-supporting-status)
- [Tips and tricks](#tips-and-tricks)
- [Contributing](#contributing)
@@ -96,7 +99,10 @@ A [live playground](https://mozilla-services.github.io/react-jsonschema-form/) i
- [Development server](#development-server)
- [Tests](#tests)
- [TDD](#tdd)
+ - [Releasing](#releasing)
- [FAQ](#faq)
+ - [Q: Does rjsf support oneOf, anyOf, multiple types in an array, etc.?](#q-does-rjsf-support-oneof-anyof-multiple-types-in-an-array-etc)
+ - [Q: Will react-jsonschema-form support Material, Ant-Design, Foundation, or [some other specific widget library or frontend style]?](#q-will-react-jsonschema-form-support-material-ant-design-foundation-or-some-other-specific-widget-library-or-frontend-style)
- [License](#license)
---
@@ -1184,7 +1190,7 @@ render((
> Note: Since v0.41.0, the `ui:widget` object API, where a widget and options were specified with `"ui:widget": {component, options}` shape, is deprecated. It will be removed in a future release.
-#### Customizing widgets' text input
+#### Customizing widgets text input
All the widgets that render a text input use the `BaseInput` component internally. If you need to customize all text inputs without customizing all widgets individially, you can provide a `BaseInput` component in the `widgets` property of `Form` (see [Custom component registration](#custom-component-registration).
diff --git a/package.json b/package.json
index c4f1c74cd2..0137af3c36 100644
--- a/package.json
+++ b/package.json
@@ -8,17 +8,18 @@
"build:dist": "rimraf dist && cross-env NODE_ENV=production webpack --config webpack.config.dist.js --optimize-minimize",
"build:playground": "rimraf build && cross-env NODE_ENV=production webpack --config webpack.config.prod.js --optimize-minimize && cp playground/index.prod.html build/index.html",
"cs-check": "prettier -l $npm_package_prettierOptions '{playground,src,test}/**/*.js'",
- "cs-format": "prettier $npm_package_prettierOptions '{playground,src,test}/**/*.js' --write",
+ "cs-format": "prettier --jsx-bracket-same-line --trailing-comma es5 --use-tabs false --semi --tab-width 2 '{playground,src,test}/**/*.js' --write",
"dist": "npm run build:lib && npm run build:dist",
"lint": "eslint src test playground",
"precommit": "lint-staged",
"publish-to-gh-pages": "npm run build:playground && gh-pages --dist build/",
"publish-to-npm": "npm run build:readme && npm run dist && npm publish",
+ "preversion": "npm run build:playground && npm run dist && npm run build:readme && npm run cs-check && npm run lint",
"start": "node devServer.js",
"tdd": "cross-env NODE_ENV=test mocha --compilers js:babel-register --watch --require ./test/setup-jsdom.js test/**/*_test.js",
"test": "cross-env NODE_ENV=test mocha --compilers js:babel-register --require ./test/setup-jsdom.js test/**/*_test.js"
},
- "prettierOptions": "--jsx-bracket-same-line --trailing-comma es5 --semi",
+ "prettierOptions": "--jsx-bracket-same-line --trailing-comma es5 --semi --tab-width 2",
"lint-staged": {
"{playground,src,test}/**/*.js": [
"npm run lint",
diff --git a/src/components/Form.js b/src/components/Form.js
index e32a7b239c..c1b053786e 100644
--- a/src/components/Form.js
+++ b/src/components/Form.js
@@ -173,6 +173,7 @@ export default class Form extends Component {
children,
safeRenderCompletion,
id,
+ idPrefix,
className,
name,
method,
@@ -207,6 +208,7 @@ export default class Form extends Component {
uiSchema={uiSchema}
errorSchema={errorSchema}
idSchema={idSchema}
+ idPrefix={idPrefix}
formData={formData}
onChange={this.onChange}
onBlur={this.onBlur}
diff --git a/src/components/fields/ArrayField.js b/src/components/fields/ArrayField.js
index 94fbabac6d..dd71f85642 100644
--- a/src/components/fields/ArrayField.js
+++ b/src/components/fields/ArrayField.js
@@ -64,7 +64,10 @@ function DefaultArrayItem(props) {
+ style={{
+ display: "flex",
+ justifyContent: "space-around",
+ }}>
{(props.hasMoveUp || props.hasMoveDown) && (
{
},
},
};
- let form = createFormComponent({ schema: complexSchema, formData: {} });
+ let form = createFormComponent({
+ schema: complexSchema,
+ formData: {},
+ });
let inputs = form.node.querySelectorAll("input[type=text]");
expect(inputs[0].value).eql("Default name");
expect(inputs[1].value).eql("Default name");
@@ -726,7 +729,10 @@ describe("ArrayField", () => {
});
it("should handle a change event", () => {
- const { comp, node } = createFormComponent({ schema, uiSchema });
+ const { comp, node } = createFormComponent({
+ schema,
+ uiSchema,
+ });
Simulate.change(node.querySelectorAll("[type=checkbox]")[0], {
target: { checked: true },
@@ -1058,7 +1064,10 @@ describe("ArrayField", () => {
});
it("should fill fields with data", () => {
- const { node } = createFormComponent({ schema, formData: ["foo", 42] });
+ const { node } = createFormComponent({
+ schema,
+ formData: ["foo", 42],
+ });
const strInput = node.querySelector(
"fieldset .field-string input[type=text]"
);
diff --git a/test/Form_test.js b/test/Form_test.js
index ec26583948..fd84eea2cf 100644
--- a/test/Form_test.js
+++ b/test/Form_test.js
@@ -68,6 +68,85 @@ describe("Form", () => {
});
});
+ describe("Changing idPrefix", function() {
+ it("should work with simple example", 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"]);
+ });
+
+ it("should work with oneOf", function() {
+ const schema = {
+ $schema: "http://json-schema.org/draft-06/schema#",
+ type: "object",
+ properties: {
+ connector: {
+ type: "string",
+ enum: ["aws", "gcp"],
+ title: "Provider",
+ default: "aws",
+ },
+ },
+ dependencies: {
+ connector: {
+ oneOf: [
+ {
+ type: "object",
+ properties: {
+ connector: {
+ type: "string",
+ enum: ["aws"],
+ },
+ key_aws: {
+ type: "string",
+ },
+ },
+ },
+ {
+ type: "object",
+ properties: {
+ connector: {
+ type: "string",
+ enum: ["gcp"],
+ },
+ key_gcp: {
+ type: "string",
+ },
+ },
+ },
+ ],
+ },
+ },
+ };
+
+ 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_key_aws"]);
+ });
+ });
+
describe("Custom field template", () => {
const schema = {
type: "object",
@@ -592,7 +671,11 @@ describe("Form", () => {
foo: "",
};
const onChange = sandbox.spy();
- const { node } = createFormComponent({ schema, formData, onChange });
+ const { node } = createFormComponent({
+ schema,
+ formData,
+ onChange,
+ });
Simulate.change(node.querySelector("[type=text]"), {
target: { value: "new" },
@@ -835,7 +918,10 @@ describe("Form", () => {
});
it("should denote the new error in the field", () => {
- const { node } = createFormComponent({ schema, liveValidate: true });
+ const { node } = createFormComponent({
+ schema,
+ liveValidate: true,
+ });
Simulate.change(node.querySelector("input[type=text]"), {
target: { value: "short" },
@@ -1056,7 +1142,9 @@ describe("Form", () => {
const { comp } = createFormComponent(formProps);
expect(comp.state.errorSchema).eql({
- 1: { __errors: ["should NOT be shorter than 4 characters"] },
+ 1: {
+ __errors: ["should NOT be shorter than 4 characters"],
+ },
});
});
@@ -1108,8 +1196,12 @@ describe("Form", () => {
expect(comp.state.errorSchema).eql({
level1: {
- 1: { __errors: ["should NOT be shorter than 4 characters"] },
- 3: { __errors: ["should NOT be shorter than 4 characters"] },
+ 1: {
+ __errors: ["should NOT be shorter than 4 characters"],
+ },
+ 3: {
+ __errors: ["should NOT be shorter than 4 characters"],
+ },
},
});
});
@@ -1158,10 +1250,14 @@ describe("Form", () => {
expect(comp.state.errorSchema).eql({
outer: {
0: {
- 1: { __errors: ["should NOT be shorter than 4 characters"] },
+ 1: {
+ __errors: ["should NOT be shorter than 4 characters"],
+ },
},
1: {
- 0: { __errors: ["should NOT be shorter than 4 characters"] },
+ 0: {
+ __errors: ["should NOT be shorter than 4 characters"],
+ },
},
},
});
diff --git a/test/NumberField_test.js b/test/NumberField_test.js
index b5eee0fe3a..f1f5fd4824 100644
--- a/test/NumberField_test.js
+++ b/test/NumberField_test.js
@@ -51,7 +51,9 @@ describe("NumberField", () => {
});
it("should default state value to undefined", () => {
- const { comp } = createFormComponent({ schema: { type: "number" } });
+ const { comp } = createFormComponent({
+ schema: { type: "number" },
+ });
expect(comp.state.formData).eql(undefined);
});
diff --git a/test/SchemaField_test.js b/test/SchemaField_test.js
index 6376b4fd51..fa503d767e 100644
--- a/test/SchemaField_test.js
+++ b/test/SchemaField_test.js
@@ -22,7 +22,9 @@ describe("SchemaField", () => {
describe("Unsupported field", () => {
it("should warn on invalid field type", () => {
- const { node } = createFormComponent({ schema: { type: "invalid" } });
+ const { node } = createFormComponent({
+ schema: { type: "invalid" },
+ });
expect(node.querySelector(".unsupported-field").textContent).to.contain(
"Unknown field type invalid"
@@ -240,7 +242,9 @@ describe("SchemaField", () => {
},
},
};
- const { node } = createFormComponent({ schema: schemaWithReference });
+ const { node } = createFormComponent({
+ schema: schemaWithReference,
+ });
const matches = node.querySelectorAll("#root_foo__description");
expect(matches).to.have.length.of(1);
@@ -301,7 +305,11 @@ describe("SchemaField", () => {
}
it("should render it's own errors", () => {
- const { node } = createFormComponent({ schema, uiSchema, validate });
+ const { node } = createFormComponent({
+ schema,
+ uiSchema,
+ validate,
+ });
submit(node);
const matches = node.querySelectorAll(
@@ -312,7 +320,11 @@ describe("SchemaField", () => {
});
it("should pass errors to child component", () => {
- const { node } = createFormComponent({ schema, uiSchema, validate });
+ const { node } = createFormComponent({
+ schema,
+ uiSchema,
+ validate,
+ });
submit(node);
const matches = node.querySelectorAll(
diff --git a/test/StringField_test.js b/test/StringField_test.js
index af02df60ba..8bb9d2b079 100644
--- a/test/StringField_test.js
+++ b/test/StringField_test.js
@@ -66,7 +66,9 @@ describe("StringField", () => {
});
it("should default state value to undefined", () => {
- const { comp } = createFormComponent({ schema: { type: "string" } });
+ const { comp } = createFormComponent({
+ schema: { type: "string" },
+ });
expect(comp.state.formData).eql(undefined);
});
@@ -368,7 +370,10 @@ describe("StringField", () => {
it("should handle an empty string change event with custom ui:defaultValue", () => {
const { comp, node } = createFormComponent({
schema: { type: "string" },
- uiSchema: { "ui:widget": "textarea", "ui:emptyValue": "default" },
+ uiSchema: {
+ "ui:widget": "textarea",
+ "ui:emptyValue": "default",
+ },
formData: "x",
});
@@ -1535,7 +1540,9 @@ describe("StringField", () => {
});
Simulate.change(node.querySelector("[type=file]"), {
- target: { files: [{ name: "file1.txt", size: 1, type: "type" }] },
+ target: {
+ files: [{ name: "file1.txt", size: 1, type: "type" }],
+ },
});
return new Promise(setImmediate).then(() =>
diff --git a/test/uiSchema_test.js b/test/uiSchema_test.js
index 68d8123eb4..01848d32c8 100644
--- a/test/uiSchema_test.js
+++ b/test/uiSchema_test.js
@@ -200,7 +200,11 @@ describe("uiSchema", () => {
});
it("should render merged ui:widget options for widget referenced as function", () => {
- const { node } = createFormComponent({ schema, uiSchema, widgets });
+ const { node } = createFormComponent({
+ schema,
+ uiSchema,
+ widgets,
+ });
const widget = node.querySelector("#funcAll");
expect(widget.style.background).to.equal("purple");
@@ -210,7 +214,11 @@ describe("uiSchema", () => {
});
it("should render ui:widget default options for widget referenced as function", () => {
- const { node } = createFormComponent({ schema, uiSchema, widgets });
+ const { node } = createFormComponent({
+ schema,
+ uiSchema,
+ widgets,
+ });
const widget = node.querySelector("#funcNone");
expect(widget.style.background).to.equal("yellow");
@@ -220,7 +228,11 @@ describe("uiSchema", () => {
});
it("should render merged ui:widget options for widget referenced as string", () => {
- const { node } = createFormComponent({ schema, uiSchema, widgets });
+ const { node } = createFormComponent({
+ schema,
+ uiSchema,
+ widgets,
+ });
const widget = node.querySelector("#stringAll");
expect(widget.style.background).to.equal("blue");
@@ -230,7 +242,11 @@ describe("uiSchema", () => {
});
it("should render ui:widget default options for widget referenced as string", () => {
- const { node } = createFormComponent({ schema, uiSchema, widgets });
+ const { node } = createFormComponent({
+ schema,
+ uiSchema,
+ widgets,
+ });
const widget = node.querySelector("#stringNone");
expect(widget.style.background).to.equal("yellow");
@@ -240,7 +256,11 @@ describe("uiSchema", () => {
});
it("should ui:option inputType for html5 input types", () => {
- const { node } = createFormComponent({ schema, uiSchema, widgets });
+ const { node } = createFormComponent({
+ schema,
+ uiSchema,
+ widgets,
+ });
const widget = node.querySelector("input[type='tel']");
expect(widget).to.not.be.null;
});
@@ -280,7 +300,11 @@ describe("uiSchema", () => {
};
it("should render a nested custom widget", () => {
- const { node } = createFormComponent({ schema, uiSchema, widgets });
+ const { node } = createFormComponent({
+ schema,
+ uiSchema,
+ widgets,
+ });
expect(node.querySelectorAll(".custom")).to.have.length.of(1);
});
@@ -335,7 +359,11 @@ describe("uiSchema", () => {
};
it("should render a custom widget with options", () => {
- const { node } = createFormComponent({ schema, uiSchema, widgets });
+ const { node } = createFormComponent({
+ schema,
+ uiSchema,
+ widgets,
+ });
expect(node.querySelectorAll(".custom")).to.have.length.of(1);
});
@@ -1766,7 +1794,11 @@ describe("uiSchema", () => {
};
const formData = ["a", "b"];
- let rendered = createFormComponent({ schema, uiSchema, formData });
+ let rendered = createFormComponent({
+ schema,
+ uiSchema,
+ formData,
+ });
node = rendered.node;
});
@@ -2050,7 +2082,11 @@ describe("uiSchema", () => {
};
const formData = ["a", "b"];
- let rendered = createFormComponent({ schema, uiSchema, formData });
+ let rendered = createFormComponent({
+ schema,
+ uiSchema,
+ formData,
+ });
node = rendered.node;
});
diff --git a/test/utils_test.js b/test/utils_test.js
index 1e3b0141e3..2ada075147 100644
--- a/test/utils_test.js
+++ b/test/utils_test.js
@@ -145,7 +145,14 @@ describe("utils", () => {
properties: {
level1: {
type: "object",
- default: { level2: { leaf1: 1, leaf2: 1, leaf3: 1, leaf4: 1 } },
+ default: {
+ level2: {
+ leaf1: 1,
+ leaf2: 1,
+ leaf3: 1,
+ leaf4: 1,
+ },
+ },
properties: {
level2: {
type: "object",
@@ -166,9 +173,13 @@ describe("utils", () => {
},
};
expect(
- getDefaultFormState(schema, { level1: { level2: { leaf4: 4 } } })
+ getDefaultFormState(schema, {
+ level1: { level2: { leaf4: 4 } },
+ })
).eql({
- level1: { level2: { leaf1: 1, leaf2: 2, leaf3: 3, leaf4: 4 } },
+ level1: {
+ level2: { leaf1: 1, leaf2: 2, leaf3: 3, leaf4: 4 },
+ },
});
});
@@ -183,7 +194,9 @@ describe("utils", () => {
},
},
};
- expect(getDefaultFormState(schema, {})).eql({ level1: [1, 2, 3] });
+ expect(getDefaultFormState(schema, {})).eql({
+ level1: [1, 2, 3],
+ });
});
it("should use parent defaults for ArrayFields if declared in parent", () => {
@@ -197,7 +210,9 @@ describe("utils", () => {
},
},
};
- expect(getDefaultFormState(schema, {})).eql({ level1: [1, 2, 3] });
+ expect(getDefaultFormState(schema, {})).eql({
+ level1: [1, 2, 3],
+ });
});
it("should map item defaults to fixed array default", () => {
@@ -318,7 +333,10 @@ describe("utils", () => {
describe("uniqueItems is true", () => {
describe("schema items enum is an array", () => {
it("should be true", () => {
- let schema = { items: { enum: ["foo", "bar"] }, uniqueItems: true };
+ let schema = {
+ items: { enum: ["foo", "bar"] },
+ uniqueItems: true,
+ };
expect(isMultiSelect(schema)).to.be.true;
});
});
@@ -359,13 +377,18 @@ describe("utils", () => {
items: { $ref: "#/definitions/FooItem" },
uniqueItems: true,
};
- const definitions = { FooItem: { type: "string", enum: ["foo"] } };
+ const definitions = {
+ FooItem: { type: "string", enum: ["foo"] },
+ };
expect(isMultiSelect(schema, definitions)).to.be.true;
});
});
it("should be false if uniqueItems is false", () => {
- const schema = { items: { enum: ["foo", "bar"] }, uniqueItems: false };
+ const schema = {
+ items: { enum: ["foo", "bar"] },
+ uniqueItems: false,
+ };
expect(isMultiSelect(schema)).to.be.false;
});
});
@@ -450,7 +473,9 @@ describe("utils", () => {
const obj1 = { a: { b: [1] } };
const obj2 = { a: { b: [2] } };
- expect(mergeObjects(obj1, obj2, true)).eql({ a: { b: [1, 2] } });
+ expect(mergeObjects(obj1, obj2, true)).eql({
+ a: { b: [1, 2] },
+ });
});
});
});