-
Notifications
You must be signed in to change notification settings - Fork 15
Theming
One particularity of react-jsonschema-form is to separate "data structure" from "ui structure".
<ApolloForm>
tries to simplify the logic around this by enabling "theming".
When configuring a Form component, you can pass a optional theme
argument:
interface ApolloFormConfigureTheme {
templates?: ApolloFormTheme['templates'];
widgets?: ApolloFormTheme['widgets'];
fields?: ApolloFormTheme['fields'];
renderers?: Partial<ApolloFormTheme['renderers']>;
}
(if fields
, templates
, widgets
are unknown to you, please read Understanding "react jsonschema form" in 2 minutes
)
Theme allows you to override rendering of core components: fields, templates and renderers. Or add some custom widgets for complex properties or types.
You will find all default fields
, templates
and widgets
react-jsonschema-form
repo
With no theming, our "Todo Form" looks like this:
import { Button, Input, Checkbox, Header, Form, Message } from 'semantic-ui-react';
const ErrorList: ErrorListComponent = p => (
<Message
error={true}
visible={true}
header="There was some errors"
list={p.errors.map(e => e.message)}
/>
);
const theme: ApolloFormConfigureTheme = {
templates: {
FieldTemplate: props => {
const { classNames, help, description, errors, children, rawErrors, label } = props;
return (
<Form.Field>
<label>{label}{props.required && '*'}</label>
{children}
<span>{description}</span>
</Form.Field>
);
},
ObjectFieldTemplate: props => {
return (
<div>
{props.properties.map(p => p.content)}
</div>
);
}
},
fields: {
StringField: (p: FieldProps) => (
<Input value={p.formData} onChange={
(e: React.SyntheticEvent<HTMLInputElement>) => p.onChange(e.currentTarget.value)
} />
),
BooleanField: (p: FieldProps) => (
<Checkbox label={p.title} checked={p.formData} onChange={
(e: React.SyntheticEvent<HTMLInputElement>, data: object) => {
// tslint:disable-next-line:no-any
p.onChange((data as any).checked);
}
} />
)
},
renderers: {
saveButton: p => (
<Button onClick={p.save} primary={true}>
Save
</Button>
),
cancelButton: p => (
<Button onClick={p.cancel}>
Cancel
</Button>
),
header: p => (
<Header as="h1">{p.title}</Header>
)
}
};
Just pass the theme
to configure
and pass ErrorList
to your form ui={}
prop.
Now, our form is shiny:
As seen in Understanding "react jsonschema form" in 2 minutes
), fields are responsible of instanciating a widget component if ui:widget
is present in the field uiSchema
.
If you define a new Field
component, remember to check if a ui:widget
is specified.
If so, just fallback to the original field component that will instanciate the widget properly.
Example
import StringField from 'react-jsonschema-form/lib/components/fields/StringField';
export const MyStringField = (props: FieldProps) => {
const uiSchema = props.uiSchema;
return (
// render original StringField if 'ui:widget'
uiSchema && uiSchema['ui:widget'] ?
<StringField {...props} /> :
<MyInput
type="text"
value={props.formData}
name={props.name}
onChange={props.onChange}
/>
);
};