diff --git a/src/components/Form.js b/src/components/Form.js index 98fed2f7ee..fd15052332 100644 --- a/src/components/Form.js +++ b/src/components/Form.js @@ -79,11 +79,12 @@ export default class Form extends Component { return { SchemaField: this.props.SchemaField || SchemaField, TitleField: this.props.TitleField || TitleField, + widgets: this.props.widgets || {}, }; } render() { - const {children, schema, uiSchema} = this.props; + const {children, schema, uiSchema, widgets} = this.props; const {formData} = this.state; const registry = this.getRegistry(); const _SchemaField = registry.SchemaField; @@ -94,6 +95,7 @@ export default class Form extends Component { schema={schema} uiSchema={uiSchema} formData={formData} + widgets={widgets} onChange={this.onChange.bind(this)} registry={registry}/> { children ? children :

} @@ -107,6 +109,7 @@ if (process.env.NODE_ENV !== "production") { schema: PropTypes.object.isRequired, uiSchema: PropTypes.object, formData: PropTypes.any, + widgets: PropTypes.object, onChange: PropTypes.func, onError: PropTypes.func, onSubmit: PropTypes.func, diff --git a/src/components/fields/ArrayField.js b/src/components/fields/ArrayField.js index 837aeea7a1..b231c7e2eb 100644 --- a/src/components/fields/ArrayField.js +++ b/src/components/fields/ArrayField.js @@ -69,7 +69,7 @@ class ArrayField extends Component { const {schema, uiSchema, name} = this.props; const title = schema.title || name; const {items} = this.state; - const SchemaField = this.props.registry.SchemaField; + const {SchemaField} = this.props.registry; if (isMultiSelect(schema)) { return ( ; } return ; diff --git a/src/components/fields/ObjectField.js b/src/components/fields/ObjectField.js index 7b12f047d5..4bcc77512c 100644 --- a/src/components/fields/ObjectField.js +++ b/src/components/fields/ObjectField.js @@ -67,7 +67,7 @@ class ObjectField extends Component { formData={this.state[name]} onChange={this.onChange.bind(this, name)} registry={this.props.registry} /> - ); + ); }) } ); diff --git a/src/components/fields/SchemaField.js b/src/components/fields/SchemaField.js index ffa3f2399a..491accf131 100644 --- a/src/components/fields/SchemaField.js +++ b/src/components/fields/SchemaField.js @@ -98,6 +98,7 @@ if (process.env.NODE_ENV !== "production") { SchemaField.propTypes = { schema: PropTypes.object.isRequired, uiSchema: PropTypes.object, + registry: PropTypes.object, }; } diff --git a/src/components/fields/StringField.js b/src/components/fields/StringField.js index d496a34a93..833dce108d 100644 --- a/src/components/fields/StringField.js +++ b/src/components/fields/StringField.js @@ -5,7 +5,8 @@ import TextWidget from "./../widgets/TextWidget"; import SelectWidget from "./../widgets/SelectWidget"; -function StringField({schema, name, uiSchema, formData, required, onChange}) { +function StringField(props) { + const {schema, widgets, name, uiSchema, formData, required, onChange} = props; const {title, description} = schema; const widget = uiSchema["ui:widget"]; const commonProps = { @@ -19,13 +20,13 @@ function StringField({schema, name, uiSchema, formData, required, onChange}) { }; if (Array.isArray(schema.enum)) { if (widget) { - const Widget = getAlternativeWidget(schema.type, widget); + const Widget = getAlternativeWidget(schema.type, widget, widgets); return ; } return ; } if (widget) { - const Widget = getAlternativeWidget(schema.type, widget); + const Widget = getAlternativeWidget(schema.type, widget, widgets); return ; } return ; diff --git a/src/utils.js b/src/utils.js index 6ad084ce30..6513f22d38 100644 --- a/src/utils.js +++ b/src/utils.js @@ -43,13 +43,16 @@ export function defaultFieldValue(formData, schema) { return formData === null ? defaultTypeValue(schema.type) : formData; } -export function getAlternativeWidget(type, widget) { +export function getAlternativeWidget(type, widget, registeredWidgets={}) { if (typeof widget === "function") { return widget; } if (typeof widget !== "string") { throw new Error(`Unsupported widget definition: ${typeof widget}`); } + if (widget in registeredWidgets) { + return registeredWidgets[widget]; + } if (!altWidgetMap.hasOwnProperty(type)) { throw new Error(`No alternative widget for type ${type}`); } diff --git a/test/index_test.js b/test/index_test.js index fd31aae7ab..0a49186981 100644 --- a/test/index_test.js +++ b/test/index_test.js @@ -91,6 +91,26 @@ describe("Form", () => { }); }); + describe("Custom widgets", () => { + it("should support custom StringField widgets", () => { + const schema = {type: "string"}; + const uiSchema = {"ui:widget": "foo"}; + const foo = () =>
yo
; + const {node} = createComponent({schema, uiSchema, widgets: {foo}}); + + expect(node.querySelector("#custom").textContent).eql("yo"); + }); + + it("should support custom BooleanField widgets", () => { + const schema = {type: "boolean"}; + const uiSchema = {"ui:widget": "foo"}; + const foo = () =>
yo
; + const {node} = createComponent({schema, uiSchema, widgets: {foo}}); + + expect(node.querySelector("#custom").textContent).eql("yo"); + }); + }); + describe("Object fields ordering", () => { const schema = { type: "object",