Skip to content

Instantly share code, notes, and snippets.

@zbyte64
Created March 25, 2016 01:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zbyte64/67a06857d236e42e852d to your computer and use it in GitHub Desktop.
Save zbyte64/67a06857d236e42e852d to your computer and use it in GitHub Desktop.
Bootstrap theme for react-jsonschema-form
import React, { PropTypes } from "react";
import { isMultiSelect, retrieveSchema } from "zbyte64/react-jsonschema-form/src/utils";
import ArrayField from "zbyte64/react-jsonschema-form/src/components/fields/ArrayField";
import BooleanField from "zbyte64/react-jsonschema-form/src/components/fields/BooleanField";
import NumberField from "zbyte64/react-jsonschema-form/src/components/fields/NumberField";
import ObjectField from "zbyte64/react-jsonschema-form/src/components/fields/ObjectField";
import StringField from "zbyte64/react-jsonschema-form/src/components/fields/StringField";
import UnsupportedField from "zbyte64/react-jsonschema-form/src/components/fields/UnsupportedField";
const REQUIRED_FIELD_SYMBOL = "*";
const COMPONENT_TYPES = {
"array": ArrayField,
"boolean": BooleanField,
"date-time": StringField,
"integer": NumberField,
"number": NumberField,
"object": ObjectField,
"string": StringField,
};
function getFieldComponent(schema, uiSchema, fields) {
const field = uiSchema["ui:field"];
if (typeof field === "function") {
return field;
}
if (typeof field === "string" && field in fields) {
return fields[field];
}
return COMPONENT_TYPES[schema.type] || UnsupportedField;
}
function getLabel(label, required) {
if (!label) {
return null;
}
if (required) {
return label + REQUIRED_FIELD_SYMBOL;
}
return label;
}
function ErrorList({errors}) {
return (
<div className="error-detail">{
(errors || []).map((error, index) => {
return <li key={index}>{error}</li>;
})
}</div>
);
}
function Wrapper(props) {
const {type, classNames, errorSchema, displayLabel, label, required, children} = props;
const {errors} = errorSchema;
const isError = errors && errors.length > 0;
const classList = [
"form-group",
"field",
`field-${type}`,
isError ? "has-error" : "",
classNames,
].join(" ").trim();
return (
<div className={classList}>
{ displayLabel ? <label>{getLabel(label, required)}</label> : null}
{children}
{isError ? <ErrorList errors={errors} /> : <div/>}
</div>
);
}
if (process.env.NODE_ENV !== "production") {
Wrapper.propTypes = {
type: PropTypes.string.isRequired,
label: PropTypes.string,
required: PropTypes.bool,
displayLabel: PropTypes.bool,
children: React.PropTypes.node.isRequired,
classNames: React.PropTypes.string,
};
}
Wrapper.defaultProps = {
classNames: ""
};
function SchemaBootstrapField(props) {
const {uiSchema, errorSchema, name, required, registry} = props;
const {definitions, fields} = registry;
const schema = retrieveSchema(props.schema, definitions);
const FieldComponent = getFieldComponent(schema, uiSchema, fields);
if (Object.keys(schema).length === 0) {
return <div />;
}
let displayLabel = true;
if (schema.type === "array") {
displayLabel = isMultiSelect(schema);
}
if (schema.type === "object") {
displayLabel = false;
}
return (
<Wrapper
label={schema.title || name}
errorSchema={errorSchema}
required={required}
type={schema.type}
displayLabel={displayLabel}
classNames={uiSchema.classNames}>
<FieldComponent {...props} className="form-control" />
</Wrapper>
);
}
SchemaBootstrapField.defaultProps = {
uiSchema: {},
errorSchema: {},
};
if (process.env.NODE_ENV !== "production") {
SchemaBootstrapField.propTypes = {
schema: PropTypes.object.isRequired,
uiSchema: PropTypes.object,
formData: PropTypes.any,
errorSchema: PropTypes.object,
registry: PropTypes.shape({
widgets: PropTypes.objectOf(PropTypes.func).isRequired,
fields: PropTypes.objectOf(PropTypes.func).isRequired,
})
};
}
export default SchemaBootstrapField;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment