Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Theming

Charly POLY edited this page Jun 6, 2018 · 5 revisions

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.


Build our custom theme with Semantic UI

You will find all default fields, templates and widgets react-jsonschema-form repo

With no theming, our "Todo Form" looks like this:

https://s3.eu-west-2.amazonaws.com/github-oss/react-apollo-form/getting-started-todo-form.png

Our Semantic UI theme:

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:

https://s3.eu-west-2.amazonaws.com/github-oss/react-apollo-form/theming-semantic-ui.png


⚠️ Warning, note on Field overrides ⚠️

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}
            />
    );
};
Clone this wiki locally
Morty Proxy This is a proxified and sanitized view of the page, visit original site.