Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add idPrefix option for oneOf #883

Merged
merged 1 commit into from
Apr 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -84,19 +87,22 @@ 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)
- [Coding style](#coding-style)
- [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)

---
Expand Down Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the apostrophe here was correct ("the text input belonging to widgets").


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).

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change? It seems like this still corresponds to $prettierOptions.

"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",
Expand Down
2 changes: 2 additions & 0 deletions src/components/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export default class Form extends Component {
children,
safeRenderCompletion,
id,
idPrefix,
className,
name,
method,
Expand Down Expand Up @@ -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}
Expand Down
5 changes: 4 additions & 1 deletion src/components/fields/ArrayField.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ function DefaultArrayItem(props) {
<div className="col-xs-3 array-item-toolbox">
<div
className="btn-group"
style={{ display: "flex", justifyContent: "space-around" }}>
style={{
display: "flex",
justifyContent: "space-around",
}}>
{(props.hasMoveUp || props.hasMoveDown) && (
<IconBtn
icon="arrow-up"
Expand Down
2 changes: 2 additions & 0 deletions src/components/fields/ObjectField.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class ObjectField extends Component {
required,
disabled,
readonly,
idPrefix,
onBlur,
onFocus,
registry = getDefaultRegistry(),
Expand Down Expand Up @@ -117,6 +118,7 @@ class ObjectField extends Component {
uiSchema={uiSchema[name]}
errorSchema={errorSchema[name]}
idSchema={idSchema[name]}
idPrefix={idPrefix}
formData={formData[name]}
onChange={this.onPropertyChange(name)}
onBlur={onBlur}
Expand Down
10 changes: 9 additions & 1 deletion src/components/fields/SchemaField.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import PropTypes from "prop-types";
import {
isMultiSelect,
retrieveSchema,
toIdSchema,
getDefaultRegistry,
mergeObjects,
getUiOptions,
isFilesArray,
deepEquals,
Expand Down Expand Up @@ -153,7 +155,7 @@ function SchemaFieldRender(props) {
uiSchema,
formData,
errorSchema,
idSchema,
idPrefix,
name,
required,
registry = getDefaultRegistry(),
Expand All @@ -164,7 +166,12 @@ function SchemaFieldRender(props) {
formContext,
FieldTemplate = DefaultTemplate,
} = registry;
let idSchema = props.idSchema;
const schema = retrieveSchema(props.schema, definitions, formData);
idSchema = mergeObjects(
toIdSchema(schema, null, definitions, formData, idPrefix),
idSchema
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to generate another idSchema at this level? What's wrong with the one that was generated for us at toplevel? That one was generated from the resolved schema, so it should have the oneOf accounted for, shouldn't it?

I'm a little concerned that we're restarting with id=null here -- won't this lose our place in the hierarchy?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question here, removing this piece of code doesn't seem to break any test.

const FieldComponent = getFieldComponent(schema, uiSchema, idSchema, fields);
const { DescriptionField } = fields;
const disabled = Boolean(props.disabled || uiSchema["ui:disabled"]);
Expand Down Expand Up @@ -199,6 +206,7 @@ function SchemaFieldRender(props) {
const field = (
<FieldComponent
{...props}
idSchema={idSchema}
schema={schema}
uiSchema={{ ...uiSchema, classNames: undefined }}
disabled={disabled}
Expand Down
4 changes: 4 additions & 0 deletions src/components/widgets/BaseInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import PropTypes from "prop-types";
function BaseInput(props) {
// Note: since React 15.2.0 we can't forward unknown element attributes, so we
// exclude the "options" and "schema" ones here.
if (!props.id) {
console.log("No id for", props);
throw new Error(`no id for props ${JSON.stringify(props)}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better for this code not to come between the comment and the code the comment describes.

const {
value,
readonly,
Expand Down
15 changes: 12 additions & 3 deletions test/ArrayField_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,10 @@ describe("ArrayField", () => {
},
},
};
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");
Expand Down Expand Up @@ -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 },
Expand Down Expand Up @@ -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]"
);
Expand Down
110 changes: 103 additions & 7 deletions test/Form_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(<Form schema={schema} idPrefix="rjsf" />);
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(<Form schema={schema} idPrefix="rjsf" />);
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",
Expand Down Expand Up @@ -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" },
Expand Down Expand Up @@ -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" },
Expand Down Expand Up @@ -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"],
},
});
});

Expand Down Expand Up @@ -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"],
},
},
});
});
Expand Down Expand Up @@ -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"],
},
},
},
});
Expand Down
4 changes: 3 additions & 1 deletion test/NumberField_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down
Loading