Skip to main content
Version: v4

Customizing material-ui fields and widgets

Unlike most other themes, the material-ui theme supports the two distinct version of Material UI (versions 4 and 5) side-by-side. Material UI version 4 is provided by the scoped packages under @material-ui and version 5 is provided by the scoped packages under @mui.

The components used by @rjsf/material-ui for Material UI version 4 and version 5 have identical names and props. As a result, all of the fields and widgets provided by the theme are identical as well. The trick to making the two versions function side-by-side, was done by creating a React context, MuiComponentContext, that provides the appropriate set of components used by theme, for the particular scoped package.

In addition to this context, a custom hook, useMuiComponent(), is provided to allow quick access to that component set.

Example of a custom widget for @rjsf/material-ui

Here is an update to the MyCustomWidget for the material-ui theme

const schema = {
type: "string"
};

import { useMuiComponent } from '@rjsf/material-ui/v4';

function MyCustomWidget(props) {
const { options, ...otherProps } = props;
const { color, backgroundColor } = options;
const { TextInput } = useMuiComponent();
return <TextInput {...otherProps} style={{ color, backgroundColor }} />;
}

MyCustomWidget.defaultProps = {
options: {
color: "red"
}
};

const uiSchema = {
"ui:widget": MyCustomWidget,
"ui:options": {
backgroundColor: "yellow"
}
};

// renders red on yellow input
render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

Example of a custom field for @rjsf/material-ui

Here is an update to the GeoPosition for the material-ui theme

const schema = {
type: "object",
required: ["lat", "lon"],
properties: {
lat: { type: "number"},
lon: { type: "number" }
}
};

import { useMuiComponent } from '@rjsf/material-ui/v4';

// Define a custom component for handling the root position object
function GeoPosition(props) {
const { lat, lon } = props.formData;
const { Box, TextInput } = useMuiComponent();

const onChangeLat = (event) => {
const { target: { value } } = event;
const newData = { ...props.formData, lat: value };
props.onChange(newData);
};

const onChangeLon = (event) => {
const { target: { value } } = event;
const newData = { ...props.formData, lon: value };
props.onChange(newData);
};

return (
<Box>
<TextInput type="number" value={lat} onChange={onChangeLat} />
<TextInput type="number" value={lon} onChange={onChangeLon} />
</Box>
);
}

// Define the custom field component to use for the root object
const uiSchema = { "ui:field": "geo" };

// Define the custom field components to register; here our "geo"
// custom field component
const fields = { geo: GeoPosition };

// Render the form with all the properties we just defined passed
// as props
render((
<Form
schema={schema}
uiSchema={uiSchema}
fields={fields} />
), document.getElementById("app"));