diff --git a/docs/404.html b/docs/404.html index fb4a3f45dc..7fc9a3ba24 100644 --- a/docs/404.html +++ b/docs/404.html @@ -4,13 +4,13 @@ Page Not Found | react-jsonschema-form - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/docs/advanced-customization/custom-templates/index.html b/docs/advanced-customization/custom-templates/index.html index 26d0528b84..f9bb2f03e1 100644 --- a/docs/advanced-customization/custom-templates/index.html +++ b/docs/advanced-customization/custom-templates/index.html @@ -4,7 +4,7 @@ Custom Templates | react-jsonschema-form - + @@ -45,7 +45,7 @@ You can customize the MoveUpButton to render something other than the icon button that is provided by a theme as follows:

import React from 'react';
import { IconButtonProps, RJSFSchema } from '@rjsf/utils';
import { FormattedMessage } from 'react-intl';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'string',
};

function MoveUpButton(props: IconButtonProps) {
const { icon, iconType, ...btnProps } = props;
return (
<button {...btnProps}>
{icon} <FormattedMessage defaultMessage='Move Up' />
</button>
);
}

render(
<Form schema={schema} validator={validator} templates={{ ButtonTemplates: { MoveUpButton } }} />,
document.getElementById('app')
);

RemoveButton

The RemoveButton is used to render a remove action on a Form for both a existing additionalProperties element for an object or an existing element in an array. You can customize the RemoveButton to render something other than the icon button that is provided by a theme as follows:

import React from 'react';
import { IconButtonProps, RJSFSchema } from '@rjsf/utils';
import { FormattedMessage } from 'react-intl';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'string',
};

function RemoveButton(props: IconButtonProps) {
const { icon, iconType, ...btnProps } = props;
return (
<button {...btnProps}>
{icon} <FormattedMessage defaultMessage='Remove' />
</button>
);
}

render(
<Form schema={schema} validator={validator} templates={{ ButtonTemplates: { RemoveButton } }} />,
document.getElementById('app')
);

SubmitButton

The SubmitButton is already very customizable via the UISchemaSubmitButtonOptions capabilities in the uiSchema but it can also be fully customized as you see fit.

NOTE: However you choose to implement this, making it something other than a submit type button may result in the Form not submitting when pressed. You could also choose to provide your own submit button as the children prop of the Form should you so choose.

import React from 'react';
import { getSubmitButtonOptions, RJSFSchema, SubmitButtonProps } from '@rjsf/utils';
import { FormattedMessage } from 'react-intl';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'string',
};

function SubmitButton(props: SubmitButtonProps) {
const { uiSchema } = props;
const { norender } = getSubmitButtonOptions(uiSchema);
if (norender) {
return null;
}
return (
<button type='submit'>
<FormattedMessage defaultMessage='Okay' />
</button>
);
}

render(
<Form schema={schema} validator={validator} templates={{ ButtonTemplates: { SubmitButton } }} />,
document.getElementById('app')
);

The following prop is passed to a SubmitButton:

- + \ No newline at end of file diff --git a/docs/advanced-customization/custom-themes/index.html b/docs/advanced-customization/custom-themes/index.html index 703f39a70b..103120ee80 100644 --- a/docs/advanced-customization/custom-themes/index.html +++ b/docs/advanced-customization/custom-themes/index.html @@ -4,7 +4,7 @@ Custom Themes | react-jsonschema-form - + @@ -16,7 +16,7 @@ Thus, for each default widget or field not specified/overridden, the themed-form will rely on the defaults from the rjsf Form. Note that you are not required to pass in either custom widgets, fields or templates when using the custom-themed HOC component; you can essentially redefine the default Form by simply doing const Form = withTheme({});.

Widgets and fields

widgets and fields should be in the same format as shown here.

Example theme with custom widget:

import { WidgetProps, RegistryWidgetsType } from '@rjsf/utils';
import { ThemeProps } from '@rjsf/core';

const MyCustomWidget = (props: WidgetProps) => {
return (
<input
type='text'
className='custom'
value={props.value}
required={props.required}
onChange={(event) => props.onChange(event.target.value)}
/>
);
};

const myWidgets: RegistryWidgetsType = {
myCustomWidget: MyCustomWidget,
};

const ThemeObject: ThemeProps = { widgets: myWidgets };
export default ThemeObject;

The above can be similarly done for fields and templates.

Templates

Each template should be passed into the theme object via the templates object just as you would into the rjsf Form component. Here is an example of how to use a custom ArrayFieldTemplate and ErrorListTemplate in the theme object:

import { ArrayFieldTemplateProps, ErrorListProps } from '@rjsf/utils';
import { ThemeProps } from '@rjsf/core';

function MyArrayFieldTemplate(props: ArrayFieldTemplateProps) {
return (
<div>
{props.items.map((element) => element.children)}
{props.canAdd && <button type='button' onClick={props.onAddClick}></button>}
</div>
);
}

function MyErrorListTemplate(props: ErrorListProps) {
const { errors } = props;
return (
<ul>
{errors.map((error) => (
<li key={error.stack}>{error.stack}</li>
))}
</ul>
);
}

const ThemeObject: ThemeProps = {
templates: {
ArrayFieldTemplate: MyArrayFieldTemplate,
ErrorListTemplate: MyErrorListTemplate,
},
widgets: myWidgets,
};

export default ThemeObject;

Overriding other Form props

Just as the theme can override widgets, fields, any of the templates, and set default values to properties like showErrorList, you can do the same with the instance of the withTheme() Form component.

import { ThemeProps } from '@rjsf/core';

const ThemeObject: ThemeProps = {
templates: {
ArrayFieldTemplate: MyArrayFieldTemplate,
},
fields: myFields,
showErrorList: false,
widgets: myWidgets,
};

Thus, the user has higher priority than the withTheme HOC, and the theme has higher priority than the default values of the rjsf Form component (User > Theme > Defaults).

- + \ No newline at end of file diff --git a/docs/advanced-customization/custom-widgets-fields/index.html b/docs/advanced-customization/custom-widgets-fields/index.html index 5e9084e7a2..cf76ed6549 100644 --- a/docs/advanced-customization/custom-widgets-fields/index.html +++ b/docs/advanced-customization/custom-widgets-fields/index.html @@ -4,7 +4,7 @@ Custom Widgets and Fields | react-jsonschema-form - + @@ -13,7 +13,7 @@ The way to do this varies based upon whether you are using core or some other theme (such as mui).

Here is an example of modifying the SelectWidget to change the ordering of enumOptions:

import { WidgetProps } from '@rjsf/utils';
import { getDefaultRegistry } from '@rjsf/core';
import { Widgets } from '@rjsf/mui';

import myOptionsOrderFunction from './myOptionsOrderFunction';

const {
widgets: { SelectWidget },
} = getDefaultRegistry(); // To get widgets from core
// const { SelectWidget } = Widgets; // To get widgets from a theme do this

function MySelectWidget(props: WidgetProps) {
const { options } = props;
let { enumOptions } = options;
// Reorder the `enumOptions` however you want
enumOptions = myOptionsOrderFunction(enumOptions);
return <SelectWidget {...props} options={{ ...options, enumOptions }} />;
}

Custom field components

You can provide your own field components to a uiSchema for basically any json schema data type, by specifying a ui:field property.

For example, let's create and register a dumb geo component handling a latitude and a longitude:

import { RJSFSchema, UiSchema, FieldProps, RegistryFieldsType } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

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

// Define a custom component for handling the root position object
class GeoPosition extends React.Component<FieldProps> {
constructor(props: FieldProps) {
super(props);
this.state = { ...props.formData };
}

onChange(name) {
return (event) => {
this.setState(
{
[name]: parseFloat(event.target.value),
},
() => this.props.onChange(this.state)
);
};
}

render() {
const { lat, lon } = this.state;
return (
<div>
<input type='number' value={lat} onChange={this.onChange('lat')} />
<input type='number' value={lon} onChange={this.onChange('lon')} />
</div>
);
}
}

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

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

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

Note: Registered fields can be reused across the entire schema.

Field props

A field component will always be passed the following props:

The registry object

The registry is an object containing the registered core, theme and custom fields and widgets as well as the root schema, form context, schema utils.

The registry is passed down the component tree, so you can access it from your custom field, custom widget, custom template and SchemaField components.

Custom SchemaField

Warning: This is a powerful feature as you can override the whole form behavior and easily mess it up. Handle with care.

You can provide your own implementation of the SchemaField base React component for rendering any JSONSchema field type, including objects and arrays. This is useful when you want to augment a given field type with supplementary powers.

To proceed so, pass a fields object having a SchemaField property to your Form component; here's an example:

import { RJSFSchema, FieldProps, RegistryFieldsType } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const CustomSchemaField = function (props: FieldProps) {
return (
<div id='custom'>
<p>Yeah, I'm pretty dumb.</p>
<div>My props are: {JSON.stringify(props)}</div>
</div>
);
};

const fields: RegistryFieldsType = {
SchemaField: CustomSchemaField,
};

const schema: RJSFSchema = {
type: 'string',
};

render(<Form schema={schema} validator={validator} fields={fields} />, document.getElementById('app'));

If you're curious how this could ever be useful, have a look at the Kinto formbuilder repository to see how it's used to provide editing capabilities to any form field.

Props passed to a custom SchemaField are the same as the ones passed to a custom field.

Custom ArraySchemaField

Everything that was mentioned above for a Custom SchemaField applies, but this is only used to render the Array item children that are then passed to the ArrayFieldItemTemplate. By default, ArraySchemaField is not actually implemented in the fields list since ArrayField falls back to SchemaField if ArraySchemaField is not provided. If you want to customize how the individual items for an array are rendered, provide your implementation of ArraySchemaField as a fields override.

import { RJSFSchema, UiSchema, FieldProps, RegistryFieldsType } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const CustomArraySchemaField = function (props: FieldProps) {
const { index, registry } = props;
const { SchemaField } = registry.fields;
const name = `Index ${index}`;
return <SchemaField {...props} name={name} />;
};

const fields: RegistryFieldsType = {
ArraySchemaField: CustomArraySchemaField,
};

const schema: RJSFSchema = {
type: 'string',
};

render(<Form schema={schema} validator={validator} fields={fields} />, document.getElementById('app'));

Custom Field by Id

Warning: This is a powerful feature as you can override the whole form behavior and easily mess it up. Handle with care.

You can provide your own implementation of the field component that applies to any schema or sub-schema based on the schema's $id value. This is useful when your custom field should be conditionally applied based on the schema rather than the property name or data type.

To provide a custom field in this way, the fields prop should be an object which contains a key that matches the $id value of the schema which should have a custom field; here's an example:

import { RJSFSchema, FieldProps, RegistryFieldsType } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const CustomIdField = function (props: FieldProps) {
return (
<div id='custom'>
<p>Yeah, I'm pretty dumb.</p>
<div>My props are: {JSON.stringify(props)}</div>
</div>
);
};

const fields: RegistryFieldsType = {
'/schemas/my-id': CustomIdField,
};

const schema: RJSFSchema = {
$id: '/schemas/my-id',
type: 'string',
};

render(<Form schema={schema} validator={validator} fields={fields} />, document.getElementById('app'));

Wrapping an existing field to customize it

Sometimes you just need to customize the properties that are passed to an existing field.

Here is an example of wrapping the ObjectField to tweak the onChange handler to look for a specific kind of bad data:

import { useCallback } from 'react';
import { FieldProps } from '@rjsf/utils';
import { getDefaultRegistry } from '@rjsf/core';

import checkBadData from './checkBadData';

const {
fields: { ObjectField },
} = getDefaultRegistry();

function MyObjectField(props: FieldProps) {
const { onChange } = props;
const onChangeHandler = useCallback(
(newFormData: T | undefined, es?: ErrorSchema<T>, id?: string) => {
let data = newFormData;
let error = es;
if (checkBadData(newFormData)) {
// Format the `error` and fix the `data` here
}
onChange(data, error, id);
},
[onChange]
);
return <ObjectField {...props} onChange={onChangeHandler} />;
}
- + \ No newline at end of file diff --git a/docs/advanced-customization/index.html b/docs/advanced-customization/index.html index 4a03e065fd..a06b33fab9 100644 --- a/docs/advanced-customization/index.html +++ b/docs/advanced-customization/index.html @@ -4,13 +4,13 @@ Advanced Customization | react-jsonschema-form - +
Skip to main content
- + \ No newline at end of file diff --git a/docs/advanced-customization/internals/index.html b/docs/advanced-customization/internals/index.html index 56a340a0a2..f36b8b63aa 100644 --- a/docs/advanced-customization/internals/index.html +++ b/docs/advanced-customization/internals/index.html @@ -4,7 +4,7 @@ Internals | react-jsonschema-form - + @@ -12,7 +12,7 @@
Skip to main content
Version: v5

Internals

Miscellaneous internals of react-jsonschema-form are listed here.

JSON Schema supporting status

This component follows JSON Schema specs. We currently support JSON Schema-07 by default, but we also support other JSON schema versions through the custom schema validation feature. Due to the limitation of form widgets, there are some exceptions as follows:

  • additionalItems keyword for arrays

    This keyword works when items is an array. additionalItems: true is not supported because there's no widget to represent an item of any type. In this case it will be treated as no additional items allowed. additionalItems being a valid schema is supported.

  • anyOf, allOf, and oneOf, or multiple types (i.e. "type": ["string", "array"])

    The anyOf and oneOf keywords are supported; however, properties declared inside the anyOf/oneOf should not overlap with properties "outside" of the anyOf/oneOf.

    You can also use oneOf with schema dependencies to dynamically add schema properties based on input data.

    The allOf keyword is supported; it uses json-schema-merge-allof to merge subschemas to render the final combined schema in the form. When these subschemas are incompatible, though (or if the library has an error merging it), the allOf keyword is dropped from the schema.

  • "additionalProperties":false produces incorrect schemas when used with schema dependencies. This library does not remove extra properties, which causes validation to fail. It is recommended to avoid setting "additionalProperties":false when you use schema dependencies. See #848 #902 #992

Handling of schema defaults

This library automatically fills default values defined in the JSON Schema as initial values in your form. This also works for complex structures in the schema. If a field has a default defined, it should always appear as default value in form. This also works when using schema dependencies.

Since there is a complex interaction between any supplied original form data and any injected defaults, this library tries to do the injection in a way which keeps the original intention of the original form data.

Check out the defaults example on the live playground to see this in action.

Merging of defaults into the form data

There are three different cases which need to be considered for the merging. Objects, arrays and scalar values. This library always deeply merges any defaults with the existing form data for objects.

This are the rules which are used when injecting the defaults:

  • When there is a scalar in the form data, nothing is changed.
  • When the value is undefined in the form data, the default is created in the form data.
  • When the value is an object in the form data, the defaults are deeply merged into the form data, using the rules defined here for the deep merge.
  • Then the value is an array in the form data, defaults are only injected in existing array items. No new array items will be created, even if the schema has minItems or additional items defined.

Merging of defaults within the schema

In the schema itself, defaults of parent elements are propagated into children. So when you have a schema which defines a deeply nested object as default, these defaults will be applied to children of the current node. This also merges objects defined at different levels together with the "deeper" not having precedence. If the parent node defines properties, which are not defined in the child, they will be merged so that the default for the child will be the merged defaults of parent and child.

For arrays this is not the case. Defining an array, when a parent also defines an array, will be overwritten. This is only true when arrays are used in the same level, for objects within these arrays, they will be deeply merged again.

Custom array field buttons

The ArrayField component provides a UI to add, copy, remove and reorder array items, and these buttons use Bootstrap glyphicons. If you don't use glyphicons but still want to provide your own icons or texts for these buttons, you can easily do so using CSS:

NOTE this only applies to the @rjsf/core theme

i.glyphicon {
display: none;
}
.btn-add::after {
content: 'Add';
}
.array-item-copy::after {
content: 'Copy';
}
.array-item-move-up::after {
content: 'Move Up';
}
.array-item-move-down::after {
content: 'Move Down';
}
.array-item-remove::after {
content: 'Remove';
}

Submit form programmatically

You can use the reference to get your Form component and call the submit method to submit the form programmatically without a submit button. This method will dispatch the submit event of the form, and the function, that is passed to onSubmit props, will be called.

import { createRef } from 'react';
import { RJSFSchema, UiSchema } from '@rjsf/utils';
import { Form } from '@rjsf/core';
import validator from '@rjsf/validator-ajv8';

const onSubmit = ({ formData }) => console.log('Data submitted: ', formData);
let yourForm;

const schema: RJSFSchema = {
type: 'string',
};

const formRef = createRef<Form>();

render(
<Form schema={schema} validator={validator} onSubmit={onSubmit} ref={formRef} />,
document.getElementById('app')
);

formRef.current.submit();
- + \ No newline at end of file diff --git a/docs/advanced-customization/typescript/index.html b/docs/advanced-customization/typescript/index.html index 8273a69948..f7bb4fa102 100644 --- a/docs/advanced-customization/typescript/index.html +++ b/docs/advanced-customization/typescript/index.html @@ -4,7 +4,7 @@ Typescript Support | react-jsonschema-form - + @@ -19,7 +19,7 @@ Using the withTheme() function is just as easy:

import { RJSFSchema } from '@rjsf/utils';
import { customizeValidator } from '@rjsf/validator-ajv8';
import { withTheme, ThemeProps } from '@rjsf/core';

interface FormData {
foo?: string;
bar?: number;
}

type MySchema = JSONSchemaType<FormData>;

const schema: MySchema = {
type: 'object',
properties: {
foo: { type: 'string' },
bar: { type: 'number' },
},
};

interface FormContext {
myCustomWidgetData: object;
}

const theme: ThemeProps<FormData, MySchema, FormContext> = {
widgets: { test: () => <div>test</div> },
};

const ThemedForm = withTheme<FormData, MySchema, FormContext>(theme);

const validator = customizeValidator<FormData, MySchema, FormContext>();

const Demo = () => <ThemedForm schema={schema} uiSchema={uiSchema} validator={validator} />;

Overriding generics in other themes

Since all the other themes in RJSF are extensions of @rjsf/core, overriding parts of these themes with custom generics is a little different. The exported Theme and Form from any of the themes have been created using the generic defaults, and as a result, do not take generics themselves. In order to override generics, special generateForm() and generateTheme() functions are exported for your use.

Overriding a Theme

If you are doing something like the following to create a new theme based on @rjsf/mui to extend one or more templates:

import React from 'react';
import { WidgetProps } from '@rjsf/utils';
import { ThemeProps, withTheme } from '@rjsf/core';
import validator from '@rjsf/validator-ajv8';
import { Theme } from '@rjsf/mui';

const OldBaseInputTemplate = Theme.templates.BaseInputTemplate;

// Force the underlying `TextField` component to always use size="small"
function MyBaseInputTemplate(props: WidgetProps) {
return <OldBaseInputTemplate {...props} size='small' />;
}

const myTheme: ThemeProps = {
...Theme,
templates: {
...Theme.templates,
BaseInputTemplate: MyBaseInputTemplate,
},
};

const ThemedForm = withTheme(myTheme);

const Demo = () => <ThemedForm schema={schema} uiSchema={uiSchema} validator={validator} />;

Then you would use the new generateTheme() and generateForm() functions as follows:

import React from 'react';
import { WidgetProps } from '@rjsf/utils';
import { ThemeProps, withTheme } from '@rjsf/core';
import { customizeValidator } from '@rjsf/validator-ajv8';
import { generateTheme } from '@rjsf/mui';

interface FormData {
foo?: string;
bar?: number;
}

type MySchema = JSONSchemaType<FormData>;

const schema: MySchema = {
type: 'object',
properties: {
foo: { type: 'string' },
bar: { type: 'number' },
},
};

interface FormContext {
myCustomWidgetData: object;
}

const Theme: ThemeProps<FormData, MySchema, FormContext> = generateTheme<FormData, MySchema, FormContext>();

const OldBaseInputTemplate = Theme.templates.BaseInputTemplate;

// Force the underlying `TextField` component to always use size="small"
function MyBaseInputTemplate(props: WidgetProps<FormData, MySchema, FormContext>) {
return <OldBaseInputTemplate {...props} size='small' />;
}

const myTheme: ThemeProps<FormData, MySchema, FormContext> = {
...Theme,
templates: {
...Theme.templates,
BaseInputTemplate: MyBaseInputTemplate,
},
};

const ThemedForm = withTheme<FormData, MySchema, FormContext>(myTheme);

const validator = customizeValidator<FormData, MySchema, FormContext>();

// You could also do since they are effectively the same:
// const ThemedForm = generateForm<FormData, MySchema, FormContext>(myTheme);

const Demo = () => <ThemedForm schema={schema} uiSchema={uiSchema} validator={validator} />;

NOTE: The same approach works for extending widgets and fields as well.

- + \ No newline at end of file diff --git a/docs/api-reference/form-props/index.html b/docs/api-reference/form-props/index.html index 47fa86ad34..01d87810cc 100644 --- a/docs/api-reference/form-props/index.html +++ b/docs/api-reference/form-props/index.html @@ -4,7 +4,7 @@ <Form /> Props | react-jsonschema-form - + @@ -35,7 +35,7 @@ The ordering of parameters is important because some languages may choose to put the second parameter before the first in its translation. In addition to replaceable parameters, some of the strings support the use of markdown and simple html.

One can use the documentation of the TranslatableString enums to determine which enum values contain replaceable parameters and which support markdown and simple html.

One could use this function to alter one or more of the existing english strings to better suit one's application or fully translate all strings into a different language. Below is an example of changing a few of the english strings to something else:

import { TranslatableString, englishStringTranslator, replaceStringParameters } from '@rjsf/utils';

function fixupSomeEnglishStrings(stringToTranslate: TranslatableString, params?: string[]): string {
switch (stringToTranslate) {
case TranslatableString.NewStringDefault:
return ''; // Use an empty string for the new additionalProperties string default value
case TranslatableString.KeyLabel:
return replaceStringParameters('%1 Key Name', params); // Add "Name" onto the end of the WrapIfAdditionalTemplate key label
default:
return englishStringTranslator(stringToTranslate, params); // Fallback to the default english
}
}

uiSchema

Form uiSchema. See uiSchema Reference for more information.

validator

Required! An implementation of the ValidatorType interface that is needed for form validation to work. @rjsf/validator-ajv8 exports the implementation of this interface from RJSF version 4.

widgets

Dictionary of registered widgets in the form. See Custom Widgets and Fields for more information.

- + \ No newline at end of file diff --git a/docs/api-reference/index.html b/docs/api-reference/index.html index 77a4e2c28f..1e2bd9867c 100644 --- a/docs/api-reference/index.html +++ b/docs/api-reference/index.html @@ -4,13 +4,13 @@ API Reference | react-jsonschema-form - +
Skip to main content
- + \ No newline at end of file diff --git a/docs/api-reference/themes/antd/uiSchema/index.html b/docs/api-reference/themes/antd/uiSchema/index.html index 5b35815de5..7425201e27 100644 --- a/docs/api-reference/themes/antd/uiSchema/index.html +++ b/docs/api-reference/themes/antd/uiSchema/index.html @@ -4,7 +4,7 @@ AntD Customization | react-jsonschema-form - + @@ -12,7 +12,7 @@
Skip to main content
Version: v5

AntD Customization

formContext

You can customize the look of the form by passing options to Ant-Design theme fields.

The formContext antd object accepts descriptionLocation, readonlyAsDisabled properties.

descriptionLocation can be 'below' | 'tooltip', the default is 'below' which places the description below the form item. You can set it to tooltip that put the description inside the tooltip. Note that you should have antd 4.7+ to use 'tooltip'.

Setting {readonlyAsDisabled: false} on the formContext will make the antd theme treat readOnly fields as disabled.

<Form
formContext={{
descriptionLocation: 'tooltip',
readonlyAsDisabled: false,
// other props...
}}
/>

These are the formContext properties that you can modify to adjust the antd presentation:

  • descriptionLocation: Where to display the description, either 'below' or 'tooltip', defaults to 'below'
  • readonlyAsDisabled: Whether to make the antd theme treat readOnly fields as disabled, defaults to true

Using Antd v5 theme

You can use AntD v5 styling by wrapping your application with StyleProvider from @ant-design/cssinjs.

By default, @rjsf/antd components are using the v4 styling.

import { StyleProvider } from '@ant-design/cssinjs';

const Component = () => {
return (
<StyleProvider>
<YourFormComponents />
</StyleProvider>
);
};
- + \ No newline at end of file diff --git a/docs/api-reference/themes/chakra-ui/uiSchema/index.html b/docs/api-reference/themes/chakra-ui/uiSchema/index.html index 7bda314ef4..0aa3de6e09 100644 --- a/docs/api-reference/themes/chakra-ui/uiSchema/index.html +++ b/docs/api-reference/themes/chakra-ui/uiSchema/index.html @@ -4,14 +4,14 @@ Chakra-UI Customization | react-jsonschema-form - +
Skip to main content
Version: v5

Chakra-UI Customization

When using @rjsf/chakra-ui there are a couple of ways to customize the feel of the form.

Styling

You can use ChakraProvider, where you can customize the field components at a theme level. And, uiSchema allows for the use of a "chakra" "ui:option" to customize the styling of the form widgets.

{
"yourField": {
"ui:options": {
"chakra": {
"p": "1rem",
"color": "blue.200",
"sx": {
"margin": "0 auto"
}
}
}
}
}

It accepts the theme accessible style props provided by Chakra and Emotion.

Limitations

  • The chakra option is only available for the Chakra-UI theme.
  • The props are given to the parent component in the individual widget. To pass styles to the inner components, use the sx prop.
- + \ No newline at end of file diff --git a/docs/api-reference/themes/semantic-ui/uiSchema/index.html b/docs/api-reference/themes/semantic-ui/uiSchema/index.html index 0f9d81c2d5..a2218e74c1 100644 --- a/docs/api-reference/themes/semantic-ui/uiSchema/index.html +++ b/docs/api-reference/themes/semantic-ui/uiSchema/index.html @@ -4,13 +4,13 @@ Semantic-UI Customization | react-jsonschema-form - +
Skip to main content
Version: v5

Semantic-UI Customization

There are various options to pass to semantic theme fields.

Note that every semantic property within uiSchema can be rendered in one of two ways: {"ui:options": {semantic:{[property]: [value]}}}

In other words, the following uiSchema is equivalent:

Note: All fields have the following settings below as their default

fluid: Take on the size of its container.
inverted: Format to appear on dark backgrounds.
{
"ui:options": {
"semantic": {
"fluid": true,
"inverted": false,
"errorOptions": {
"size": "small",
"pointing": "above"
}
}
}
}

Semantic Widget Optional Properties

errorOptions

The uiSchema semantic object accepts an errorOptions property for each field of the schema:

size: determines the size of the error message dialog
pointing: determines the direction of the arrow on the error message dialog

Below are the current defaults

import { UiSchema } from '@rjsf/utils';

const uiSchema: UiSchema = {
'ui:options': {
semantic: {
errorOptions: {
size: 'small',
pointing: 'above',
},
},
},
};

semantic options uiSchema for array items

To specify a uiSchema that applies to array items, specify the semantic uiSchema value within the ui:options property:

wrapItem: wrap each array item in a Segment
horizontalButtons: vertical buttons instead of the default horizontal
import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'string',
},
};

const uiSchema: UiSchema = {
'ui:options': {
semantic: {
wrapItem: true,
horizontalButtons: false,
},
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

formContext

The formContext semantic object accepts wrapContent ,wrapLabel properties.

wrapContent: wrap all inputs  field content in a div, for custom styling
wrapLabel: wrap all labels in a div, for custom styling via CSS
<Form
formContext={{
semantic: {
wrapLabel: true,
wrapContent: true,
},
// other props...
}}
/>
- + \ No newline at end of file diff --git a/docs/api-reference/uiSchema/index.html b/docs/api-reference/uiSchema/index.html index 9db7db5db9..1c8278162e 100644 --- a/docs/api-reference/uiSchema/index.html +++ b/docs/api-reference/uiSchema/index.html @@ -4,7 +4,7 @@ uiSchema | react-jsonschema-form - + @@ -24,7 +24,7 @@ If you want to override the titles of the first two elements within the anyOf list you would do the following:

import { RJSFSchema, UiSchema } from '@rjsf/utils';

const schema: RJSFSchema = {
type: 'object',
anyOf: [
{
title: 'Strings',
type: 'string',
},
{
title: 'Numbers',
type: 'number',
},
{
title: 'Booleans',
type: 'boolean',
},
],
};

const uiSchema: UiSchema = {
anyOf: [
{
'ui:title': 'Custom String Title',
},
{
'ui:title': 'Custom Number Title',
},
],
};

NOTE: Because the third element in the schema does not have an associated element in the uiSchema, it will keep its original title.

oneOf

The uiSchema will work with elements inside an oneOf as long as the uiSchema defines the oneOf key at the same level as the oneOf within the schema. Because the oneOf in the schema is an array, so must be the one in the uiSchema. If you want to override the titles of the first two elements within the oneOf list you would do the following:

import { RJSFSchema, UiSchema } from '@rjsf/utils';

const schema: RJSFSchema = {
type: 'object',
oneOf: [
{
title: 'Strings',
type: 'string',
},
{
title: 'Numbers',
type: 'number',
},
{
title: 'Booleans',
type: 'boolean',
},
],
};

const uiSchema: UiSchema = {
oneOf: [
{
'ui:title': 'Custom String Title',
},
{
'ui:title': 'Custom Number Title',
},
],
};

NOTE: Because the third element in the schema does not have an associated element in the uiSchema, it will keep its original title.

Theme Options

- + \ No newline at end of file diff --git a/docs/api-reference/utility-functions/index.html b/docs/api-reference/utility-functions/index.html index 666455be65..e01cdb9083 100644 --- a/docs/api-reference/utility-functions/index.html +++ b/docs/api-reference/utility-functions/index.html @@ -4,7 +4,7 @@ RJSF utility functions, constants and types | react-jsonschema-form - + @@ -82,7 +82,7 @@ For more information about how to specify the path see the eslint lodash plugin docs.

Parameters

Returns

setErrors()

Sets/replaces the errorOrList as the error(s) in the ErrorSchema at either the root level or the location within the schema described by the pathOfError. For more information about how to specify the path see the eslint lodash plugin docs.

Parameters

Returns

clearErrors()

Clears the error(s) in the ErrorSchema at either the root level or the location within the schema described by the pathOfError. For more information about how to specify the path see the eslint lodash plugin docs.

Parameters

Returns

- + \ No newline at end of file diff --git a/docs/api-reference/validator-ajv8/index.html b/docs/api-reference/validator-ajv8/index.html index 767a42718a..88e77a61e8 100644 --- a/docs/api-reference/validator-ajv8/index.html +++ b/docs/api-reference/validator-ajv8/index.html @@ -4,7 +4,7 @@ @rjsf/validator-ajv8 APIs | react-jsonschema-form - + @@ -17,7 +17,7 @@ The main reasons for using a precompiled validator is reducing code size, improving validation speed and, most importantly, avoiding dynamic code compilation when prohibited by a browser's Content Security Policy. For more information about AJV code compilation see: https://ajv.js.org/standalone.html

Parameters

createPrecompiledValidator<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>()

Creates and returns a ValidatorType interface that is implemented with a precompiled validator. If a localizer is provided, it is used to translate the messages generated by the underlying AJV validation.

NOTE: The validateFns parameter is an object obtained by importing from a precompiled validation file created via the compileSchemaValidators() function.

Parameters

Returns

- + \ No newline at end of file diff --git a/docs/assets/js/219dd62e.33672f6b.js b/docs/assets/js/219dd62e.33672f6b.js new file mode 100644 index 0000000000..e6c2129023 --- /dev/null +++ b/docs/assets/js/219dd62e.33672f6b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_rjsf_docs=self.webpackChunk_rjsf_docs||[]).push([[3940],{3636:(e,a,t)=>{t.d(a,{Iu:()=>d,yg:()=>h});var n=t(5668);function r(e,a,t){return a in e?Object.defineProperty(e,a,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[a]=t,e}function o(e,a){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);a&&(n=n.filter((function(a){return Object.getOwnPropertyDescriptor(e,a).enumerable}))),t.push.apply(t,n)}return t}function i(e){for(var a=1;a=0||(r[t]=e[t]);return r}(e,a);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=n.createContext({}),m=function(e){var a=n.useContext(l),t=a;return e&&(t="function"==typeof e?e(a):i(i({},a),e)),t},d=function(e){var a=m(e.components);return n.createElement(l.Provider,{value:a},e.children)},p="mdxType",c={inlineCode:"code",wrapper:function(e){var a=e.children;return n.createElement(n.Fragment,{},a)}},u=n.forwardRef((function(e,a){var t=e.components,r=e.mdxType,o=e.originalType,l=e.parentName,d=s(e,["components","mdxType","originalType","parentName"]),p=m(t),u=r,h=p["".concat(l,".").concat(u)]||p[u]||c[u]||o;return t?n.createElement(h,i(i({ref:a},d),{},{components:t})):n.createElement(h,i({ref:a},d))}));function h(e,a){var t=arguments,r=a&&a.mdxType;if("string"==typeof e||r){var o=t.length,i=new Array(o);i[0]=u;var s={};for(var l in a)hasOwnProperty.call(a,l)&&(s[l]=a[l]);s.originalType=e,s[p]="string"==typeof e?e:r,i[1]=s;for(var m=2;m{t.r(a),t.d(a,{assets:()=>l,contentTitle:()=>i,default:()=>c,frontMatter:()=>o,metadata:()=>s,toc:()=>m});var n=t(5307),r=(t(5668),t(3636));const o={},i="Validation",s={unversionedId:"usage/validation",id:"usage/validation",title:"Validation",description:"When the form is submitted, the form data is validated to conform to the given JSON schema;",source:"@site/docs/usage/validation.md",sourceDirName:"usage",slug:"/usage/validation",permalink:"/react-jsonschema-form/docs/usage/validation",draft:!1,editUrl:"https://github.com/rjsf-team/react-jsonschema-form/tree/main/packages/docs/docs/usage/validation.md",tags:[],version:"current",frontMatter:{},sidebar:"docs",previous:{title:"Themes",permalink:"/react-jsonschema-form/docs/usage/themes"},next:{title:"Widgets",permalink:"/react-jsonschema-form/docs/usage/widgets"}},l={},m=[{value:"API documentation",id:"api-documentation",level:2},{value:"Precompiled validators",id:"precompiled-validators",level:2},{value:"Schema precompilation",id:"schema-precompilation",level:3},{value:"Using the precompiled validator",id:"using-the-precompiled-validator",level:3},{value:"Dynamically pre-compiling validators",id:"dynamically-pre-compiling-validators",level:3},{value:"Live validation",id:"live-validation",level:2},{value:"Validate form programmatically",id:"validate-form-programmatically",level:2},{value:"HTML5 Validation",id:"html5-validation",level:2},{value:"Custom validation rules",id:"custom-validation-rules",level:2},{value:"Custom error messages",id:"custom-error-messages",level:2},{value:"Error List Display",id:"error-list-display",level:2},{value:"The case of empty strings",id:"the-case-of-empty-strings",level:2},{value:"Custom meta schema validation",id:"custom-meta-schema-validation",level:2},{value:"additionalMetaSchemas",id:"additionalmetaschemas",level:3},{value:"customFormats",id:"customformats",level:3},{value:"Async validation",id:"async-validation",level:3},{value:"ajvOptionsOverrides",id:"ajvoptionsoverrides",level:3},{value:"Using the raw Ajv instance",id:"using-the-raw-ajv-instance",level:2},{value:"Ajv8 validator differences",id:"ajv8-validator-differences",level:2},{value:"ajvFormatOptions",id:"ajvformatoptions",level:3},{value:"AjvClass",id:"ajvclass",level:3},{value:"Localization (L10n) support",id:"localization-l10n-support",level:3},{value:"Some examples",id:"some-examples",level:4}],d={toc:m},p="wrapper";function c(e){let{components:a,...t}=e;return(0,r.yg)(p,(0,n.c)({},d,t,{components:a,mdxType:"MDXLayout"}),(0,r.yg)("h1",{id:"validation"},"Validation"),(0,r.yg)("p",null,"When the form is submitted, the form data is validated to conform to the given JSON schema;"),(0,r.yg)("p",null,"As of version 5, as a result of decoupling the validation implementation from the ",(0,r.yg)("inlineCode",{parentName:"p"},"Form"),", a ",(0,r.yg)("inlineCode",{parentName:"p"},"validator")," implementation is required to be passed to all ",(0,r.yg)("inlineCode",{parentName:"p"},"Form"),"s.\nReact Json Schema Form provides a default ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv6")," implementation that uses version 6 of the ",(0,r.yg)("a",{parentName:"p",href:"https://github.com/ajv-validator/ajv"},"ajv")," validator."),(0,r.yg)("blockquote",null,(0,r.yg)("p",{parentName:"blockquote"},"NOTE: The ajv6 validator has been deprecated from the outset in favor of the ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8")," and is provided primarily to assist in code migrations")),(0,r.yg)("p",null,"It also provides a new ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8")," implementation that uses version 8 of the ",(0,r.yg)("a",{parentName:"p",href:"https://github.com/ajv-validator/ajv"},"ajv")," validator.\nThe error messages generated by this new validator differ from those provided by the original validator due to it using a newer version.\nIf you depend on having specifically formatted messages, then using this validator would constitute a breaking change for you."),(0,r.yg)("p",null,"It is also possible for you to provide your own implementation if you desire, as long as it fulfills the ",(0,r.yg)("inlineCode",{parentName:"p"},"ValidatorType")," interface specified in ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/utils"),"."),(0,r.yg)("h2",{id:"api-documentation"},"API documentation"),(0,r.yg)("p",null,"The documentation for the APIs associated with the AJV 8 validator package can be found ",(0,r.yg)("a",{parentName:"p",href:"/react-jsonschema-form/docs/api-reference/validator-ajv8"},"here")),(0,r.yg)("h2",{id:"precompiled-validators"},"Precompiled validators"),(0,r.yg)("p",null,"In 5.7.0, support for precompiled validators was added to the ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8")," package.\nThe main use case for this is to overcome issues with ",(0,r.yg)("inlineCode",{parentName:"p"},"unsafe-eval")," warnings from the browser caused by strict Content Security Policy settings.\nSee the ",(0,r.yg)("a",{parentName:"p",href:"https://ajv.js.org/standalone.html"},"Standalone Validation Code")," section of the AJV documentation for more details about precompiled validators."),(0,r.yg)("p",null,"Due to how RJSF uses the AJV validator in determining ",(0,r.yg)("inlineCode",{parentName:"p"},"anyOf/oneOf")," selections and how it resolves dependencies, if-then-else and references ($ref) in schemas via the ",(0,r.yg)("inlineCode",{parentName:"p"},"retrieveSchema()")," utility method, RJSF provides its own schema compilation API built on-top-of the one provided by AJV 8.\nIf you are wanting to use a precompiled validator, two steps are required:"),(0,r.yg)("ol",null,(0,r.yg)("li",{parentName:"ol"},"Precompiling the schema into a set of validator functions"),(0,r.yg)("li",{parentName:"ol"},"Providing those precompiled validator functions to a ",(0,r.yg)("inlineCode",{parentName:"li"},"ValidatorType")," implementation in the ",(0,r.yg)("inlineCode",{parentName:"li"},"Form"))),(0,r.yg)("h3",{id:"schema-precompilation"},"Schema precompilation"),(0,r.yg)("p",null,"The first step in the process is to compile a schema into a set of validator functions that are saved into a commonJS-based Javascript file.\nThe ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8")," package exports the ",(0,r.yg)("inlineCode",{parentName:"p"},"compileSchemaValidators()")," function that does this.\nIt is expected that this function will be used in a manner similar to the following:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-cjs"},"const compileSchemaValidators = require('@rjsf/validator-ajv8/dist/compileSchemaValidators').default;\nconst yourSchema = require('path_to/yourSchema'); // If your schema is a js file\n\ncompileSchemaValidators(yourSchema, 'path_to/yourCompiledSchema.js');\n")),(0,r.yg)("p",null,"If you are currently using the ",(0,r.yg)("inlineCode",{parentName:"p"},"customizeValidator()")," function to provide ",(0,r.yg)("inlineCode",{parentName:"p"},"additionalMetaSchemas"),", ",(0,r.yg)("inlineCode",{parentName:"p"},"customFormats"),", ",(0,r.yg)("inlineCode",{parentName:"p"},"ajvOptionsOverrides")," and/or ",(0,r.yg)("inlineCode",{parentName:"p"},"ajvFormatOptions")," then you can pass those in as the optional third parameter to the ",(0,r.yg)("inlineCode",{parentName:"p"},"compileSchemaValidators()")," function in a manner similar to:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-cjs"},"const { compileSchemaValidators } = require('@rjsf/validator-ajv8');\nconst yourSchema = require('path_to/yourSchema.json'); // If your schema is a json file\n\nconst options = {\n additionalMetaSchemas: [require('ajv/lib/refs/json-schema-draft-06.json')],\n customFormats: { 'phone-us': /\\(?\\d{3}\\)?[\\s-]?\\d{3}[\\s-]?\\d{4}$/, 'area-code': /\\d{3}/ },\n ajvOptionsOverrides: {\n $data: true,\n verbose: true,\n },\n ajvFormatOptions: {\n mode: 'fast',\n },\n};\n\ncompileSchemaValidators(yourSchema, 'path_to/yourCompiledSchema.js', options);\n")),(0,r.yg)("p",null,"It is highly recommended to create a ",(0,r.yg)("inlineCode",{parentName:"p"},"compileYourSchema.js")," file (or what ever name you want) with code similar to what is shown above and then, using node, run the code as follows:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre"},"node compileYourSchema.js\n")),(0,r.yg)("blockquote",null,(0,r.yg)("p",{parentName:"blockquote"},"NOTE: You must have your schema provided within a file that can be parsed and turned into the set of precompiled validator functions.")),(0,r.yg)("blockquote",null,(0,r.yg)("p",{parentName:"blockquote"},"Additional Note: If you are using Webpack or NextJS and are encountering an issue resolving ",(0,r.yg)("inlineCode",{parentName:"p"},"fs")," during development, consult this ",(0,r.yg)("a",{parentName:"p",href:"https://bobbyhadz.com/blog/module-not-found-cant-resolve-fs"},"blog post")," for how to solve the issue.")),(0,r.yg)("h3",{id:"using-the-precompiled-validator"},"Using the precompiled validator"),(0,r.yg)("p",null,"After you have completed step 1 having generated your precompiled schema functions into the ",(0,r.yg)("inlineCode",{parentName:"p"},"yourCompiledSchema.js")," output file (or whatever you called it), then you need to create a ",(0,r.yg)("inlineCode",{parentName:"p"},"ValidatorType")," implementation from it to use in the ",(0,r.yg)("inlineCode",{parentName:"p"},"Form"),".\nThe ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8")," package exports the ",(0,r.yg)("inlineCode",{parentName:"p"},"createPrecompiledValidator()")," function for this.\nHere is an example of how to use your precompiled validator with your ",(0,r.yg)("inlineCode",{parentName:"p"},"Form"),":"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { createPrecompiledValidator, ValidatorFunctions } from '@rjsf/validator-ajv8';\nimport Form from '@rjsf/core'; // Or whatever theme you use\n\nimport yourSchema from 'path_to/yourSchema'; // This needs to be the same file that was precompiled\nimport * as precompiledValidator from 'path_to/yourCompiledSchema';\n\nconst validator = createPrecompiledValidator(precompiledValidator as ValidatorFunctions);\n\nrender(
, document.getElementById('app'));\n")),(0,r.yg)("h3",{id:"dynamically-pre-compiling-validators"},"Dynamically pre-compiling validators"),(0,r.yg)("p",null,"For more advanced cases when schema needs to be precompiled on request - ",(0,r.yg)("inlineCode",{parentName:"p"},"compileSchemaValidatorsCode")," can be used."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-ts"},"import { compileSchemaValidatorsCode } from '@rjsf/validator-ajv8/dist/compileSchemaValidators';\n\nconst code = compileSchemaValidatorsCode(schema, options);\n")),(0,r.yg)("p",null,"For the most part it is the same as ",(0,r.yg)("inlineCode",{parentName:"p"},"compileSchemaValidators"),", but instead of writing the file - it returns generated code directly."),(0,r.yg)("p",null,"To use it on browser side - some modifications are needed to provide runtime dependencies in generated code needs to be provided."),(0,r.yg)("p",null,"Example implementation of it:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import type { ValidatorFunctions } from '@rjsf/validator-ajv8';\n\nimport ajvRuntimeEqual from 'ajv/dist/runtime/equal';\nimport {\n parseJson as ajvRuntimeparseJson,\n parseJsonNumber as ajvRuntimeparseJsonNumber,\n parseJsonString as ajvRuntimeparseJsonString,\n} from 'ajv/dist/runtime/parseJson';\nimport ajvRuntimeQuote from 'ajv/dist/runtime/quote';\n// import ajvRuntimeRe2 from 'ajv/dist/runtime/re2';\nimport ajvRuntimeTimestamp from 'ajv/dist/runtime/timestamp';\nimport ajvRuntimeUcs2length from 'ajv/dist/runtime/ucs2length';\nimport ajvRuntimeUri from 'ajv/dist/runtime/uri';\nimport * as ajvFormats from 'ajv-formats/dist/formats';\n\n// dependencies to replace in generated code, to be provided by at runtime\nconst validatorsBundleReplacements: Record = {\n // '': ['', ],\n 'require(\"ajv/dist/runtime/equal\").default': ['ajvRuntimeEqual', ajvRuntimeEqual],\n 'require(\"ajv/dist/runtime/parseJson\").parseJson': ['ajvRuntimeparseJson', ajvRuntimeparseJson],\n 'require(\"ajv/dist/runtime/parseJson\").parseJsonNumber': ['ajvRuntimeparseJsonNumber', ajvRuntimeparseJsonNumber],\n 'require(\"ajv/dist/runtime/parseJson\").parseJsonString': ['ajvRuntimeparseJsonString', ajvRuntimeparseJsonString],\n 'require(\"ajv/dist/runtime/quote\").default': ['ajvRuntimeQuote', ajvRuntimeQuote],\n // re2 by default is not in dependencies for ajv and so is likely not normally used\n // 'require(\"ajv/dist/runtime/re2\").default': ['ajvRuntimeRe2', ajvRuntimeRe2],\n 'require(\"ajv/dist/runtime/timestamp\").default': ['ajvRuntimeTimestamp', ajvRuntimeTimestamp],\n 'require(\"ajv/dist/runtime/ucs2length\").default': ['ajvRuntimeUcs2length', ajvRuntimeUcs2length],\n 'require(\"ajv/dist/runtime/uri\").default': ['ajvRuntimeUri', ajvRuntimeUri],\n // formats\n 'require(\"ajv-formats/dist/formats\")': ['ajvFormats', ajvFormats],\n};\n\nconst regexp = new RegExp(\n Object.keys(validatorsBundleReplacements)\n .map((key) => key.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&'))\n .join('|'),\n 'g'\n);\n\nfunction wrapAjvBundle(code: string) {\n return `function(${Object.values(validatorsBundleReplacements)\n .map(([name]) => name)\n .join(', ')}){\\nvar exports = {};\\n${code.replace(\n regexp,\n (req) => validatorsBundleReplacements[req][0]\n )};\\nreturn exports;\\n}`;\n}\n\nconst windowValidatorOnLoad = '__rjsf_validatorOnLoad';\nconst schemas = new Map<\n string,\n { promise: Promise; resolve: (result: ValidatorFunctions) => void }\n>();\nif (typeof window !== 'undefined') {\n // @ts-ignore\n window[windowValidatorOnLoad] = (loadedId: string, fn: (...args: unknown[]) => ValidatorFunctions) => {\n const validator = fn(...Object.values(validatorsBundleReplacements).map(([, dep]) => dep));\n let validatorLoader = schemas.get(loadedId);\n if (validatorLoader) {\n validatorLoader.resolve(validator);\n } else {\n throw new Error(`Unknown validator loaded id=\"${loadedId}\"`);\n }\n };\n}\n\n/**\n * Evaluate precompiled validator in browser using script tag\n * @param id Identifier to avoid evaluating the same code multiple times\n * @param code Code generated server side using `compileSchemaValidatorsCode`\n * @param nonce nonce attribute to be added to script tag (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce#using_nonce_to_allowlist_a_script_element)\n */\nexport function evaluateValidator(id: string, code: string, nonce: string): Promise {\n let maybeValidator = schemas.get(id);\n if (maybeValidator) return maybeValidator.promise;\n let resolveValidator: (result: ValidatorFunctions) => void;\n const validatorPromise = new Promise((resolve) => {\n resolveValidator = resolve;\n });\n schemas.set(id, {\n promise: validatorPromise,\n resolve: resolveValidator!,\n });\n\n const scriptElement = document.createElement('script');\n\n scriptElement.setAttribute('nonce', nonce);\n scriptElement.text = `window[\"${windowValidatorOnLoad}\"](\"${id}\", ${wrapAjvBundle(code)})`;\n\n document.body.appendChild(scriptElement);\n return validatorPromise;\n}\n")),(0,r.yg)("p",null,"From React component this can be used as following:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"let [precompiledValidator, setPrecompiledValidator] = React.useState();\nReact.useEffect(() => {\n evaluateValidator(\n schemaId, // some schema id to avoid evaluating it multiple times\n code, // result of compileSchemaValidatorsCode returned from the server\n nonce // nonce script tag attribute to allow this ib content security policy for the page\n ).then(setPrecompiledValidator);\n}, [entityType.id]);\n\nif (!precompiledValidator) {\n // render loading screen\n}\nconst validator = createPrecompiledValidator(precompiledValidator, schema);\n")),(0,r.yg)("h2",{id:"live-validation"},"Live validation"),(0,r.yg)("p",null,"By default, form data are only validated when the form is submitted or when a new ",(0,r.yg)("inlineCode",{parentName:"p"},"formData")," prop is passed to the ",(0,r.yg)("inlineCode",{parentName:"p"},"Form")," component."),(0,r.yg)("p",null,"You can enable live form data validation by passing a ",(0,r.yg)("inlineCode",{parentName:"p"},"liveValidate")," prop to the ",(0,r.yg)("inlineCode",{parentName:"p"},"Form")," component, and set it to ",(0,r.yg)("inlineCode",{parentName:"p"},"true"),". Then, every time a value changes within the form data tree (e.g. the user entering a character in a field), a validation operation is performed, and the validation results are reflected into the form state."),(0,r.yg)("p",null,"Be warned that this is an expensive strategy, with possibly strong impact on performances."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport validator from '@rjsf/validator-ajv8';\n\nconst schema: RJSFSchema = {\n type: ['string'],\n const: 'test',\n};\n\nconst formData = 'a';\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("h2",{id:"validate-form-programmatically"},"Validate form programmatically"),(0,r.yg)("p",null,"It is possible to programmatically validate a form using the ",(0,r.yg)("inlineCode",{parentName:"p"},"validateForm()")," function on ",(0,r.yg)("inlineCode",{parentName:"p"},"Form"),".\nAdd a ",(0,r.yg)("inlineCode",{parentName:"p"},"ref")," to your ",(0,r.yg)("inlineCode",{parentName:"p"},"Form")," component and call the ",(0,r.yg)("inlineCode",{parentName:"p"},"validateForm()")," method to validate the form programmatically.\nThe ",(0,r.yg)("inlineCode",{parentName:"p"},"validateForm()")," method returns true if the form is valid, false otherwise.\nIf you have provided an ",(0,r.yg)("inlineCode",{parentName:"p"},"onError")," callback it will be called with the list of errors when the ",(0,r.yg)("inlineCode",{parentName:"p"},"validatorForm()")," method returns false."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { createRef } from 'react';\nimport { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport validator from '@rjsf/validator-ajv8';\n\nconst formRef = createRef();\nconst onError = (errors) => alert(errors);\n\nconst schema: RJSFSchema = {\n type: 'string',\n};\n\nrender(, document.getElementById('app'));\n\nif (formRef.current.validateForm()) {\n alert('Form is valid');\n}\n")),(0,r.yg)("h2",{id:"html5-validation"},"HTML5 Validation"),(0,r.yg)("p",null,"By default, the form uses HTML5 validation. This may cause unintuitive results because the HTML5 validation errors (such as when a field is ",(0,r.yg)("inlineCode",{parentName:"p"},"required"),") may be displayed before the form is submitted, and thus these errors will display differently from the react-jsonschema-form validation errors. You can turn off HTML validation by setting the ",(0,r.yg)("inlineCode",{parentName:"p"},"noHtml5Validate")," to ",(0,r.yg)("inlineCode",{parentName:"p"},"true"),"."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport validator from '@rjsf/validator-ajv8';\n\nconst schema: RJSFSchema = {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n required: true,\n },\n },\n};\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("h2",{id:"custom-validation-rules"},"Custom validation rules"),(0,r.yg)("p",null,"Form data is always validated against the JSON schema."),(0,r.yg)("p",null,"But it is possible to define your own custom validation rules that will run in addition to (and after) the ",(0,r.yg)("inlineCode",{parentName:"p"},"validator")," implementation.\nThis is especially useful when the validation depends on several interdependent fields."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport validator from '@rjsf/validator-ajv8';\n\nfunction customValidate(formData, errors, uiSchema) {\n if (formData.pass1 !== formData.pass2) {\n errors.pass2.addError(\"Passwords don't match\");\n }\n return errors;\n}\n\nconst schema: RJSFSchema = {\n type: 'object',\n properties: {\n pass1: { type: 'string', minLength: 3 },\n pass2: { type: 'string', minLength: 3 },\n },\n};\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("blockquote",null,(0,r.yg)("p",{parentName:"blockquote"},"Notes:"),(0,r.yg)("ul",{parentName:"blockquote"},(0,r.yg)("li",{parentName:"ul"},"The ",(0,r.yg)("inlineCode",{parentName:"li"},"customValidate()")," function must implement the ",(0,r.yg)("inlineCode",{parentName:"li"},"CustomValidator")," interface found in ",(0,r.yg)("inlineCode",{parentName:"li"},"@rjsf/utils"),"."),(0,r.yg)("li",{parentName:"ul"},"The ",(0,r.yg)("inlineCode",{parentName:"li"},"customValidate()")," function must ",(0,r.yg)("strong",{parentName:"li"},"always")," return the ",(0,r.yg)("inlineCode",{parentName:"li"},"errors")," object received as second argument."),(0,r.yg)("li",{parentName:"ul"},"The ",(0,r.yg)("inlineCode",{parentName:"li"},"customValidate()")," function is called ",(0,r.yg)("strong",{parentName:"li"},"after")," the JSON schema validation."),(0,r.yg)("li",{parentName:"ul"},"The ",(0,r.yg)("inlineCode",{parentName:"li"},"customValidate()")," function is passed the ",(0,r.yg)("inlineCode",{parentName:"li"},"uiSchema")," as the third argument. This allows the ",(0,r.yg)("inlineCode",{parentName:"li"},"customValidate()")," function to be able to derive additional information from it for generating errors."))),(0,r.yg)("h2",{id:"custom-error-messages"},"Custom error messages"),(0,r.yg)("p",null,"Validation error messages are provided by the JSON Schema validation by default.\nIf you need to change these messages or make any other modifications to the errors from the JSON Schema validation, you can define a transform function that receives the list of JSON Schema errors and returns a new list."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport validator from '@rjsf/validator-ajv8';\n\nfunction transformErrors(errors, uiSchema) {\n return errors.map((error) => {\n if (error.name === 'pattern') {\n error.message = 'Only digits are allowed';\n }\n return error;\n });\n}\n\nconst schema: RJSFSchema = {\n type: 'object',\n properties: {\n onlyNumbersString: { type: 'string', pattern: '^\\\\d*$' },\n },\n};\n\nrender(\n ,\n document.getElementById('app')\n);\n")),(0,r.yg)("blockquote",null,(0,r.yg)("p",{parentName:"blockquote"},"Notes:"),(0,r.yg)("ul",{parentName:"blockquote"},(0,r.yg)("li",{parentName:"ul"},"The ",(0,r.yg)("inlineCode",{parentName:"li"},"transformErrors()")," function must implement the ",(0,r.yg)("inlineCode",{parentName:"li"},"ErrorTransformer")," interface found in ",(0,r.yg)("inlineCode",{parentName:"li"},"@rjsf/utils"),"."),(0,r.yg)("li",{parentName:"ul"},"The ",(0,r.yg)("inlineCode",{parentName:"li"},"transformErrors()")," function must return the list of errors. Modifying the list in place without returning it will result in an error."),(0,r.yg)("li",{parentName:"ul"},"The ",(0,r.yg)("inlineCode",{parentName:"li"},"transformErrors()")," function is passed the ",(0,r.yg)("inlineCode",{parentName:"li"},"uiSchema")," as the second argument. This allows the ",(0,r.yg)("inlineCode",{parentName:"li"},"transformErrors()")," function to be able to derive additional information from it for transforming errors."))),(0,r.yg)("p",null,"Each element in the ",(0,r.yg)("inlineCode",{parentName:"p"},"errors")," list passed to ",(0,r.yg)("inlineCode",{parentName:"p"},"transformErrors")," is a ",(0,r.yg)("inlineCode",{parentName:"p"},"RJSFValidationError")," interface (in ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/utils"),") and has the following properties:"),(0,r.yg)("ul",null,(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"name"),': optional name of the error, for example, "required" or "minLength"'),(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"message"),': optional message, for example, "is a required property" or "should NOT be shorter than 3 characters"'),(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"params"),": optional object with the error params returned by ajv (",(0,r.yg)("a",{parentName:"li",href:"https://github.com/ajv-validator/ajv/tree/6a671057ea6aae690b5967ee26a0ddf8452c6297#error-parameters"},"see doc")," for more info)."),(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"property"),": optional string in Javascript property accessor notation to the data path of the field with the error. For example, ",(0,r.yg)("inlineCode",{parentName:"li"},".name")," or ",(0,r.yg)("inlineCode",{parentName:"li"},".first-name"),"."),(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"schemaPath"),": optional JSON pointer to the schema of the keyword that failed validation. For example, ",(0,r.yg)("inlineCode",{parentName:"li"},"#/fields/firstName/required"),". (Note: this may sometimes be wrong due to a ",(0,r.yg)("a",{parentName:"li",href:"https://github.com/ajv-validator/ajv/issues/512"},"bug in ajv"),")."),(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"stack"),': full error name, for example ".name is a required property".')),(0,r.yg)("h2",{id:"error-list-display"},"Error List Display"),(0,r.yg)("p",null,"To take control over how the form errors are displayed, you can define an ",(0,r.yg)("em",{parentName:"p"},"error list template")," for your form.\nThis list is the form global error list that appears at the top of your forms."),(0,r.yg)("p",null,"An error list template is basically a React stateless component being passed errors as props, so you can render them as you like:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},'import { Form } from \'@rjsf/core\';\nimport { RJSFSchema, ErrorListProps } from "@rjsf/utils";\nimport validator from "@rjsf/validator-ajv8";\n\nfunction ErrorListTemplate(props: ErrorListProps) {\n const { errors } = props;\n return (\n
\n

Custom error list

\n
    \n {errors.map(error => (\n
  • \n {error.stack}\n
  • \n ))}\n
\n
\n );\n}\n\nconst schema: RJSFSchema = {\n type: "string",\n const: "test"\n};\n\nrender((\n \n), document.getElementById("app"));\n')),(0,r.yg)("blockquote",null,(0,r.yg)("p",{parentName:"blockquote"},"Note: Your custom ",(0,r.yg)("inlineCode",{parentName:"p"},"ErrorList")," template will only render when ",(0,r.yg)("inlineCode",{parentName:"p"},"showErrorList")," is ",(0,r.yg)("inlineCode",{parentName:"p"},"top")," or ",(0,r.yg)("inlineCode",{parentName:"p"},"botttom"),".")),(0,r.yg)("p",null,"The following props are passed to ",(0,r.yg)("inlineCode",{parentName:"p"},"ErrorList")," as defined by the ",(0,r.yg)("inlineCode",{parentName:"p"},"ErrorListProps")," interface in ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/utils"),":"),(0,r.yg)("ul",null,(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"errors"),": An array of the errors."),(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"errorSchema"),": The errorSchema constructed by ",(0,r.yg)("inlineCode",{parentName:"li"},"Form"),"."),(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"schema"),": The schema that was passed to ",(0,r.yg)("inlineCode",{parentName:"li"},"Form"),"."),(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"uiSchema"),": The uiSchema that was passed to ",(0,r.yg)("inlineCode",{parentName:"li"},"Form"),"."),(0,r.yg)("li",{parentName:"ul"},(0,r.yg)("inlineCode",{parentName:"li"},"formContext"),": The ",(0,r.yg)("inlineCode",{parentName:"li"},"formContext")," object that you passed to ",(0,r.yg)("inlineCode",{parentName:"li"},"Form"),".")),(0,r.yg)("h2",{id:"the-case-of-empty-strings"},"The case of empty strings"),(0,r.yg)("p",null,"When a text input is empty, the field in form data is set to ",(0,r.yg)("inlineCode",{parentName:"p"},"undefined"),".\nHowever, since ",(0,r.yg)("inlineCode",{parentName:"p"},"undefined")," isn't a valid JSON value according to ",(0,r.yg)("a",{parentName:"p",href:"https://www.ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf"},"the official JSON standard")," (ECMA-404, Section 5), the values get stored as ",(0,r.yg)("inlineCode",{parentName:"p"},"null"),"."),(0,r.yg)("p",null,"String fields that use ",(0,r.yg)("inlineCode",{parentName:"p"},"enum")," and a ",(0,r.yg)("inlineCode",{parentName:"p"},"select")," widget will have an empty option at the top of the options list that when selected will result in the field being ",(0,r.yg)("inlineCode",{parentName:"p"},"null"),"."),(0,r.yg)("p",null,"One consequence of this is that if you have an empty string in your ",(0,r.yg)("inlineCode",{parentName:"p"},"enum")," array, selecting that option in the ",(0,r.yg)("inlineCode",{parentName:"p"},"select")," input will cause the field to be set to ",(0,r.yg)("inlineCode",{parentName:"p"},"null"),", not an empty string."),(0,r.yg)("p",null,"If you want to have the field set to a default value when empty you can provide a ",(0,r.yg)("inlineCode",{parentName:"p"},"ui:emptyValue")," field in the ",(0,r.yg)("inlineCode",{parentName:"p"},"uiSchema")," object."),(0,r.yg)("h2",{id:"custom-meta-schema-validation"},"Custom meta schema validation"),(0,r.yg)("p",null,"To have your schemas validated against any other meta schema than draft-07 (the current version of ",(0,r.yg)("a",{parentName:"p",href:"http://json-schema.org/"},"JSON Schema"),"), make sure your schema has a ",(0,r.yg)("inlineCode",{parentName:"p"},"$schema")," attribute that enables the validator to use the correct meta schema.\nFor example:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-json"},'{\n "$schema": "http://json-schema.org/draft-04/schema#",\n ...\n}\n')),(0,r.yg)("p",null,"Note that react-jsonschema-form supports JSON Schema draft-07 by default.\nTo support additional meta schemas, you can create and pass to the ",(0,r.yg)("inlineCode",{parentName:"p"},"Form")," component a customized ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8"),":"),(0,r.yg)("h3",{id:"additionalmetaschemas"},"additionalMetaSchemas"),(0,r.yg)("p",null,"The ",(0,r.yg)("inlineCode",{parentName:"p"},"additionalMetaSchemas")," prop allows you to validate the form data against one (or more than one) JSON Schema meta schema, for example, JSON Schema draft-04.\nYou can import a meta schema as follows:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"const metaSchemaDraft04 = require('ajv/lib/refs/json-schema-draft-04.json');\n")),(0,r.yg)("p",null,"In this example ",(0,r.yg)("inlineCode",{parentName:"p"},"schema")," passed as props to ",(0,r.yg)("inlineCode",{parentName:"p"},"Form")," component can be validated against draft-07 (default) and by draft-04 (added), depending on the value of ",(0,r.yg)("inlineCode",{parentName:"p"},"$schema")," attribute."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv6';\n\nconst validator = customizeValidator({\n additionalMetaSchemas: [metaSchemaDraft04],\n});\n\nconst schema: RJSFSchema = {\n $schema: 'http://json-schema.org/draft-04/schema#',\n type: 'string',\n};\n\nreturn ;\n")),(0,r.yg)("p",null,"NOTE: This syntax works only for the ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv6")," validator; if you only use the ",(0,r.yg)("inlineCode",{parentName:"p"},"draft-04")," schema, and you want to use the ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8")," you can do the following:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv8';\nimport AjvDraft04 from 'ajv-draft-04';\n\nconst validator = customizeValidator({ AjvClass: AjvDraft04 });\n\nconst schema: RJSFSchema = {\n $schema: 'http://json-schema.org/draft-04/schema#',\n type: 'string',\n};\n\nreturn ;\n")),(0,r.yg)("h3",{id:"customformats"},"customFormats"),(0,r.yg)("p",null,(0,r.yg)("a",{parentName:"p",href:"https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.7"},"Pre-defined semantic formats")," are limited.\nreact-jsonschema-form adds two formats, ",(0,r.yg)("inlineCode",{parentName:"p"},"color")," and ",(0,r.yg)("inlineCode",{parentName:"p"},"data-url"),", to support certain ",(0,r.yg)("a",{parentName:"p",href:"/react-jsonschema-form/docs/usage/widgets"},"alternative widgets"),".\nTo add formats of your own, you can create and pass to the ",(0,r.yg)("inlineCode",{parentName:"p"},"Form")," component a customized ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8"),":"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv8';\n\nconst schema: RJSFSchema = {\n type: 'string',\n format: 'phone-us',\n};\n\nconst customFormats = {\n 'phone-us': /\\(?\\d{3}\\)?[\\s-]?\\d{3}[\\s-]?\\d{4}$/,\n};\n\nconst validator = customizeValidator({ customFormats });\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("p",null,"Format values can be anything AJV's ",(0,r.yg)("a",{parentName:"p",href:"https://github.com/ajv-validator/ajv/tree/6a671057ea6aae690b5967ee26a0ddf8452c6297#addformatstring-name-stringregexpfunctionobject-format---ajv"},(0,r.yg)("inlineCode",{parentName:"a"},"addFormat")," method")," accepts."),(0,r.yg)("h3",{id:"async-validation"},"Async validation"),(0,r.yg)("p",null,"Handling async errors is an important part of many applications. Support for this is added in the form of the ",(0,r.yg)("inlineCode",{parentName:"p"},"extraErrors")," prop."),(0,r.yg)("p",null,"For example, a request could be made to some backend when the user submits the form. If that request fails, the errors returned by the backend should be formatted like in the following example."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema, ErrorSchema } from '@rjsf/utils';\nimport validator from '@rjsf/validator-ajv8';\n\nconst schema: RJSFSchema = {\n type: 'object',\n properties: {\n foo: {\n type: 'string',\n },\n candy: {\n type: 'object',\n properties: {\n bar: {\n type: 'string',\n },\n },\n },\n },\n};\n\nconst extraErrors: ErrorSchema = {\n foo: {\n __errors: ['some error that got added as a prop'],\n },\n candy: {\n bar: {\n __errors: ['some error that got added as a prop'],\n },\n },\n};\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("p",null,'An important note is that these errors are "display only" and will not block the user from submitting the form again.'),(0,r.yg)("h3",{id:"ajvoptionsoverrides"},"ajvOptionsOverrides"),(0,r.yg)("p",null,"In version 5, with the advent of the decoupling of the validation implementation from the ",(0,r.yg)("inlineCode",{parentName:"p"},"Form"),", it is now possible to provide additional options to the ",(0,r.yg)("inlineCode",{parentName:"p"},"ajv")," instance used within ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8"),".\nFor instance, if you need more information from ",(0,r.yg)("inlineCode",{parentName:"p"},"ajv")," about errors via the ",(0,r.yg)("inlineCode",{parentName:"p"},"verbose")," option, now you can turn it on!"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv8';\n\nconst schema: RJSFSchema = {\n type: 'string',\n format: 'phone-us',\n};\n\nconst ajvOptionsOverrides = {\n verbose: true,\n};\n\nconst validator = customizeValidator({ ajvOptionsOverrides });\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("h2",{id:"using-the-raw-ajv-instance"},"Using the raw Ajv instance"),(0,r.yg)("p",null,"The ",(0,r.yg)("inlineCode",{parentName:"p"},"customizeValidator()")," function returns the ",(0,r.yg)("inlineCode",{parentName:"p"},"AJV8Validator")," (or ",(0,r.yg)("inlineCode",{parentName:"p"},"AJV6Validator")," depending on the library you use) implementation class, which has an internal raw ",(0,r.yg)("inlineCode",{parentName:"p"},"ajv")," instance within it.\nIf you need to do some deep customization of the instance using any of the ",(0,r.yg)("inlineCode",{parentName:"p"},"ajv")," libraries (like ",(0,r.yg)("inlineCode",{parentName:"p"},"ajv-keywords"),"), you can do so using this raw instance as follows:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-ts"},"import { customizeValidator } from '@rjsf/validator-ajv6';\nimport ajvKeywords from 'ajv-keywords';\n\nconst validator = customizeValidator();\najvKeywords(validator.ajv, ['your-keyword']);\n\n// use your update validator with a `Form`\n")),(0,r.yg)("h2",{id:"ajv8-validator-differences"},"Ajv8 validator differences"),(0,r.yg)("p",null,"There are a few differences in configuring the Ajv 8 validator.\nFirst, there are many things to be aware of related to internal migration from Ajv 6 to 8; see the ",(0,r.yg)("a",{parentName:"p",href:"https://ajv.js.org/v6-to-v8-migration.html"},"migration guide")," for more information."),(0,r.yg)("p",null,"One big difference is that Ajv 8 dropped support for any JSON Schema version before draft-06.\nSo if your schema is using an older format, you have to either upgrade it or stick with the ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv6"),"."),(0,r.yg)("p",null,"Our implementation of ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8")," also utilizes Ajv's internal cache to avoid unnecessarily re-compiling schemas, which can be an expensive operation. The cache key is the schema ",(0,r.yg)("inlineCode",{parentName:"p"},"$id"),"."),(0,r.yg)("p",null,"The ",(0,r.yg)("inlineCode",{parentName:"p"},"ajvOptionsOverrides")," for the Ajv 8 validator are the ones supported by that version and not the Ajv 6 validator.\nSecond, the data formats previously provided in Ajv 6 now need to be added explicitly using the ",(0,r.yg)("inlineCode",{parentName:"p"},"ajv-formats")," package.\nA new ",(0,r.yg)("inlineCode",{parentName:"p"},"ajvFormatOptions")," option is available on the ",(0,r.yg)("inlineCode",{parentName:"p"},"customizeValidator()")," API to be able to configure this.\nAdditionally, a new ",(0,r.yg)("inlineCode",{parentName:"p"},"AjvClass")," option is available on the ",(0,r.yg)("inlineCode",{parentName:"p"},"customizeValidator()")," API to support using one of the other ",(0,r.yg)("a",{parentName:"p",href:"https://ajv.js.org/json-schema.html#json-schema-versions"},"JSON schema versions")," provided by Ajv 8 besides the ",(0,r.yg)("inlineCode",{parentName:"p"},"draft-07")," default.\nFinally, the Ajv 8 validator supports the localization of error messages."),(0,r.yg)("h3",{id:"ajvformatoptions"},"ajvFormatOptions"),(0,r.yg)("p",null,"By default, ALL formats are being added to the default ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8")," that you get when you import it."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport validator from '@rjsf/validator-ajv8';\n\nconst schema: RJSFSchema = {\n type: 'string',\n format: 'email',\n};\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("p",null,"If you don't actually need any of the ",(0,r.yg)("a",{parentName:"p",href:"https://github.com/ajv-validator/ajv-formats#formats"},"ajv-formats")," and want to reduce the memory footprint, then you can turn it off as follows:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv8';\n\nconst schema: RJSFSchema = {\n type: 'string',\n};\n\nconst validator = customizeValidator({ ajvFormatOptions: false });\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("p",null,"If you only need some of them, you can pass any of the ",(0,r.yg)("a",{parentName:"p",href:"https://github.com/ajv-validator/ajv-formats#options"},"options")," to the formatter:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv8';\n\nconst schema: RJSFSchema = {\n type: 'string',\n format: 'date',\n};\n\nconst validator = customizeValidator({ ajvFormatOptions: ['date'] });\n// or\n// const validator = customizeValidator({ ajvFormatOptions: { mode: \"fast\", formats: [\"date\"], keywords: true } });\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("h3",{id:"ajvclass"},"AjvClass"),(0,r.yg)("p",null,"By default, the ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf/validator-ajv8")," uses the ",(0,r.yg)("inlineCode",{parentName:"p"},"draft-07")," schema version.\nIt is possible to use one of the other version it supports, like ",(0,r.yg)("inlineCode",{parentName:"p"},"draft-2019-09")," or ",(0,r.yg)("inlineCode",{parentName:"p"},"draft-2020-12"),".\nNOTE: ",(0,r.yg)("inlineCode",{parentName:"p"},"draft-2020-12")," has breaking changes and hasn't been fully tested with ",(0,r.yg)("inlineCode",{parentName:"p"},"@rjsf"),"."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv8';\nimport Ajv2019 from 'ajv/dist/2019';\n\nconst schema: RJSFSchema = {\n type: 'string',\n format: 'date',\n};\n\nconst validator = customizeValidator({ AjvClass: Ajv2019 });\n// or\n// const validator = customizeValidator({ AjvClass: Ajv2020 });\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("h3",{id:"localization-l10n-support"},"Localization (L10n) support"),(0,r.yg)("p",null,"The Ajv 8 validator supports the localization of error messages using ",(0,r.yg)("a",{parentName:"p",href:"https://github.com/ajv-validator/ajv-i18n"},"ajv-i18n"),".\nIn addition, you may provide a custom solution by implementing a function that conforms to the ",(0,r.yg)("inlineCode",{parentName:"p"},"Localizer")," interface if your language is not supported."),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-ts"},"import { ErrorObject } from 'ajv';\n/** The type describing a function that takes a list of Ajv `ErrorObject`s and localizes them\n */\nexport type Localizer = (errors?: null | ErrorObject[]) => void;\n")),(0,r.yg)("p",null,"NOTE: The ",(0,r.yg)("inlineCode",{parentName:"p"},"ajv-i18n")," validators implement the ",(0,r.yg)("inlineCode",{parentName:"p"},"Localizer")," interface."),(0,r.yg)("h4",{id:"some-examples"},"Some examples"),(0,r.yg)("p",null,"Using a specific locale while including all of ",(0,r.yg)("inlineCode",{parentName:"p"},"ajv-i18n"),":"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv8';\nimport localizer from 'ajv-i18n';\n\nconst schema: RJSFSchema = {\n type: 'string',\n};\n\nconst validator = customizeValidator({}, localizer.it);\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("p",null,"Using a specific locale minimizing the bundle size"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv8';\nimport spanishLocalizer from 'ajv-i18n/localize/es';\n\nconst schema: RJSFSchema = {\n type: 'string',\n};\n\nconst validator = customizeValidator({}, spanishLocalizer);\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("p",null,"An example of a custom ",(0,r.yg)("inlineCode",{parentName:"p"},"Localizer")," implementation:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-tsx"},"import { Form } from '@rjsf/core';\nimport { RJSFSchema } from '@rjsf/utils';\nimport { customizeValidator } from '@rjsf/validator-ajv8';\nimport { ErrorObject } from 'ajv';\n\nfunction localize_ru(errors: null | ErrorObject[] = []) {\n if (!(errors && errors.length)) return;\n errors.forEach(function (error) {\n let outMessage = '';\n\n switch (error.keyword) {\n case 'pattern': {\n outMessage = '\u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437\u0446\u0443 \"' + error.params.pattern + '\"';\n break;\n }\n case 'required': {\n outMessage = '\u043f\u043e\u043b\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f';\n break;\n }\n default:\n outMessage = error.message;\n }\n\n error.message = outMessage;\n });\n}\n\nconst schema: RJSFSchema = {\n type: 'string',\n};\n\nconst validator = customizeValidator({}, localize_ru);\n\nrender(, document.getElementById('app'));\n")),(0,r.yg)("p",null,"NOTES:"),(0,r.yg)("ul",null,(0,r.yg)("li",{parentName:"ul"},"If you provided your own function, modify the list in place."),(0,r.yg)("li",{parentName:"ul"},"You must process all the cases which you need by yourself. See the full list of possible cases ",(0,r.yg)("a",{parentName:"li",href:"https://github.com/ajv-validator/ajv-i18n/blob/master/messages/index.js"},"here"),"."),(0,r.yg)("li",{parentName:"ul"},"Each element in the ",(0,r.yg)("inlineCode",{parentName:"li"},"errors")," list passed to the custom function represent a ",(0,r.yg)("strong",{parentName:"li"},"raw")," error object returned by ajv (",(0,r.yg)("a",{parentName:"li",href:"https://github.com/ajv-validator/ajv/blob/master/docs/api.md#error-objects"},"see doc"),").")))}c.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/docs/assets/js/runtime~main.6e865233.js b/docs/assets/js/runtime~main.6e865233.js new file mode 100644 index 0000000000..8c64bd4b1a --- /dev/null +++ b/docs/assets/js/runtime~main.6e865233.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,c,a,f,b,d={},r={};function t(e){var c=r[e];if(void 0!==c)return c.exports;var a=r[e]={id:e,loaded:!1,exports:{}};return d[e].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}t.m=d,t.c=r,e=[],t.O=(c,a,f,b)=>{if(!a){var d=1/0;for(i=0;i=b)&&Object.keys(t.O).every((e=>t.O[e](a[o])))?a.splice(o--,1):(r=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[a,f,b]},t.n=e=>{var c=e&&e.__esModule?()=>e.default:()=>e;return t.d(c,{a:c}),c},a=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,t.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var b=Object.create(null);t.r(b);var d={};c=c||[null,a({}),a([]),a(a)];for(var r=2&f&&e;"object"==typeof r&&!~c.indexOf(r);r=a(r))Object.getOwnPropertyNames(r).forEach((c=>d[c]=()=>e[c]));return d.default=()=>e,t.d(b,d),b},t.d=(e,c)=>{for(var a in c)t.o(c,a)&&!t.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:c[a]})},t.f={},t.e=e=>Promise.all(Object.keys(t.f).reduce(((c,a)=>(t.f[a](e,c),c)),[])),t.u=e=>"assets/js/"+({28:"55828450",108:"8bc2ac95",340:"d330ea77",392:"4f0869c8",550:"ea6a4d96",588:"38fbb798",1136:"81423478",1142:"76407226",1156:"5f32cc67",1200:"d5ac8034",1272:"471cbf69",1468:"0b3cdf12",1480:"3a4b2402",1504:"6b9b26b2",1556:"d7074bc5",1584:"d50357eb",1588:"2f92f8af",1608:"6f5f68c3",1748:"18754115",1856:"65a42dc2",1864:"c49a42af",1990:"e02c3a1f",2076:"165933ca",2128:"8073c6d8",2184:"4f1007ae",2256:"db61454e",2276:"1bfb7197",2454:"e6ac1264",2508:"400ce25c",2544:"ad4e2fc7",2648:"f5464f7a",2768:"6cc77d9e",3312:"3ddf1ed7",3438:"7c80f27c",3564:"ce8c3ba3",3688:"697c973a",3824:"17c4f025",3940:"219dd62e",4112:"e7c8e838",4130:"62a4c0df",4200:"bc30978e",4276:"479b786b",4608:"e5c1ae69",5108:"5a56bbfa",5472:"b55dc87a",5696:"935f2afb",5712:"4d54d076",5784:"f6a427b5",5900:"64eb1cb9",5904:"f3f7bfff",5988:"41ef4206",6120:"beeb8746",6128:"87c83d9b",6256:"f0347b45",6372:"92d5580e",6736:"e59d324b",6752:"17896441",6848:"516b911c",6940:"5fee4058",6968:"1a47775b",6976:"e1e16817",7368:"732cba76",7440:"154a8133",7488:"6544de8f",7681:"5137640e",7744:"5a7d1c91",7960:"deff9645",8388:"cd42c997",8456:"2ac27c21",8724:"7112b103",9076:"8bda08be",9196:"cd51a22b",9367:"8c1b5197",9548:"c61b9675",9605:"5802ae45",9648:"1a4e3797",9652:"e187e1d9",9656:"1be78505",9660:"9ff188b7",9768:"294529be",9860:"ce18b779",9904:"fd16ad34",9908:"791a9c83"}[e]||e)+"."+{28:"2b065623",108:"710647d2",340:"c19ffc63",392:"74466f1a",550:"c453fa3b",588:"88a00c95",1136:"e2c0b58a",1142:"91058388",1156:"b9ecc864",1200:"9fbd29ef",1272:"f8707b9b",1468:"70fff40d",1480:"b98dbc3f",1504:"a579b37c",1556:"d62a8b62",1584:"6d8d0ca1",1588:"d69fb227",1608:"8a452b94",1748:"93fd8f6a",1856:"abfdb249",1864:"527fc59d",1990:"6ef6ed69",2076:"43fe2c40",2128:"d4bdcd1b",2184:"87910254",2256:"10e78a7e",2272:"ff825110",2276:"0b382810",2454:"9cdbf12d",2508:"b910a301",2544:"15dda5e6",2648:"f236cd1c",2768:"12b9f768",3312:"c0a21af0",3438:"2a0ffadc",3564:"fe01ff58",3644:"bc6de301",3688:"cb0d59e5",3824:"36207f37",3940:"33672f6b",4112:"e82cb434",4130:"f86e9db3",4200:"aaaccd6c",4276:"cb5d0ad2",4608:"55ec06e7",5108:"1bf901f7",5472:"3a7d5a8c",5696:"dbbad3de",5712:"77657f15",5784:"4420eb6f",5900:"56a16faf",5904:"76b393c6",5988:"5f2db8e7",6120:"e099f4cc",6128:"c0274ed1",6256:"fcb5fcbc",6372:"8e91d9ae",6736:"55cf3e02",6752:"1d620fb3",6848:"851e7998",6940:"5bbbed9c",6968:"b4e1f6af",6976:"56f0f6bd",7368:"11b6d2ef",7440:"ae9a173a",7488:"743cf46a",7681:"3d559b90",7744:"0fd0b4f2",7847:"810f0898",7960:"2926887e",8240:"d873a58c",8388:"c98fb299",8456:"cb44e6ce",8724:"6eb1d8ee",9076:"d10f7570",9196:"73c56f1d",9367:"a14c2dac",9548:"2878a326",9605:"7836f405",9648:"a72caa1f",9652:"e381802d",9656:"0934b729",9660:"e1cab0e8",9768:"9e1d7186",9860:"0b01eb04",9904:"fb23510f",9908:"1acfc0a7"}[e]+".js",t.miniCssF=e=>{},t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),t.o=(e,c)=>Object.prototype.hasOwnProperty.call(e,c),f={},b="@rjsf/docs:",t.l=(e,c,a,d)=>{if(f[e])f[e].push(c);else{var r,o;if(void 0!==a)for(var n=document.getElementsByTagName("script"),i=0;i{r.onerror=r.onload=null,clearTimeout(l);var b=f[e];if(delete f[e],r.parentNode&&r.parentNode.removeChild(r),b&&b.forEach((e=>e(a))),c)return c(a)},l=setTimeout(s.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=s.bind(null,r.onerror),r.onload=s.bind(null,r.onload),o&&document.head.appendChild(r)}},t.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.p="/react-jsonschema-form/docs/",t.gca=function(e){return e={17896441:"6752",18754115:"1748",55828450:"28",76407226:"1142",81423478:"1136","8bc2ac95":"108",d330ea77:"340","4f0869c8":"392",ea6a4d96:"550","38fbb798":"588","5f32cc67":"1156",d5ac8034:"1200","471cbf69":"1272","0b3cdf12":"1468","3a4b2402":"1480","6b9b26b2":"1504",d7074bc5:"1556",d50357eb:"1584","2f92f8af":"1588","6f5f68c3":"1608","65a42dc2":"1856",c49a42af:"1864",e02c3a1f:"1990","165933ca":"2076","8073c6d8":"2128","4f1007ae":"2184",db61454e:"2256","1bfb7197":"2276",e6ac1264:"2454","400ce25c":"2508",ad4e2fc7:"2544",f5464f7a:"2648","6cc77d9e":"2768","3ddf1ed7":"3312","7c80f27c":"3438",ce8c3ba3:"3564","697c973a":"3688","17c4f025":"3824","219dd62e":"3940",e7c8e838:"4112","62a4c0df":"4130",bc30978e:"4200","479b786b":"4276",e5c1ae69:"4608","5a56bbfa":"5108",b55dc87a:"5472","935f2afb":"5696","4d54d076":"5712",f6a427b5:"5784","64eb1cb9":"5900",f3f7bfff:"5904","41ef4206":"5988",beeb8746:"6120","87c83d9b":"6128",f0347b45:"6256","92d5580e":"6372",e59d324b:"6736","516b911c":"6848","5fee4058":"6940","1a47775b":"6968",e1e16817:"6976","732cba76":"7368","154a8133":"7440","6544de8f":"7488","5137640e":"7681","5a7d1c91":"7744",deff9645:"7960",cd42c997:"8388","2ac27c21":"8456","7112b103":"8724","8bda08be":"9076",cd51a22b:"9196","8c1b5197":"9367",c61b9675:"9548","5802ae45":"9605","1a4e3797":"9648",e187e1d9:"9652","1be78505":"9656","9ff188b7":"9660","294529be":"9768",ce18b779:"9860",fd16ad34:"9904","791a9c83":"9908"}[e]||e,t.p+t.u(e)},(()=>{var e={296:0,2176:0};t.f.j=(c,a)=>{var f=t.o(e,c)?e[c]:void 0;if(0!==f)if(f)a.push(f[2]);else if(/^2(17|9)6$/.test(c))e[c]=0;else{var b=new Promise(((a,b)=>f=e[c]=[a,b]));a.push(f[2]=b);var d=t.p+t.u(c),r=new Error;t.l(d,(a=>{if(t.o(e,c)&&(0!==(f=e[c])&&(e[c]=void 0),f)){var b=a&&("load"===a.type?"missing":a.type),d=a&&a.target&&a.target.src;r.message="Loading chunk "+c+" failed.\n("+b+": "+d+")",r.name="ChunkLoadError",r.type=b,r.request=d,f[1](r)}}),"chunk-"+c,c)}},t.O.j=c=>0===e[c];var c=(c,a)=>{var f,b,d=a[0],r=a[1],o=a[2],n=0;if(d.some((c=>0!==e[c]))){for(f in r)t.o(r,f)&&(t.m[f]=r[f]);if(o)var i=o(t)}for(c&&c(a);n Contributing | react-jsonschema-form - + @@ -33,7 +33,7 @@ the latest changelog entry in CHANGELOG.md to make the release notes, and update as necessary.

This will trigger a GitHub Actions pipeline that will build and publish all packages to npm.

The package is published through an automation token belonging to the rjsf-bot user on npm. This token is stored as the NPM_TOKEN secret on GitHub Actions.

Releasing docs

Docs are automatically published to GitHub Pages when the main branch is updated.

We are currently in the process of automatically configuring versionable documentation on our new docs site.

Releasing the playground

The playground automatically gets deployed from GitHub Pages.

If you need to manually publish the latest playground to https://rjsf-team.github.io/react-jsonschema-form/, though, run:

cd packages/playground
npm run publish-to-gh-pages
- + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index c4709d11c3..67afbd4b0e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -4,13 +4,13 @@ Introduction | react-jsonschema-form - +
Version: v5

react-jsonschema-form

Build Status

A simple React component capable of building HTML forms out of a JSON schema.

A live playground is hosted on GitHub Pages:

Playground

Philosophy

react-jsonschema-form is meant to automatically generate a React form based on a JSON Schema. If you want to generate a form for any data, sight unseen, simply given a JSON schema, react-jsonschema-form may be for you. If you have a priori knowledge of your data and want a toolkit for generating forms for it, you might look elsewhere.

react-jsonschema-form also comes with tools such as uiSchema and other form props to customize the look and feel of the form beyond the default themes.

Installation

First install the dependencies from npm, along with a validator implementation (such as @rjsf/validator-ajv8):

$ npm install @rjsf/core @rjsf/utils @rjsf/validator-ajv8 --save

Then import the dependencies as follows:

import Form from '@rjsf/core';
import validator from '@rjsf/validator-ajv8';

Our latest version requires React 16+.

Usage

import Form from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
title: 'Todo',
type: 'object',
required: ['title'],
properties: {
title: { type: 'string', title: 'Title', default: 'A new task' },
done: { type: 'boolean', title: 'Done?', default: false },
},
};

const log = (type) => console.log.bind(console, type);

render(
<Form
schema={schema}
validator={validator}
onChange={log('changed')}
onSubmit={log('submitted')}
onError={log('errors')}
/>,
document.getElementById('app')
);

Theming

For more information on what themes we support, see Using Themes.

License

Apache 2

Credits

mozilla-services-logoThis project initially started as a mozilla-services project.
browserstack logoTesting is powered by BrowserStack.
netlify logoDeploy Previews are provided by Netlify.

Who uses react-jsonschema-form?

  • ...

Add your own company / organization by making a pull request.

- + \ No newline at end of file diff --git a/docs/json-schema/arrays/index.html b/docs/json-schema/arrays/index.html index 9ec223dd57..5589f2bf12 100644 --- a/docs/json-schema/arrays/index.html +++ b/docs/json-schema/arrays/index.html @@ -4,7 +4,7 @@ Arrays | react-jsonschema-form - + @@ -12,7 +12,7 @@
Version: v5

Arrays

Arrays are defined with a type equal to array, and array items' schemas are specified in the items keyword.

Arrays of a single field

Arrays of a single field type can be specified as follows:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'string',
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Arrays of objects

Arrays of objects can be specified as follows:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'object',
properties: {
name: {
type: 'string',
},
},
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

uiSchema for array items

To specify a uiSchema that applies to array items, specify the uiSchema value within the items property:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'string',
},
};

const uiSchema = {
items: {
'ui:widget': 'textarea',
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

The additionalItems keyword

The additionalItems keyword allows the user to add additional items of a given schema. For example:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'string',
},
additionalItems: {
type: 'boolean',
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Array item uiSchema options

Any of these options can be set globally if they are contained within the ui:globalOptions block. They can also be overridden on a per-field basis inside a ui:options block as shown below.

orderable option

Array items are orderable by default, and react-jsonschema-form renders move up/down buttons alongside them. The uiSchema orderable options allows you to disable ordering:

import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'string',
},
};

const uiSchema: UiSchema = {
'ui:options': {
orderable: false,
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

addable option

If either items or additionalItems contains a schema object, an add button for new items is shown by default. You can turn this off with the addable option in uiSchema:

import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'string',
},
};

const uiSchema: UiSchema = {
'ui:options': {
addable: false,
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

copyable option

A copy button is NOT shown by default for an item if items contains a schema object, or the item is an additionalItems instance. You can turn this ON with the copyable option in uiSchema:

import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'string',
},
};

const uiSchema: UiSchema = {
'ui:options': {
copyable: true,
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

removable option

A remove button is shown by default for an item if items contains a schema object, or the item is an additionalItems instance. You can turn this off with the removable option in uiSchema:

import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'string',
},
};

const uiSchema: UiSchema = {
'ui:options': {
removable: false,
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

Multiple-choice list

The default behavior for array fields is a list of text inputs with add/remove buttons. There are two alternative widgets for picking multiple elements from a list of choices. Typically, this applies when a schema has an enum list for the items property of an array field, and the uniqueItems property set to true.

Example:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
title: 'A multiple-choice list',
items: {
type: 'string',
enum: ['foo', 'bar', 'fuzz', 'qux'],
},
uniqueItems: true,
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

By default, this will render a multiple select box. If you prefer a list of checkboxes, just set the uiSchema ui:widget directive to checkboxes for that field:

import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
title: 'A multiple-choice list',
items: {
type: 'string',
enum: ['foo', 'bar', 'fuzz', 'qux'],
},
uniqueItems: true,
};

const uiSchema: UiSchema = {
'ui:widget': 'checkboxes',
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

Custom widgets

In addition to ArrayFieldTemplate you use your own widget by providing it to the uiSchema with the property of ui:widget.

Example:

import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const CustomSelectComponent = (props) => {
return (
<select>
{props.value.map((item, index) => (
<option key={index} id='custom-select'>
{item}
</option>
))}
</select>
);
};

const schema: RJSFSchema = {
type: 'array',
title: 'A multiple-choice list',
items: {
type: 'string',
},
};

const uiSchema: UiSchema = {
'ui:widget': 'CustomSelect',
};

const widgets = {
CustomSelect: CustomSelectComponent,
};

render(
<Form schema={schema} uiSchema={uiSchema} widgets={widgets} validator={validator} />,
document.getElementById('app')
);

Specifying the minimum or maximum number of items

Note that when an array property is marked as required, an empty array is considered valid. If the array needs to be populated, you can specify the minimum number of items using the minItems property.

Example:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
minItems: 2,
title: 'A multiple-choice list',
items: {
type: 'string',
enum: ['foo', 'bar', 'fuzz', 'qux'],
},
uniqueItems: true,
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

You can also specify the maximum number of items in an array using the maxItems property.

Inline checkboxes

By default, checkboxes are stacked. If you prefer them inline, set the inline property to true:

import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'array',
minItems: 2,
title: 'A multiple-choice list',
items: {
type: 'string',
enum: ['foo', 'bar', 'fuzz', 'qux'],
},
uniqueItems: true,
};

const uiSchema: UiSchema = {
'ui:widget': 'checkboxes',
'ui:options': {
inline: true,
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));
- + \ No newline at end of file diff --git a/docs/json-schema/definitions/index.html b/docs/json-schema/definitions/index.html index 337e60b5da..e9ac967262 100644 --- a/docs/json-schema/definitions/index.html +++ b/docs/json-schema/definitions/index.html @@ -4,13 +4,13 @@ Schema definitions and references | react-jsonschema-form - +
Version: v5

Schema definitions and references

This library partially supports inline schema definition dereferencing, which allows you to re-use parts of your schema:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
definitions: {
address: {
type: 'object',
properties: {
street_address: { type: 'string' },
city: { type: 'string' },
state: { type: 'string' },
},
required: ['street_address', 'city', 'state'],
},
},
type: 'object',
properties: {
billing_address: { $ref: '#/definitions/address' },
shipping_address: { $ref: '#/definitions/address' },
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Note that this library only supports local definition referencing. The value in the $ref keyword should be a JSON Pointer in URI fragment identifier format.

- + \ No newline at end of file diff --git a/docs/json-schema/dependencies/index.html b/docs/json-schema/dependencies/index.html index 66c780a38a..adae6e8329 100644 --- a/docs/json-schema/dependencies/index.html +++ b/docs/json-schema/dependencies/index.html @@ -4,14 +4,14 @@ Dependencies | react-jsonschema-form - +
Version: v5

Dependencies

react-jsonschema-form supports the dependencies keyword from an earlier draft of JSON Schema (note that this is not part of the latest JSON Schema spec, though). Dependencies can be used to create dynamic schemas that change fields based on what data is entered.

Property dependencies

This library supports conditionally making fields required based on the presence of other fields.

Unidirectional

In the following example the billing_address field will be required if credit_card is defined.

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',

properties: {
name: { type: 'string' },
credit_card: { type: 'number' },
billing_address: { type: 'string' },
},

required: ['name'],

dependencies: {
credit_card: ['billing_address'],
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Bidirectional

In the following example the billing_address field will be required if credit_card is defined and the credit_card field will be required if billing_address is defined, making them both required if either is defined.

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',

properties: {
name: { type: 'string' },
credit_card: { type: 'number' },
billing_address: { type: 'string' },
},

required: ['name'],

dependencies: {
credit_card: ['billing_address'],
billing_address: ['credit_card'],
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

(Sample schemas courtesy of the Space Telescope Science Institute)

Schema dependencies

This library also supports modifying portions of a schema based on form data.

Conditional

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',

properties: {
name: { type: 'string' },
credit_card: { type: 'number' },
},

required: ['name'],

dependencies: {
credit_card: {
properties: {
billing_address: { type: 'string' },
},
required: ['billing_address'],
},
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

In this example the billing_address field will be displayed in the form if credit_card is defined.

(Sample schemas courtesy of the Space Telescope Science Institute)

Dynamic

The JSON Schema standard says that the dependency is triggered if the property is present. However, sometimes it's useful to have more sophisticated rules guiding the application of the dependency. For example, maybe you have three possible values for a field, and each one should lead to adding a different question. For this, we support a very restricted use of the oneOf keyword.

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
title: 'Person',
type: 'object',
properties: {
'Do you have any pets?': {
type: 'string',
enum: ['No', 'Yes: One', 'Yes: More than one'],
default: 'No',
},
},
required: ['Do you have any pets?'],
dependencies: {
'Do you have any pets?': {
oneOf: [
{
properties: {
'Do you have any pets?': {
enum: ['No'],
},
},
},
{
properties: {
'Do you have any pets?': {
enum: ['Yes: One'],
},
'How old is your pet?': {
type: 'number',
},
},
required: ['How old is your pet?'],
},
{
properties: {
'Do you have any pets?': {
enum: ['Yes: More than one'],
},
'Do you want to get rid of any?': {
type: 'boolean',
},
},
required: ['Do you want to get rid of any?'],
},
],
},
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

In this example the user is prompted with different follow-up questions dynamically based on their answer to the first question.

In these examples, the "Do you have any pets?" question is validated against the corresponding property in each schema in the oneOf array. If exactly one matches, the rest of that schema is merged with the existing schema.

- + \ No newline at end of file diff --git a/docs/json-schema/index.html b/docs/json-schema/index.html index 47ed4aa0cf..8bc3dac4f3 100644 --- a/docs/json-schema/index.html +++ b/docs/json-schema/index.html @@ -4,13 +4,13 @@ JSON Schema | react-jsonschema-form - + - + \ No newline at end of file diff --git a/docs/json-schema/objects/index.html b/docs/json-schema/objects/index.html index 608754a2c0..11dc2654d2 100644 --- a/docs/json-schema/objects/index.html +++ b/docs/json-schema/objects/index.html @@ -4,13 +4,13 @@ Objects | react-jsonschema-form - +
Version: v5

Objects

Object properties

Objects are defined with a type equal to object and properties specified in the properties keyword.

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
title: 'My title',
description: 'My description',
type: 'object',
properties: {
name: {
type: 'string',
},
age: {
type: 'number',
},
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Required properties

You can specify which properties are required using the required attribute:

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
title: 'My title',
description: 'My description',
type: 'object',
properties: {
name: {
type: 'string',
},
age: {
type: 'number',
},
},
required: ['name'],
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Specifying property order

Since the order of object properties in Javascript and JSON is not guaranteed, the uiSchema object spec allows you to define the order in which properties are rendered using the ui:order property:

import { Form } from '@rjsf/core';
import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',
properties: {
foo: { type: 'string' },
bar: { type: 'string' },
},
};

const uiSchema: UiSchema = {
'ui:order': ['bar', 'foo'],
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

If a guaranteed fixed order is only important for some fields, you can insert a wildcard "*" item in your ui:order definition. All fields that are not referenced explicitly anywhere in the list will be rendered at that point:

import { UiSchema } from '@rjsf/utils';

const uiSchema: UiSchema = {
'ui:order': ['bar', '*'],
};

Additional properties

The additionalProperties keyword allows the user to add properties with arbitrary key names. Set this keyword equal to a schema object:

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',
properties: {
name: {
type: 'string',
},
},
additionalProperties: {
type: 'number',
enum: [1, 2, 3],
},
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

In this way, an add button for new properties is shown by default.

You can also define uiSchema options for additionalProperties by setting the additionalProperties attribute in the uiSchema.

expandable option

You can turn support for additionalProperties off with the expandable option in uiSchema:

import { UiSchema } from '@rjsf/utils';

const uiSchema: UiSchema = {
'ui:options': {
expandable: false,
},
};
- + \ No newline at end of file diff --git a/docs/json-schema/oneof/index.html b/docs/json-schema/oneof/index.html index dbdfd02223..3c295ecf39 100644 --- a/docs/json-schema/oneof/index.html +++ b/docs/json-schema/oneof/index.html @@ -4,13 +4,13 @@ oneOf, anyOf, and allOf | react-jsonschema-form - +
Version: v5

oneOf, anyOf, and allOf

react-jsonschema-form supports custom widgets for oneOf, anyOf, and allOf.

  • A schema with oneOf is valid if exactly one of the subschemas is valid.
  • A schema with anyOf is valid if at least one of the subschemas is valid.
  • A schema with allOf is valid if all of the subschemas are valid.

oneOf

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',
oneOf: [
{
properties: {
lorem: {
type: 'string',
},
},
required: ['lorem'],
},
{
properties: {
ipsum: {
type: 'string',
},
},
required: ['ipsum'],
},
],
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

anyOf

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',
anyOf: [
{
properties: {
lorem: {
type: 'string',
},
},
required: ['lorem'],
},
{
properties: {
lorem: {
type: 'string',
},
ipsum: {
type: 'string',
},
},
},
],
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

allOf

When allOf is specified in a schema, react-jsonschema-form uses the json-schema-merge-allof library to merge the specified subschemas to create a combined subschema that is valid. For example, the below schema evaluates to a combined subschema of {type: "boolean"}:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
title: 'Field',
allOf: [
{
type: ['string', 'boolean'],
},
{
type: 'boolean',
},
],
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));
- + \ No newline at end of file diff --git a/docs/json-schema/single/index.html b/docs/json-schema/single/index.html index 9bccd9df80..74556be5fd 100644 --- a/docs/json-schema/single/index.html +++ b/docs/json-schema/single/index.html @@ -4,13 +4,13 @@ Single fields | react-jsonschema-form - +
Version: v5

Single fields

The simplest example of a JSON Schema contains only a single field. The field type is determined by the type parameter.

Field types

The base field types in JSON Schema include:

  • string
  • number
  • integer
  • boolean
  • null

Here is an example of a string field:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'string',
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Titles and descriptions

Fields can have titles and descriptions specified by the title keyword in the schema and the description keyword in the schema, respectively. These two can also be overridden by the ui:title and ui:description keywords in the uiSchema.

Description can render markdown. This feature is disabled by default. It needs to be enabled by the ui:enableMarkdownInDescription keyword and setting to true. Read more about markdown options in the markdown-to-jsx official docs.

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
title: 'My form',
description: 'My description',
type: 'string',
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Enumerated values

All base schema types support the enum attribute, which restricts the user to select among a list of options. For example:

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'string',
enum: ['one', 'two', 'three'],
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Custom labels for enum fields

JSON Schema supports the following approaches to enumerations using oneOf/anyOf; react-jsonschema-form supports it as well.

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'number',
anyOf: [
{
type: 'number',
title: 'one',
enum: [1],
},
{
type: 'number',
title: 'two',
enum: [2],
},
{
type: 'number',
title: 'three',
enum: [3],
},
],
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));
import { RJSFSchema } from '@rjsf/utils';

const schema: RJSFSchema = {
type: 'number',
oneOf: [
{ const: 1, title: 'one' },
{ const: 2, title: 'two' },
{ const: 3, title: 'three' },
],
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

In your JSON Schema, you may also specify enumNames, a non-standard field which RJSF can use to label an enumeration. This behavior is deprecated and will be removed in a future major release of RJSF. Use the "ui:enumNames" property in the uiSchema instead.

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'number',
enum: [1, 2, 3],
enumNames: ['one', 'two', 'three'],
};
render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Same example using the uiSchema's ui:enumNames instead.

import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'number',
enum: [1, 2, 3],
};
const uiSchema: UiSchema = {
'ui:enumNames': ['one', 'two', 'three'],
};
render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

Disabled attribute for enum fields

To disable an option, use the ui:enumDisabled property in the uiSchema.

import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'boolean',
enum: [true, false],
};

const uiSchema: UiSchema = {
'ui:enumDisabled': [true],
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

Nullable types

JSON Schema supports specifying multiple types in an array; however, react-jsonschema-form only supports a restricted subset of this -- nullable types, in which an element is either a given type or equal to null.

import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: ['string', 'null'],
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));
- + \ No newline at end of file diff --git a/docs/migration-guides/index.html b/docs/migration-guides/index.html index d60556c93f..8bfb824434 100644 --- a/docs/migration-guides/index.html +++ b/docs/migration-guides/index.html @@ -4,13 +4,13 @@ Migration Guides | react-jsonschema-form - + - + \ No newline at end of file diff --git a/docs/migration-guides/v2.x upgrade guide/index.html b/docs/migration-guides/v2.x upgrade guide/index.html index 4d09e6185d..64e15d8cfa 100644 --- a/docs/migration-guides/v2.x upgrade guide/index.html +++ b/docs/migration-guides/v2.x upgrade guide/index.html @@ -4,13 +4,13 @@ 2.x Upgrade Guide | react-jsonschema-form - +
Version: v5

2.x Upgrade Guide

Changes from v1 -> v2

Breaking changes

  • We now officially support the @rjsf/material-ui theme. We use a monorepo with Lerna and have published two packages (@rjsf/core and @rjsf/material-ui) with this version number. Note that react-jsonschema-form has been renamed to @rjsf/core (#1642)
  • Combine all themes into a single playground (#1539, #1607, #1623)
  • Remove ui:order console warning about extraneous properties (#1508)
  • Capitalized Yes and No defaults (#1395)
  • Fix id of oneof and anyof select (#1212). The oneof select id is now suffixed by __oneof_select and the anyof select by __anyof_select.
  • React 16+ is now a peer dependency (#1408)
  • We no longer actively support Node version < 8 (#1462)
  • Removed setState, setImmediate, safeRenderCompletion helpers/hacks (#1454, #1720)
  • Inject defaults in arrays (#1499)

Features

  • Add material-ui theme in the main repo (#1420) (note: has not been fully integrated yet -- this will be fully integrated when we publish multiple packages with lerna - #1501)
  • Add extraErrors prop for async validation (#1444)
  • Add support for overriding UnsupportedField (#1660)

Fixes

  • Fix issue with false as formData on radio components (#1438)
  • Security patches (#1458, #1459)
  • Memo components in custom widgets and fields. (#1447)
  • Introduce Form autoComplete attribute and deprecate autocomplete (#1483)
  • Rewrite mergeSchemas to fix schema dependencies merging (#1476)
  • Update arrays correctly when changing index (#1485)
  • Update anyOf schema to correctly update items in an array (#1491)
  • Update schema to re-render when idschema changes (#1493)
  • Make sure BooleanField supports an overridable DescriptionField (#1594)
  • Export typings (#1607)
- + \ No newline at end of file diff --git a/docs/migration-guides/v3.x upgrade guide/index.html b/docs/migration-guides/v3.x upgrade guide/index.html index 892bdbe1b1..1510cd866c 100644 --- a/docs/migration-guides/v3.x upgrade guide/index.html +++ b/docs/migration-guides/v3.x upgrade guide/index.html @@ -4,13 +4,13 @@ 3.x Upgrade Guide | react-jsonschema-form - +
Version: v5

3.x Upgrade Guide

Breaking changes

Node support

Dropped support for Node 8, 9, 10. Minimum supported version of Node.js is now 12.

Dereferenced schemas for anyOf/allOf options

MultiSchemaField's options interface is different. Before, an option could include a $ref. Now, any option with a reference will be resolved/dereferenced when given as props for MultiSchemaField.

Help field IDs

IDs for Help fields are now suffixed by __help so that the IDs are unique. Previously, their IDs would be nonexistent or the same as the fields that they were describing.

Bring your own polyfills

core-js@2 has been removed from @rjsf/core. See more about the rationale here.

If you're using a framework like Create React App, Gatsby, Next.js, or transpiling code through something like @babel/preset-env, polyfills are already included there and you won't have to do anything.

If you were directly depending on @rjsf/core's @babel/runtime pulling in core-js@2, just npm install core-js and using a side effectful import at the top of your entry point (import 'core-js') might be enough.

For a slightly more elaborate setup, @babel/preset-env is probably a good second choice.

From @babel/preset-env's docs

We leverage [browserslist, compat-table, and electron-to-chromium] to maintain mappings of which version of our supported target environments gained support of a JavaScript syntax or browser feature, as well as a mapping of those syntaxes and features to Babel transform plugins and core-js polyfills.

- + \ No newline at end of file diff --git a/docs/migration-guides/v4.x upgrade guide/index.html b/docs/migration-guides/v4.x upgrade guide/index.html index 162e7c8a36..f3c88b175e 100644 --- a/docs/migration-guides/v4.x upgrade guide/index.html +++ b/docs/migration-guides/v4.x upgrade guide/index.html @@ -4,13 +4,13 @@ 4.x Upgrade Guide | react-jsonschema-form - +
Version: v5

4.x Upgrade Guide

Breaking changes

React version

No longer actively supporting React version < 16.3. The minimum supported version of React is now 16.3. Discussion can be found here

@rjsf/material-ui package - Minimum version of material-ui 4

If you are using the material-ui 4 theme, @material-ui/core and @material-ui/icons packages should be updated to the latest versions. The minimum versions supported for @material-ui/core and @material-ui/icons are 4.12.0 and 4.11.1 respectively. This change is required for support for the material-ui version 5 theme

- + \ No newline at end of file diff --git a/docs/migration-guides/v5.x upgrade guide/index.html b/docs/migration-guides/v5.x upgrade guide/index.html index 06101253cb..5e8ad8deca 100644 --- a/docs/migration-guides/v5.x upgrade guide/index.html +++ b/docs/migration-guides/v5.x upgrade guide/index.html @@ -4,7 +4,7 @@ 5.x Upgrade Guide | react-jsonschema-form - + @@ -56,7 +56,7 @@ As a result, the MuiComponentContext, MuiForm5, Theme5 components and the useMuiComponent hook were removed from the export. In addition, the /v4 and /v5 sub-packages were also removed.

Migrating for Material UI version 4

If you were using this theme for Material UI version 4 AND you were using the sub-package, simply remove the /v4 from your imports.

If you modified your Typescript configuration for the /v4 sub-package, remove the following from your tsconfig.json:

{
...
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"@rjsf/material-ui/*": ["node_modules/@rjsf/material-ui/dist/*"]
}
}
}

If you modified your Jest configuration for the /v4 sub-package, remove the following from your jest.config.json:

  "moduleNameMapper": {
"@rjsf/material-ui/v4": "<rootDir>/node_modules/@rjsf/material-ui/dist/v4.js"
},

Migrating for Material UI version 5

If you were using this theme for Material UI version 5, you will want to use @rjsf/mui instead. See below for some before and after examples.

If you modified your Typescript configuration for the /v5 sub-package, remove the following from your tsconfig.json:

{
...
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"@rjsf/material-ui/*": ["node_modules/@rjsf/material-ui/dist/*"]
}
}
}

If you modified your Jest configuration for the /v5 sub-package, remove the following from your jest.config.json:

  "moduleNameMapper": {
"@rjsf/material-ui/v5": "<rootDir>/node_modules/@rjsf/material-ui/dist/v5.js"
},
Before
import Form5 from '@rjsf/material-ui';

or

import Form from '@rjsf/material-ui/v5';

or

import { withTheme } from '@rjsf/core';
import { Theme } from '@rjsf/material-ui/v5';
// Make modifications to the theme with your own fields and widgets
const Form = withTheme(Theme);

or

import { withTheme } from '@rjsf/core';
import { Theme as Theme5 } from '@rjsf/material-ui';
// Make modifications to the theme with your own fields and widgets
const Form = withTheme(Theme5);
After
import Form from '@rjsf/mui';

or

import { withTheme } from '@rjsf/core';
import { Theme } from '@rjsf/mui';
// Make modifications to the theme with your own fields and widgets
const Form = withTheme(Theme);
- + \ No newline at end of file diff --git a/docs/quickstart/index.html b/docs/quickstart/index.html index 032322ab6b..a854edf59a 100644 --- a/docs/quickstart/index.html +++ b/docs/quickstart/index.html @@ -4,7 +4,7 @@ Quickstart | react-jsonschema-form - + @@ -15,7 +15,7 @@ uiSchema should be {key: value}, where key is the property key and value is an object with the uiSchema configuration for that particular property. For example:

import Form from '@rjsf/core';
import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
title: 'Test form',
type: 'object',
properties: {
name: {
type: 'string',
},
age: {
type: 'number',
},
},
};

const uiSchema: UiSchema = {
name: {
'ui:classNames': 'custom-class-name',
},
age: {
'ui:classNames': 'custom-class-age',
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

Form initialization

Often you'll want to prefill a form with existing data; this is done by passing a formData prop object matching the schema:

import Form from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',
properties: {
title: {
type: 'string',
},
done: {
type: 'boolean',
},
},
};

const formData = {
title: 'First task',
done: true,
};

render(<Form schema={schema} formData={formData} validator={validator} />, document.getElementById('app'));

Note: If your form has a single field, pass a single value to formData. ex: formData="Charlie"

WARNING: If you have situations where your parent component can re-render, make sure you listen to the onChange event and update the data you pass to the formData attribute.

Form event handlers

You can use event handlers such as onChange, onError, onSubmit, onFocus, and onBlur on the <Form /> component; see the Form Props Reference for more details.

Controlled component

By default, <Form /> is an uncontrolled component. To make it a controlled component, use the onChange and formData props as in the below example:

import Form from '@rjsf/core';
import validator from '@rjsf/validator-ajv8';

const App = () => {
const [formData, setFormData] = React.useState(null);
return (
<Form
schema={{ type: 'string' }}
formData={formData}
onChange={(e) => setFormData(e.formData)}
validator={validator}
/>
);
};

render(<App />, document.getElementById('app'));
- + \ No newline at end of file diff --git a/docs/search/index.html b/docs/search/index.html index 9dee70c429..ad5361898e 100644 --- a/docs/search/index.html +++ b/docs/search/index.html @@ -4,13 +4,13 @@ Search the documentation | react-jsonschema-form - + - + \ No newline at end of file diff --git a/docs/usage/index.html b/docs/usage/index.html index 28e592d08a..c5f8f4476e 100644 --- a/docs/usage/index.html +++ b/docs/usage/index.html @@ -4,13 +4,13 @@ Usage and Customization | react-jsonschema-form - + - + \ No newline at end of file diff --git a/docs/usage/themes/index.html b/docs/usage/themes/index.html index 65edf3a101..a16cbfea63 100644 --- a/docs/usage/themes/index.html +++ b/docs/usage/themes/index.html @@ -4,7 +4,7 @@ Themes | react-jsonschema-form - + @@ -12,7 +12,7 @@
Version: v5

Themes

By default, this library renders form fields and widgets leveraging the Bootstrap semantics, meaning that you must load the Bootstrap stylesheet on the page to view the form properly. You can use another theme by importing one of the packages listed below.

Supported themes

Theme NameStatusPackage Name / Link
antdPublished@rjsf/antd
Bootstrap 3 (default)Published@rjsf/core
Bootstrap 4Published@rjsf/bootstrap-4
Chakra UIPublished@rjsf/chakra-ui
fluent-uiPublished@rjsf/fluent-ui
fluentui-rcPublished@rjsf/fluentui-rc
material-ui 4Published@rjsf/material-ui
material-ui 5Published@rjsf/mui
Semantic UIPublished@rjsf/semantic-ui

Using themes

To use a theme from a package, just import the <Form /> component from that package. For example, to use the material ui form, first install both @rjsf/core and @rjsf/material-ui. Then you can import the form by doing:

import Form from '@rjsf/material-ui';

If you would like to contribute a theme with a new UI framework, please develop the theme using the withTheme component described in Theme Customization and make a PR!

You can also use the uiSchema to add custom CSS class names to your form.

Customizing with other frameworks

The default theme is bootstrap 3. In order to use another theme, you must first install @rjsf/core.

For example, to use the standard bootstrap 3 form, you can run:

import Form from '@rjsf/core';

To use the material-ui 5 form, you should first install both @rjsf/core and @rjsf/mui. Then, you can run:

import Form from '@rjsf/mui';

For more information on how to create a custom theme, see documentation on the withTheme component.

- + \ No newline at end of file diff --git a/docs/usage/validation/index.html b/docs/usage/validation/index.html index 6a41283d3a..173b8570f4 100644 --- a/docs/usage/validation/index.html +++ b/docs/usage/validation/index.html @@ -4,7 +4,7 @@ Validation | react-jsonschema-form - + @@ -19,7 +19,7 @@ The @rjsf/validator-ajv8 package exports the compileSchemaValidators() function that does this. It is expected that this function will be used in a manner similar to the following:

const compileSchemaValidators = require('@rjsf/validator-ajv8/dist/compileSchemaValidators').default;
const yourSchema = require('path_to/yourSchema'); // If your schema is a js file

compileSchemaValidators(yourSchema, 'path_to/yourCompiledSchema.js');

If you are currently using the customizeValidator() function to provide additionalMetaSchemas, customFormats, ajvOptionsOverrides and/or ajvFormatOptions then you can pass those in as the optional third parameter to the compileSchemaValidators() function in a manner similar to:

const { compileSchemaValidators } = require('@rjsf/validator-ajv8');
const yourSchema = require('path_to/yourSchema.json'); // If your schema is a json file

const options = {
additionalMetaSchemas: [require('ajv/lib/refs/json-schema-draft-06.json')],
customFormats: { 'phone-us': /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/, 'area-code': /\d{3}/ },
ajvOptionsOverrides: {
$data: true,
verbose: true,
},
ajvFormatOptions: {
mode: 'fast',
},
};

compileSchemaValidators(yourSchema, 'path_to/yourCompiledSchema.js', options);

It is highly recommended to create a compileYourSchema.js file (or what ever name you want) with code similar to what is shown above and then, using node, run the code as follows:

node compileYourSchema.js

NOTE: You must have your schema provided within a file that can be parsed and turned into the set of precompiled validator functions.

Additional Note: If you are using Webpack or NextJS and are encountering an issue resolving fs during development, consult this blog post for how to solve the issue.

Using the precompiled validator

After you have completed step 1 having generated your precompiled schema functions into the yourCompiledSchema.js output file (or whatever you called it), then you need to create a ValidatorType implementation from it to use in the Form. The @rjsf/validator-ajv8 package exports the createPrecompiledValidator() function for this. -Here is an example of how to use your precompiled validator with your Form:

import { createPrecompiledValidator, ValidatorFunctions } from '@rjsf/validator-ajv8';
import Form from '@rjsf/core'; // Or whatever theme you use

import yourSchema from 'path_to/yourSchema'; // This needs to be the same file that was precompiled
import * as precompiledValidator from 'path_to/yourCompiledSchema';

const validator = createPrecompiledValidator(precompiledValidator as ValidatorFunctions);

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Dynamically pre-compiling validators

For more advanced cases when schema needs to be precompiled on request - compileSchemaValidatorsCode can be used.

import { compileSchemaValidatorsCode } from '@rjsf/validator-ajv8/dist/compileSchemaValidators';

const code = compileSchemaValidatorsCode(schema, options);

For the most part it is the same as compileSchemaValidators, but instead of writing the file - it returns generated code directly.

To use it on browser side - some modifications are needed to provide runtime dependencies in generated code needs to be provided.

Example implementation of it:

import type { ValidatorFunctions } from '@rjsf/validator-ajv8';

import ajvRuntimeEqual from 'ajv/dist/runtime/equal';
import {
parseJson as ajvRuntimeparseJson,
parseJsonNumber as ajvRuntimeparseJsonNumber,
parseJsonString as ajvRuntimeparseJsonString,
} from 'ajv/dist/runtime/parseJson';
import ajvRuntimeQuote from 'ajv/dist/runtime/quote';
// import ajvRuntimeRe2 from 'ajv/dist/runtime/re2';
import ajvRuntimeTimestamp from 'ajv/dist/runtime/timestamp';
import ajvRuntimeUcs2length from 'ajv/dist/runtime/ucs2length';
import ajvRuntimeUri from 'ajv/dist/runtime/uri';
import * as ajvFormats from 'ajv-formats/dist/formats';

// dependencies to replace in generated code, to be provided by at runtime
const validatorsBundleReplacements: Record<string, [string, unknown]> = {
// '<code to be replaced>': ['<variable name to use as replacement>', <runtime dependency>],
'require("ajv/dist/runtime/equal").default': ['ajvRuntimeEqual', ajvRuntimeEqual],
'require("ajv/dist/runtime/parseJson").parseJson': ['ajvRuntimeparseJson', ajvRuntimeparseJson],
'require("ajv/dist/runtime/parseJson").parseJsonNumber': ['ajvRuntimeparseJsonNumber', ajvRuntimeparseJsonNumber],
'require("ajv/dist/runtime/parseJson").parseJsonString': ['ajvRuntimeparseJsonString', ajvRuntimeparseJsonString],
'require("ajv/dist/runtime/quote").default': ['ajvRuntimeQuote', ajvRuntimeQuote],
// re2 by default is not in dependencies for ajv and so is likely not normally used
// 'require("ajv/dist/runtime/re2").default': ['ajvRuntimeRe2', ajvRuntimeRe2],
'require("ajv/dist/runtime/timestamp").default': ['ajvRuntimeTimestamp', ajvRuntimeTimestamp],
'require("ajv/dist/runtime/ucs2length").default': ['ajvRuntimeUcs2length', ajvRuntimeUcs2length],
'require("ajv/dist/runtime/uri").default': ['ajvRuntimeUri', ajvRuntimeUri],
// formats
'require("ajv-formats/dist/formats")': ['ajvFormats', ajvFormats],
};

const regexp = new RegExp(
Object.keys(validatorsBundleReplacements)
.map((key) => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'))
.join('|'),
'g'
);

function wrapAjvBundle(code: string) {
return `function(${Object.values(validatorsBundleReplacements)
.map(([name]) => name)
.join(', ')}){\nvar exports = {};\n${code.replace(
regexp,
(req) => validatorsBundleReplacements[req][0]
)};\nreturn exports;\n}`;
}

const windowValidatorOnLoad = '__rjsf_validatorOnLoad';
const schemas = new Map<
string,
{ promise: Promise<ValidatorFunctions>; resolve: (result: ValidatorFunctions) => void }
>();
if (typeof window !== 'undefined') {
// @ts-ignore
window[windowValidatorOnLoad] = (loadedId: string, fn: (...args: unknown[]) => ValidatorFunctions) => {
const validator = fn(...Object.values(validatorsBundleReplacements).map(([, dep]) => dep));
let validatorLoader = schemas.get(loadedId);
if (validatorLoader) {
validatorLoader.resolve(validator);
} else {
throw new Error(`Unknown validator loaded id="${loadedId}"`);
}
};
}

/**
* Evaluate precompiled validator in browser using script tag
* @param id Identifier to avoid evaluating the same code multiple times
* @param code Code generated server side using `compileSchemaValidatorsCode`
* @param nonce nonce attribute to be added to script tag (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce#using_nonce_to_allowlist_a_script_element)
*/
export function evaluateValidator(id: string, code: string, nonce: string): Promise<ValidatorFunctions> {
let maybeValidator = schemas.get(id);
if (maybeValidator) return maybeValidator.promise;
let resolveValidator: (result: ValidatorFunctions) => void;
const validatorPromise = new Promise<ValidatorFunctions>((resolve) => {
resolveValidator = resolve;
});
schemas.set(id, {
promise: validatorPromise,
resolve: resolveValidator!,
});

const scriptElement = document.createElement('script');

scriptElement.setAttribute('nonce', nonce);
scriptElement.text = `window["${windowValidatorOnLoad}"]("${id}", ${wrapAjvBundle(code)})`;

document.body.appendChild(scriptElement);
return validatorPromise;
}

From React component this can be used as following:

let [precompiledValidator, setPrecompiledValidator] = React.useState<ValidatorFunctions>();
React.useEffect(() => {
evaluateValidator(
schemaId, // some schema id to avoid evaluating it multiple times
code, // result of compileSchemaValidatorsCode returned from the server
nonce // nonce script tag attribute to allow this ib content security policy for the page
).then(setPrecompiledValidator);
}, [entityType.id]);

if (!precompiledValidator) {
// render loading screen
}
const validator = createPrecompiledValidator(precompiledValidator, schema);

Live validation

By default, form data are only validated when the form is submitted or when a new formData prop is passed to the Form component.

You can enable live form data validation by passing a liveValidate prop to the Form component, and set it to true. Then, every time a value changes within the form data tree (e.g. the user entering a character in a field), a validation operation is performed, and the validation results are reflected into the form state.

Be warned that this is an expensive strategy, with possibly strong impact on performances.

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: ['string'],
const: 'test',
};

const formData = 'a';

render(<Form schema={schema} formData={formData} validator={validator} liveValidate />, document.getElementById('app'));

Validate form programmatically

It is possible to programmatically validate a form using the validateForm() function on Form. +Here is an example of how to use your precompiled validator with your Form:

import { createPrecompiledValidator, ValidatorFunctions } from '@rjsf/validator-ajv8';
import Form from '@rjsf/core'; // Or whatever theme you use

import yourSchema from 'path_to/yourSchema'; // This needs to be the same file that was precompiled
import * as precompiledValidator from 'path_to/yourCompiledSchema';

const validator = createPrecompiledValidator(precompiledValidator as ValidatorFunctions);

render(<Form schema={yourSchema} validator={validator} />, document.getElementById('app'));

Dynamically pre-compiling validators

For more advanced cases when schema needs to be precompiled on request - compileSchemaValidatorsCode can be used.

import { compileSchemaValidatorsCode } from '@rjsf/validator-ajv8/dist/compileSchemaValidators';

const code = compileSchemaValidatorsCode(schema, options);

For the most part it is the same as compileSchemaValidators, but instead of writing the file - it returns generated code directly.

To use it on browser side - some modifications are needed to provide runtime dependencies in generated code needs to be provided.

Example implementation of it:

import type { ValidatorFunctions } from '@rjsf/validator-ajv8';

import ajvRuntimeEqual from 'ajv/dist/runtime/equal';
import {
parseJson as ajvRuntimeparseJson,
parseJsonNumber as ajvRuntimeparseJsonNumber,
parseJsonString as ajvRuntimeparseJsonString,
} from 'ajv/dist/runtime/parseJson';
import ajvRuntimeQuote from 'ajv/dist/runtime/quote';
// import ajvRuntimeRe2 from 'ajv/dist/runtime/re2';
import ajvRuntimeTimestamp from 'ajv/dist/runtime/timestamp';
import ajvRuntimeUcs2length from 'ajv/dist/runtime/ucs2length';
import ajvRuntimeUri from 'ajv/dist/runtime/uri';
import * as ajvFormats from 'ajv-formats/dist/formats';

// dependencies to replace in generated code, to be provided by at runtime
const validatorsBundleReplacements: Record<string, [string, unknown]> = {
// '<code to be replaced>': ['<variable name to use as replacement>', <runtime dependency>],
'require("ajv/dist/runtime/equal").default': ['ajvRuntimeEqual', ajvRuntimeEqual],
'require("ajv/dist/runtime/parseJson").parseJson': ['ajvRuntimeparseJson', ajvRuntimeparseJson],
'require("ajv/dist/runtime/parseJson").parseJsonNumber': ['ajvRuntimeparseJsonNumber', ajvRuntimeparseJsonNumber],
'require("ajv/dist/runtime/parseJson").parseJsonString': ['ajvRuntimeparseJsonString', ajvRuntimeparseJsonString],
'require("ajv/dist/runtime/quote").default': ['ajvRuntimeQuote', ajvRuntimeQuote],
// re2 by default is not in dependencies for ajv and so is likely not normally used
// 'require("ajv/dist/runtime/re2").default': ['ajvRuntimeRe2', ajvRuntimeRe2],
'require("ajv/dist/runtime/timestamp").default': ['ajvRuntimeTimestamp', ajvRuntimeTimestamp],
'require("ajv/dist/runtime/ucs2length").default': ['ajvRuntimeUcs2length', ajvRuntimeUcs2length],
'require("ajv/dist/runtime/uri").default': ['ajvRuntimeUri', ajvRuntimeUri],
// formats
'require("ajv-formats/dist/formats")': ['ajvFormats', ajvFormats],
};

const regexp = new RegExp(
Object.keys(validatorsBundleReplacements)
.map((key) => key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'))
.join('|'),
'g'
);

function wrapAjvBundle(code: string) {
return `function(${Object.values(validatorsBundleReplacements)
.map(([name]) => name)
.join(', ')}){\nvar exports = {};\n${code.replace(
regexp,
(req) => validatorsBundleReplacements[req][0]
)};\nreturn exports;\n}`;
}

const windowValidatorOnLoad = '__rjsf_validatorOnLoad';
const schemas = new Map<
string,
{ promise: Promise<ValidatorFunctions>; resolve: (result: ValidatorFunctions) => void }
>();
if (typeof window !== 'undefined') {
// @ts-ignore
window[windowValidatorOnLoad] = (loadedId: string, fn: (...args: unknown[]) => ValidatorFunctions) => {
const validator = fn(...Object.values(validatorsBundleReplacements).map(([, dep]) => dep));
let validatorLoader = schemas.get(loadedId);
if (validatorLoader) {
validatorLoader.resolve(validator);
} else {
throw new Error(`Unknown validator loaded id="${loadedId}"`);
}
};
}

/**
* Evaluate precompiled validator in browser using script tag
* @param id Identifier to avoid evaluating the same code multiple times
* @param code Code generated server side using `compileSchemaValidatorsCode`
* @param nonce nonce attribute to be added to script tag (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce#using_nonce_to_allowlist_a_script_element)
*/
export function evaluateValidator(id: string, code: string, nonce: string): Promise<ValidatorFunctions> {
let maybeValidator = schemas.get(id);
if (maybeValidator) return maybeValidator.promise;
let resolveValidator: (result: ValidatorFunctions) => void;
const validatorPromise = new Promise<ValidatorFunctions>((resolve) => {
resolveValidator = resolve;
});
schemas.set(id, {
promise: validatorPromise,
resolve: resolveValidator!,
});

const scriptElement = document.createElement('script');

scriptElement.setAttribute('nonce', nonce);
scriptElement.text = `window["${windowValidatorOnLoad}"]("${id}", ${wrapAjvBundle(code)})`;

document.body.appendChild(scriptElement);
return validatorPromise;
}

From React component this can be used as following:

let [precompiledValidator, setPrecompiledValidator] = React.useState<ValidatorFunctions>();
React.useEffect(() => {
evaluateValidator(
schemaId, // some schema id to avoid evaluating it multiple times
code, // result of compileSchemaValidatorsCode returned from the server
nonce // nonce script tag attribute to allow this ib content security policy for the page
).then(setPrecompiledValidator);
}, [entityType.id]);

if (!precompiledValidator) {
// render loading screen
}
const validator = createPrecompiledValidator(precompiledValidator, schema);

Live validation

By default, form data are only validated when the form is submitted or when a new formData prop is passed to the Form component.

You can enable live form data validation by passing a liveValidate prop to the Form component, and set it to true. Then, every time a value changes within the form data tree (e.g. the user entering a character in a field), a validation operation is performed, and the validation results are reflected into the form state.

Be warned that this is an expensive strategy, with possibly strong impact on performances.

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: ['string'],
const: 'test',
};

const formData = 'a';

render(<Form schema={schema} formData={formData} validator={validator} liveValidate />, document.getElementById('app'));

Validate form programmatically

It is possible to programmatically validate a form using the validateForm() function on Form. Add a ref to your Form component and call the validateForm() method to validate the form programmatically. The validateForm() method returns true if the form is valid, false otherwise. If you have provided an onError callback it will be called with the list of errors when the validatorForm() method returns false.

import { createRef } from 'react';
import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const formRef = createRef();
const onError = (errors) => alert(errors);

const schema: RJSFSchema = {
type: 'string',
};

render(<Form schema={schema} validator={validator} onError={onError} ref={formRef} />, document.getElementById('app'));

if (formRef.current.validateForm()) {
alert('Form is valid');
}

HTML5 Validation

By default, the form uses HTML5 validation. This may cause unintuitive results because the HTML5 validation errors (such as when a field is required) may be displayed before the form is submitted, and thus these errors will display differently from the react-jsonschema-form validation errors. You can turn off HTML validation by setting the noHtml5Validate to true.

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',
properties: {
name: {
type: 'string',
required: true,
},
},
};

render(<Form schema={schema} validator={validator} noHtml5Validate />, document.getElementById('app'));

Custom validation rules

Form data is always validated against the JSON schema.

But it is possible to define your own custom validation rules that will run in addition to (and after) the validator implementation. @@ -43,7 +43,7 @@ It is possible to use one of the other version it supports, like draft-2019-09 or draft-2020-12. NOTE: draft-2020-12 has breaking changes and hasn't been fully tested with @rjsf.

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import { customizeValidator } from '@rjsf/validator-ajv8';
import Ajv2019 from 'ajv/dist/2019';

const schema: RJSFSchema = {
type: 'string',
format: 'date',
};

const validator = customizeValidator({ AjvClass: Ajv2019 });
// or
// const validator = customizeValidator({ AjvClass: Ajv2020 });

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Localization (L10n) support

The Ajv 8 validator supports the localization of error messages using ajv-i18n. In addition, you may provide a custom solution by implementing a function that conforms to the Localizer interface if your language is not supported.

import { ErrorObject } from 'ajv';
/** The type describing a function that takes a list of Ajv `ErrorObject`s and localizes them
*/
export type Localizer = (errors?: null | ErrorObject[]) => void;

NOTE: The ajv-i18n validators implement the Localizer interface.

Some examples

Using a specific locale while including all of ajv-i18n:

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import { customizeValidator } from '@rjsf/validator-ajv8';
import localizer from 'ajv-i18n';

const schema: RJSFSchema = {
type: 'string',
};

const validator = customizeValidator({}, localizer.it);

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

Using a specific locale minimizing the bundle size

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import { customizeValidator } from '@rjsf/validator-ajv8';
import spanishLocalizer from 'ajv-i18n/localize/es';

const schema: RJSFSchema = {
type: 'string',
};

const validator = customizeValidator({}, spanishLocalizer);

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

An example of a custom Localizer implementation:

import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import { customizeValidator } from '@rjsf/validator-ajv8';
import { ErrorObject } from 'ajv';

function localize_ru(errors: null | ErrorObject[] = []) {
if (!(errors && errors.length)) return;
errors.forEach(function (error) {
let outMessage = '';

switch (error.keyword) {
case 'pattern': {
outMessage = 'должно соответствовать образцу "' + error.params.pattern + '"';
break;
}
case 'required': {
outMessage = 'поле обязательно для заполнения';
break;
}
default:
outMessage = error.message;
}

error.message = outMessage;
});
}

const schema: RJSFSchema = {
type: 'string',
};

const validator = customizeValidator({}, localize_ru);

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));

NOTES:

  • If you provided your own function, modify the list in place.
  • You must process all the cases which you need by yourself. See the full list of possible cases here.
  • Each element in the errors list passed to the custom function represent a raw error object returned by ajv (see doc).
- + \ No newline at end of file diff --git a/docs/usage/widgets/index.html b/docs/usage/widgets/index.html index da8e5ce79c..bbab0b33cf 100644 --- a/docs/usage/widgets/index.html +++ b/docs/usage/widgets/index.html @@ -4,7 +4,7 @@ Widgets | react-jsonschema-form - + @@ -12,7 +12,7 @@
Version: v5

Widgets

The uiSchema ui:widget property tells the form which UI widget should be used to render a field.

Example:

import Form from '@rjsf/core';
import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',
properties: {
done: {
type: 'boolean',
},
},
};

const uiSchema: UiSchema = {
done: {
'ui:widget': 'radio', // could also be "select"
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

Here's a list of supported alternative widgets for different JSON Schema data types:

For boolean fields

  • radio: a radio button group with true and false as selectable values;
  • select: a select box with true and false as options;
  • by default, a checkbox is used

Note: To set the labels for a boolean field, instead of using true and false, your schema can use oneOf with const values for both true and false, where you can specify the custom label in the title field. You will also need to specify a widget in your uiSchema. See the following example:

schema:

{
"properties": {
"booleanWithCustomLabels": {
"type": "boolean",
"oneOf": [
{ "const": true, "title": "Custom label for true" },
{ "const": false, "title": "Custom label for false" }
]
}
}
}

uiSchema:

{
"booleanWithCustomLabels": {
"ui:widget": "radio" // or "select"
}
}

For string fields

  • textarea: a textarea element is used;
  • password: an input[type=password] element is used;
  • color: an input[type=color] element is used;
  • by default, a regular input[type=text] element is used.

String formats

The built-in string field also supports the JSON Schema format property, and will render an appropriate widget by default for the following string formats:

  • email: An input[type=email] element is used;
  • uri: An input[type=url] element is used;
  • data-url: By default, an input[type=file] element is used; in case the string is part of an array, multiple files will be handled automatically (see File widgets).
  • date: By default, an input[type=date] element is used;
  • date-time: By default, an input[type=datetime-local] element is used.
  • time: By default an input[type=time] element is used;

Please note that, even though they are standardized, datetime-local, date and time input elements are not supported by IE. If you plan on targeting IE, two alternative widgets are available:

  • alt-datetime: Six select elements are used to select the year, the month, the day, the hour, the minute and the second;
  • alt-date: Three select elements are used to select the year, month and the day.

You can customize the list of years displayed in the year dropdown by providing a yearsRange property to ui:options in your uiSchema. The range can be descending by specifying the larger value first. It's also possible to remove the Now and Clear buttons with the hideNowButton and hideClearButton options.

You can also, customize the order in which date input fields are displayed by providing format property to ui:options in your uiSchema, available values are YMD(default), MDY and DMY.

import Form from '@rjsf/core';
import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'string',
};

const uiSchema: UiSchema = {
'ui:widget': 'alt-datetime',
'ui:options': {
yearsRange: [1980, 2030],
format: 'MDY',
hideNowButton: true,
hideClearButton: true,
},
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

You can also specify negative values which will be treated relative to the current year, so if it is 2020 and the range is set as follows.

   yearsRange: [-120, -18],

Years from 1900-2002 will be shown. You can also specify the dates with the higher date first to display dates in reverse order.

   yearsRange: [2030, 1980],
...
yearsRange: [-18, -120],

Years from 2030-1980 and 2002-1900, respectively will be shown.

For number and integer fields

  • updown: an input[type=number] updown selector;
  • range: an input[type=range] slider;
  • radio: a radio button group with enum values. This can only be used when enum values are specified for this input.
  • By default, a regular input[type=number] element is used.

Note: If JSON Schema's minimum, maximum and multipleOf values are defined, the min, max and step input attributes values will take those values.

Hidden widgets

It's possible to use a hidden widget for a field by setting its ui:widget uiSchema directive to hidden:

import Form from '@rjsf/core';
import { RJSFSchema, UiSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'object',
properties: {
foo: { type: 'boolean' },
},
};

const uiSchema: UiSchema = {
foo: { 'ui:widget': 'hidden' },
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

Notes:

  • Hiding widgets is only supported for boolean, string, number and integer schema types;
  • A hidden widget takes its value from the formData prop.

File widgets

This library supports a limited form of input[type=file] widgets, in the sense that it will propagate file contents to form data state as data-urls.

There are two ways to use file widgets.

  1. By declaring a string json schema type along a data-url format:
import Form from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
type: 'string',
format: 'data-url',
};

render(<Form schema={schema} validator={validator} />, document.getElementById('app'));
  1. By specifying a ui:widget field uiSchema directive as file:
import { RJSFSchema, UiSchema } from '@rjsf/utils';

const schema: RJSFSchema = {
type: 'string',
};

const uiSchema: UiSchema = {
'ui:widget': 'file',
};

Multiple files

Multiple files selectors are supported by defining an array of strings having data-url as a format:

import { RJSFSchema } from '@rjsf/utils';

const schema: RJSFSchema = {
type: 'array',
items: {
type: 'string',
format: 'data-url',
},
};

Note that storing large dataURIs into form state might slow rendering.

File widget input ref

The included FileWidget exposes a reference to the <input type="file" /> element node as an inputRef component property.

This allows you to programmatically trigger the browser's file selector, which can be used in a custom file widget.

accept option

You can use the accept attribute to specify a filter for what file types the user can upload:

import { RJSFSchema, UiSchema } from '@rjsf/utils';

const schema: RJSFSchema = {
type: 'string',
format: 'data-url',
};

const uiSchema: UiSchema = {
'ui:options': { accept: '.pdf' },
};
- + \ No newline at end of file diff --git a/docs/version-3.2.1/advanced-customization/custom-templates/index.html b/docs/version-3.2.1/advanced-customization/custom-templates/index.html index ed9e0d9a7e..827864d5c8 100644 --- a/docs/version-3.2.1/advanced-customization/custom-templates/index.html +++ b/docs/version-3.2.1/advanced-customization/custom-templates/index.html @@ -4,14 +4,14 @@ Custom Templates | react-jsonschema-form - +
Version: v3

Custom Templates

This is an advanced feature that lets you customize even more aspects of the form:

_Custom FieldCustom TemplateCustom Widget
What it doesOverrides all behaviourOverrides just the layout (not behaviour)Overrides just the input box (not layout, labels, or help, or validation)
UsageGlobal or per-fieldGlobal or per-fieldGlobal or per-field
Global Example<Form fields={MyCustomField} /><Form ArrayFieldTemplate={MyArrayTemplate} /><Form widgets={MyCustomWidget} />
Per-Field Example"ui:field": MyCustomField"ui:ArrayFieldTemplate": MyArrayTemplate"ui:widget":MyCustomWidget
DocumentationCustom FieldsFieldTemplate / ArrayFieldTemplate / ObjectFieldTemplateCustom Widgets

ArrayFieldTemplate

You can use an ArrayFieldTemplate to customize how your arrays are rendered. This allows you to customize your array, and each element in the array.

const schema = {
type: "array",
items: {
type: "string"
}
};

function ArrayFieldTemplate(props) {
return (
<div>
{props.items.map(element => element.children)}
{props.canAdd && <button type="button" onClick={props.onAddClick}></button>}
</div>
);
}

render((
<Form schema={schema}
ArrayFieldTemplate={ArrayFieldTemplate} />
), document.getElementById("app"));

You also can provide your own field template to a uiSchema by specifying a ui:ArrayFieldTemplate property.

const uiSchema = {
"ui:ArrayFieldTemplate": ArrayFieldTemplate
}

Please see customArray.js for another example.

The following props are passed to each ArrayFieldTemplate:

  • DescriptionField: The DescriptionField from the registry (in case you wanted to utilize it)
  • TitleField: The TitleField from the registry (in case you wanted to utilize it).
  • canAdd: A boolean value stating whether new elements can be added to the array.
  • className: The className string.
  • disabled: A boolean value stating if the array is disabled.
  • idSchema: Object
  • items: An array of objects representing the items in the array. Each of the items represent a child with properties described below.
  • onAddClick: (event?) => void: A function that adds a new item to the array.
  • readonly: A boolean value stating if the array is read-only.
  • required: A boolean value stating if the array is required.
  • schema: The schema object for this array.
  • uiSchema: The uiSchema object for this array field.
  • title: A string value containing the title for the array.
  • formContext: The formContext object that you passed to Form.
  • formData: The formData for this array.
  • registry: The registry object.

The following props are part of each element in items:

  • children: The html for the item's content.
  • className: The className string.
  • disabled: A boolean value stating if the array item is disabled.
  • hasMoveDown: A boolean value stating whether the array item can be moved down.
  • hasMoveUp: A boolean value stating whether the array item can be moved up.
  • hasRemove: A boolean value stating whether the array item can be removed.
  • hasToolbar: A boolean value stating whether the array item has a toolbar.
  • index: A number stating the index the array item occurs in items.
  • key: A stable, unique key for the array item.
  • onAddIndexClick: (index) => (event?) => void: Returns a function that adds a new item at index.
  • onDropIndexClick: (index) => (event?) => void: Returns a function that removes the item at index.
  • onReorderClick: (index, newIndex) => (event?) => void: Returns a function that swaps the items at index with newIndex.
  • readonly: A boolean value stating if the array item is read-only.

Note: Array and object field templates are always rendered inside of the FieldTemplate. To fully customize an array field template, you may need to specify both ui:FieldTemplate and ui:ArrayFieldTemplate.

FieldTemplate

To take control over the inner organization of each field (each form row), you can define a field template for your form.

A field template is basically a React stateless component being passed field-related props, allowing you to structure your form row as you like.

const schema = {
type: "string"
};

function CustomFieldTemplate(props) {
const {id, classNames, label, help, required, description, errors, children} = props;
return (
<div className={classNames}>
<label htmlFor={id}>{label}{required ? "*" : null}</label>
{description}
{children}
{errors}
{help}
</div>
);
}

render((
<Form schema={schema}
FieldTemplate={CustomFieldTemplate} />
), document.getElementById("app"));

You also can provide your own field template to a uiSchema by specifying a ui:FieldTemplate property.

const uiSchema = {
"ui:FieldTemplate": CustomFieldTemplate
}

If you want to handle the rendering of each element yourself, you can use the props rawHelp, rawDescription and rawErrors.

The following props are passed to a custom field template component:

  • id: The id of the field in the hierarchy. You can use it to render a label targeting the wrapped widget.
  • classNames: A string containing the base Bootstrap CSS classes, merged with any custom ones defined in your uiSchema.
  • label: The computed label for this field, as a string.
  • description: A component instance rendering the field description, if one is defined (this will use any custom DescriptionField defined).
  • rawDescription: A string containing any ui:description uiSchema directive defined.
  • children: The field or widget component instance for this field row.
  • errors: A component instance listing any encountered errors for this field.
  • rawErrors: An array of strings listing all generated error messages from encountered errors for this field.
  • help: A component instance rendering any ui:help uiSchema directive defined.
  • rawHelp: A string containing any ui:help uiSchema directive defined. NOTE: rawHelp will be undefined if passed ui:help is a React component instead of a string.
  • hidden: A boolean value stating if the field should be hidden.
  • required: A boolean value stating if the field is required.
  • readonly: A boolean value stating if the field is read-only.
  • disabled: A boolean value stating if the field is disabled.
  • displayLabel: A boolean value stating if the label should be rendered or not. This is useful for nested fields in arrays where you don't want to clutter the UI.
  • fields: An array containing all Form's fields including your custom fields and the built-in fields.
  • schema: The schema object for this field.
  • uiSchema: The uiSchema object for this field.
  • onChange: The value change event handler; Can be called with a new value to change the value for this field.
  • formContext: The formContext object that you passed to Form.
  • formData: The formData for this field.
  • registry: The registry object.

Note: you can only define a single global field template for a form, but you can set individual field templates per property using "ui:FieldTemplate".

ObjectFieldTemplate

const schema = {
type: "object",
title: "Object title",
description: "Object description",
properties: {
name: {
type: "string"
},
age: {
type: "number"
}
}
};

function ObjectFieldTemplate(props) {
return (
<div>
{props.title}
{props.description}
{props.properties.map(element => <div className="property-wrapper">{element.content}</div>)}
</div>
);
}

render((
<Form schema={schema}
ObjectFieldTemplate={ObjectFieldTemplate} />
), document.getElementById("app"));

You also can provide your own field template to a uiSchema by specifying a ui:ObjectFieldTemplate property.

const uiSchema = {
"ui:ObjectFieldTemplate": ObjectFieldTemplate
};

Please see customObject.js for a better example.

The following props are passed to each ObjectFieldTemplate:

  • DescriptionField: The DescriptionField from the registry (in case you wanted to utilize it)
  • TitleField: The TitleField from the registry (in case you wanted to utilize it).
  • title: A string value containing the title for the object.
  • description: A string value containing the description for the object.
  • disabled: A boolean value stating if the object is disabled.
  • properties: An array of object representing the properties in the array. Each of the properties represent a child with properties described below.
  • onAddClick: (schema: JSONSchema7) => () => void: Returns a function that adds a new property to the object (to be used with additionalProperties)
  • readonly: A boolean value stating if the object is read-only.
  • required: A boolean value stating if the object is required.
  • schema: The schema object for this object.
  • uiSchema: The uiSchema object for this object field.
  • idSchema: An object containing the id for this object & ids for it's properties.
  • formData: The form data for the object.
  • formContext: The formContext object that you passed to Form.
  • registry: The registry object.

The following props are part of each element in properties:

  • content: The html for the property's content.
  • name: A string representing the property name.
  • disabled: A boolean value stating if the object property is disabled.
  • readonly: A boolean value stating if the property is read-only.
  • hidden: A boolean value stating if the property should be hidden.

Note: Array and object field templates are always rendered inside of the FieldTemplate. To fully customize an object field template, you may need to specify both ui:FieldTemplate and ui:ObjectFieldTemplate.

- + \ No newline at end of file diff --git a/docs/version-3.2.1/advanced-customization/custom-themes/index.html b/docs/version-3.2.1/advanced-customization/custom-themes/index.html index 006be2b1e6..1be94fa30f 100644 --- a/docs/version-3.2.1/advanced-customization/custom-themes/index.html +++ b/docs/version-3.2.1/advanced-customization/custom-themes/index.html @@ -4,13 +4,13 @@ Custom Themes | react-jsonschema-form - +
Version: v3

Custom Themes

The withTheme component provides an easy way to extend the functionality of react-jsonschema-form by passing in a theme object that defines custom/overridden widgets and fields, as well as any of the other possible properties of the standard rjsf Form component. This theme-defining object is passed as the only parameter to the HOC (withTheme(ThemeObj)), and the HOC will return a themed-component which you use instead of the standard Form component.

Usage

import React, { Component } from 'react';
import { withTheme } from '@rjsf/core';

const theme = { widgets: {test: () => (<div>test</div>) } };

const ThemedForm = withTheme(theme);

const Demo = () => (
<ThemedForm schema={schema} uiSchema={uiSchema} />
);

Theme object properties

The Theme object consists of the same properties as the rjsf Form component (such as widgets and fields). The themed-Form component merges together any theme-specific widgets and fields with the default widgets and fields. For instance, providing a single widget in widgets will merge this widget with all the default widgets of the rjsf Form component, but overrides the default if the theme's widget's name matches the default widget's name. Thus, for each default widget or field not specified/overridden, the themed-form will rely on the defaults from the rjsf Form. Note that you are not required to pass in either custom widgets or fields when using the custom-themed HOC component; you can make the essentially redefine the default Form by simply doing const Form = withTheme({});.

Widgets and fields

widgets and fields should be in the same format as shown here.

Example theme with custom widget:

const MyCustomWidget = (props) => {
return (
<input type="text"
className="custom"
value={props.value}
required={props.required}
onChange={(event) => props.onChange(event.target.value)} />
);
};

const myWidgets = {
myCustomWidget: MyCustomWidget
};

const ThemeObject = {widgets: myWidgets};
export default ThemeObject;

The above can be similarly done for fields.

Templates

Each template should be passed directly into the theme object just as you would into the rjsf Form component. Here is an example of how to use a custom ArrayFieldTemplate and ErrorListTemplate in the theme object:

function MyArrayFieldTemplate(props) {
return (
<div>
{props.items.map(element => element.children)}
{props.canAdd && <button type="button" onClick={props.onAddClick}></button>}
</div>
);
}

function MyErrorListTemplate(props) {
const {errors} = props;
return (
<ul>
{errors.map(error => (
<li key={error.stack}>
{error.stack}
</li>
))}
</ul>
);
}

const ThemeObject = {
ArrayFieldTemplate: MyArrayFieldTemplate,
ErrorList: MyErrorListTemplate,
widgets: myWidgets
};

export default ThemeObject;

Overriding other Form props

Just as the theme can override widgets, fields, any of the field templates, and set default values to properties like showErrorList, you can do the same with the instance of the withTheme() Form component.

const ThemeObject = {
ArrayFieldTemplate: MyArrayFieldTemplate,
fields: myFields,
showErrorList: false,
widgets: myWidgets
};

Thus, the user has higher priority than the withTheme HOC, and the theme has higher priority than the default values of the rjsf Form component (User > Theme > Defaults).

- + \ No newline at end of file diff --git a/docs/version-3.2.1/advanced-customization/custom-widgets-fields/index.html b/docs/version-3.2.1/advanced-customization/custom-widgets-fields/index.html index 52a037a2a5..e50daade1d 100644 --- a/docs/version-3.2.1/advanced-customization/custom-widgets-fields/index.html +++ b/docs/version-3.2.1/advanced-customization/custom-widgets-fields/index.html @@ -4,13 +4,13 @@ Custom Widgets and Fields | react-jsonschema-form - +
Version: v3

Custom Widgets and Fields

The API allows to specify your own custom widget and field components:

  • A widget represents a HTML tag for the user to enter data, eg. input, select, etc.
  • A field usually wraps one or more widgets and most often handles internal field state; think of a field as a form row, including the labels.

Customizing the default fields and widgets

You can override any default field and widget, including the internal widgets like the CheckboxWidget that ObjectField renders for boolean values. You can override any field and widget just by providing the customized fields/widgets in the fields and widgets props:

const schema = {
type: "boolean",
default: true
};

const uiSchema = {
"ui:widget": "checkbox"
};

const CustomCheckbox = function(props) {
return (
<button id="custom" className={props.value ? "checked" : "unchecked"} onClick={() => props.onChange(!props.value)}>
{String(props.value)}
</button>
);
};

const widgets = {
CheckboxWidget: CustomCheckbox
};

render((
<Form schema={schema}
uiSchema={uiSchema}
widgets={widgets} />
), document.getElementById("app"));

This allows you to create a reusable customized form class with your custom fields and widgets:

const customFields = {StringField: CustomString};
const customWidgets = {CheckboxWidget: CustomCheckbox};

function MyForm(props) {
return <Form fields={customFields} widgets={customWidgets} {...props} />;
}

The default fields you can override are:

  • ArrayField
  • BooleanField
  • DescriptionField
  • OneOfField
  • AnyOfField
  • NullField
  • NumberField
  • ObjectField
  • SchemaField
  • StringField
  • TitleField
  • UnsupportedField

The default widgets you can override are:

  • AltDateTimeWidget
  • AltDateWidget
  • CheckboxesWidget
  • CheckboxWidget
  • ColorWidget
  • DateTimeWidget
  • DateWidget
  • EmailWidget
  • FileWidget
  • HiddenWidget
  • PasswordWidget
  • RadioWidget
  • RangeWidget
  • SelectWidget
  • TextareaWidget
  • TextWidget
  • UpDownWidget
  • URLWidget

Adding your own custom widgets

You can provide your own custom widgets to a uiSchema for the following json data types:

  • string
  • number
  • integer
  • boolean
const schema = {
type: "string"
};

const uiSchema = {
"ui:widget": (props) => {
return (
<input type="text"
className="custom"
value={props.value}
required={props.required}
onChange={(event) => props.onChange(event.target.value)} />
);
}
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

The following props are passed to custom widget components:

  • id: The generated id for this field;
  • schema: The JSONSchema subschema object for this field;
  • uiSchema: The uiSchema for this field;
  • value: The current value for this field;
  • placeholder: the placeholder for the field, if any;
  • required: The required status of this field;
  • disabled: true if the widget is disabled;
  • readonly: true if the widget is read-only;
  • autofocus: true if the widget should autofocus;
  • onChange: The value change event handler; call it with the new value every time it changes;
  • onKeyChange: The key change event handler (only called for fields with additionalProperties); pass the new value every time it changes;
  • onBlur: The input blur event handler; call it with the the widget id and value;
  • onFocus: The input focus event handler; call it with the the widget id and value;
  • options: A map of options passed as a prop to the component (see Custom widget options).
  • options.enumOptions: For enum fields, this property contains the list of options for the enum as an array of { label, value } objects. If the enum is defined using the oneOf/anyOf syntax, the entire schema object for each option is appended onto the { schema, label, value } object.
  • formContext: The formContext object that you passed to Form.
  • rawErrors: An array of strings listing all generated error messages from encountered errors for this widget.

Custom component registration

Alternatively, you can register them all at once by passing the widgets prop to the Form component, and reference their identifier from the uiSchema:

const MyCustomWidget = (props) => {
return (
<input type="text"
className="custom"
value={props.value}
required={props.required}
onChange={(event) => props.onChange(event.target.value)} />
);
};

const widgets = {
myCustomWidget: MyCustomWidget
};

const schema = {
type: "string"
};

const uiSchema = {
"ui:widget": "myCustomWidget"
}

render((
<Form
schema={schema}
uiSchema={uiSchema}
widgets={widgets} />
), document.getElementById("app"));

This is useful if you expose the uiSchema as pure JSON, which can't carry functions.

Custom widget options

If you need to pass options to your custom widget, you can add a ui:options object containing those properties. If the widget has defaultProps, the options will be merged with the (optional) options object from defaultProps:

const schema = {
type: "string"
};

function MyCustomWidget(props) {
const {options} = props;
const {color, backgroundColor} = options;
return <input 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"));

Note: This also applies to registered custom components.

Note: Since v0.41.0, the ui:widget object API, where a widget and options were specified with "ui:widget": {component, options} shape, is deprecated. It will be removed in a future release.

Customizing widgets text input

All the widgets that render a text input use the BaseInput component internally. If you need to customize all text inputs without customizing all widgets individually, you can provide a BaseInput component in the widgets property of Form (see Custom component registration).

Custom field components

You can provide your own field components to a uiSchema for basically any json schema data type, by specifying a ui:field property.

For example, let's create and register a dumb geo component handling a latitude and a longitude:

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

// Define a custom component for handling the root position object
class GeoPosition extends React.Component {
constructor(props) {
super(props);
this.state = {...props.formData};
}

onChange(name) {
return (event) => {
this.setState({
[name]: parseFloat(event.target.value)
}, () => this.props.onChange(this.state));
};
}

render() {
const {lat, lon} = this.state;
return (
<div>
<input type="number" value={lat} onChange={this.onChange("lat")} />
<input type="number" value={lon} onChange={this.onChange("lon")} />
</div>
);
}
}

// 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"));

Note: Registered fields can be reused across the entire schema.

Field props

A field component will always be passed the following props:

  • schema: The JSON schema for this field;
  • uiSchema: The uiSchema for this field;
  • idSchema: The tree of unique ids for every child field;
  • formData: The data for this field;
  • errorSchema: The tree of errors for this field and its children;
  • registry: A registry object (read next).
  • formContext: A formContext object (read next).

The registry object

The registry is an object containing the registered custom fields and widgets as well as the root schema definitions.

  • fields: The custom registered fields. By default this object contains the standard SchemaField, TitleField and DescriptionField components;
  • widgets: The custom registered widgets, if any;
  • rootSchema: The root schema, which can contain referenced definitions;
  • formContext: The formContext object;
  • definitions (deprecated since v2): Equal to rootSchema.definitions.

The registry is passed down the component tree, so you can access it from your custom field and SchemaField components.

Custom SchemaField

Warning: This is a powerful feature as you can override the whole form behavior and easily mess it up. Handle with care.

You can provide your own implementation of the SchemaField base React component for rendering any JSONSchema field type, including objects and arrays. This is useful when you want to augment a given field type with supplementary powers.

To proceed so, pass a fields object having a SchemaField property to your Form component; here's an example:


const CustomSchemaField = function(props) {
return (
<div id="custom">
<p>Yeah, I'm pretty dumb.</p>
<div>My props are: {JSON.stringify(props)}</div>
</div>
);
};

const fields = {
SchemaField: CustomSchemaField
};

const schema = {
type: "string"
};

render((
<Form schema={schema}
fields={fields} />
), document.getElementById("app"));

If you're curious how this could ever be useful, have a look at the Kinto formbuilder repository to see how it's used to provide editing capabilities to any form field.

Props passed to a custom SchemaField are the same as the ones passed to a custom field.

- + \ No newline at end of file diff --git a/docs/version-3.2.1/advanced-customization/index.html b/docs/version-3.2.1/advanced-customization/index.html index b77a289d11..6acf65faf4 100644 --- a/docs/version-3.2.1/advanced-customization/index.html +++ b/docs/version-3.2.1/advanced-customization/index.html @@ -4,13 +4,13 @@ Advanced Customization | react-jsonschema-form - + - + \ No newline at end of file diff --git a/docs/version-3.2.1/advanced-customization/internals/index.html b/docs/version-3.2.1/advanced-customization/internals/index.html index 2703a99b51..cbbc030b37 100644 --- a/docs/version-3.2.1/advanced-customization/internals/index.html +++ b/docs/version-3.2.1/advanced-customization/internals/index.html @@ -4,14 +4,14 @@ Internals | react-jsonschema-form - +
Version: v3

Internals

Miscellaneous internals of react-jsonschema-form are listed here.

JSON Schema supporting status

This component follows JSON Schema specs. We currently support JSON Schema-07 by default, but we also support other JSON schema versions through the custom schema validation feature. Due to the limitation of form widgets, there are some exceptions as follows:

  • additionalItems keyword for arrays

    This keyword works when items is an array. additionalItems: true is not supported because there's no widget to represent an item of any type. In this case it will be treated as no additional items allowed. additionalItems being a valid schema is supported.

  • anyOf, allOf, and oneOf, or multiple types (i.e. "type": ["string", "array"])

    The anyOf and oneOf keywords are supported; however, properties declared inside the anyOf/oneOf should not overlap with properties "outside" of the anyOf/oneOf.

    You can also use oneOf with schema dependencies to dynamically add schema properties based on input data.

    The allOf keyword is supported; it uses json-schema-merge-allof to merge subschemas to render the final combined schema in the form. When these subschemas are incompatible, though (or if the library has an error merging it), the allOf keyword is dropped from the schema.

  • "additionalProperties":false produces incorrect schemas when used with schema dependencies. This library does not remove extra properties, which causes validation to fail. It is recommended to avoid setting "additionalProperties":false when you use schema dependencies. See #848 #902 #992

Handling of schema defaults

This library automatically fills default values defined in the JSON Schema as initial values in your form. This also works for complex structures in the schema. If a field has a default defined, it should always appear as default value in form. This also works when using schema dependencies.

Since there is a complex interaction between any supplied original form data and any injected defaults, this library tries to do the injection in a way which keeps the original intention of the original form data.

Check out the defaults example on the live playground to see this in action.

Merging of defaults into the form data

There are three different cases which need to be considered for the merging. Objects, arrays and scalar values. This library always deeply merges any defaults with the existing form data for objects.

This are the rules which are used when injecting the defaults:

  • When there is a scalar in the form data, nothing is changed.
  • When the value is undefined in the form data, the default is created in the form data.
  • When the value is an object in the form data, the defaults are deeply merged into the form data, using the rules defined here for the deep merge.
  • Then the value is an array in the form data, defaults are only injected in existing array items. No new array items will be created, even if the schema has minItems or additional items defined.

Merging of defaults within the schema

In the schema itself, defaults of parent elements are propagated into children. So when you have a schema which defines a deeply nested object as default, these defaults will be applied to children of the current node. This also merges objects defined at different levels together with the "deeper" not having precedence. If the parent node defines properties, which are not defined in the child, they will be merged so that the default for the child will be the merged defaults of parent and child.

For arrays this is not the case. Defining an array, when a parent also defines an array, will be overwritten. This is only true when arrays are used in the same level, for objects within these arrays, they will be deeply merged again.

Custom array field buttons

The ArrayField component provides a UI to add, remove and reorder array items, and these buttons use Bootstrap glyphicons. If you don't use glyphicons but still want to provide your own icons or texts for these buttons, you can easily do so using CSS:

i.glyphicon { display: none; }
.btn-add::after { content: 'Add'; }
.array-item-move-up::after { content: 'Move Up'; }
.array-item-move-down::after { content: 'Move Down'; }
.array-item-remove::after { content: 'Remove'; }

Submit form programmatically

You can use the reference to get your Form component and call the submit method to submit the form programmatically without a submit button. This method will dispatch the submit event of the form, and the function, that is passed to onSubmit props, will be called.

const onSubmit = ({formData}) => console.log("Data submitted: ",  formData);
let yourForm;

const schema = {
type: "string"
};

render((
<Form schema={schema}
onSubmit={onSubmit} ref={(form) => {yourForm = form;}}/>
), document.getElementById("app"));

yourForm.submit();
- + \ No newline at end of file diff --git a/docs/version-3.2.1/api-reference/form-props/index.html b/docs/version-3.2.1/api-reference/form-props/index.html index 4ae6a2959a..d780d4a9bc 100644 --- a/docs/version-3.2.1/api-reference/form-props/index.html +++ b/docs/version-3.2.1/api-reference/form-props/index.html @@ -4,13 +4,13 @@ <Form /> Props | react-jsonschema-form - +
Version: v3

<Form /> props

acceptcharset

The value of this prop will be passed to the accept-charset HTML attribute on the form.

action

The value of this prop will be passed to the action HTML attribute on the form.

Note that this just renders the action attribute in the HTML markup. There is no real network request being sent to this action on submit. Instead, react-jsonschema-form catches the submit event with event.preventDefault() and then calls the onSubmit function, where you could send a request programmatically with fetch or similar.

additionalMetaSchemas

This prop allows you to validate the form data against another JSON Schema meta schema, for example, JSON Schema draft-04. See Validation for more information.

ArrayFieldTemplate

React component used to customize how alls arrays are rendered on the form. See Custom Templates for more information.

autoComplete

The value of this prop will be passed to the autocomplete HTML attribute on the form.

autocomplete

Deprecated, same functionality as autoComplete

className

The value of this prop will be passed to the class HTML attribute on the form.

children

You can provide custom buttons to your form via the Form component's children. Otherwise a default submit button will be rendered.

const schema = {
type: "string"
};

render((
<Form schema={schema}>
<div>
<button type="submit">Submit</button>
<button type="button">Cancel</button>
</div>
</Form>
), document.getElementById("app"));

Warning: There needs to be a button or an input with type="submit" to trigger the form submission (and then the form validation).

customFormats

This prop allows you to define custom formats for validation. See Validation for more information.

disabled

It's possible to disable the whole form by setting the disabled prop. The disabled prop is then forwarded down to each field of the form.

const schema = {
type: "string"
};

render((
<Form schema={schema}
disabled />
), document.getElementById("app"));

If you just want to disable some of the fields, see the ui:disabled parameter in uiSchema.

readonly

It's possible to make the whole form read-only by setting the readonly prop. The readonly prop is then forwarded down to each field of the form.

const schema = {
type: "string"
};

render((
<Form schema={schema}
readonly />
), document.getElementById("app"));

If you just want to make some of the fields read-only, see the ui:readonly parameter in uiSchema.

enctype

The value of this prop will be passed to the enctype HTML attribute on the form.

extraErrors

This prop allows passing in custom errors that are augmented with the existing JSON Schema errors on the form; it can be used to implement asynchronous validation. See Validation for more information.

ErrorList

You can pass a React component to this prop to customize how form errors are displayed. See Validation for more information.

fields

Dictionary of registered fields in the form. See Custom Widgets and Fields for more information.

FieldTemplate

React component used to customize each field of the form. See Custom Templates for more information.

formContext

You can provide a formContext object to the Form, which is passed down to all fields and widgets. Useful for implementing context aware fields and widgets.

formData

Often you'll want to prefill a form with existing data; this is done by passing a formData prop object matching the schema.

id

The value of this prop will be passed to the id HTML attribute on the form.

idPrefix

To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids (the default is root).

const schema = {
type: "string"
};

render((
<Form schema={schema}
idPrefix={"rjsf_prefix"}/>
), document.getElementById("app"));

This will render <input id="rjsf_prefix_key"> instead of <input id="root_key">

liveOmit

If omitExtraData and liveOmit are both set to true, then extra form data values that are not in any form field will be removed whenever onChange is called. Set to false by default.

liveValidate

If set to true, the form will perform validation and show any validation errors whenever the form data is changed, rather than just on submit.

method

The value of this prop will be passed to the method HTML attribute on the form.

name

The value of this prop will be passed to the name HTML attribute on the form.

noHtml5Validate

If set to true, turns off HTML5 validation on the form. Set to false on default.

noValidate

If set to true, turns off all validation. Set to false by default.

ObjectFieldTemplate

React component used to customize how all objects are rendered in the form. See Custom Templates for more information.

omitExtraData

If set to true, then extra form data values that are not in any form field will be removed whenever onSubmit is called. Set to false by default.

onBlur

Sometimes you may want to trigger events or modify external state when a field has been touched, so you can pass an onBlur handler, which will receive the id of the input that was blurred and the field value.

onChange

If you plan on being notified every time the form data are updated, you can pass an onChange handler, which will receive the same args as onSubmit any time a value is updated in the form.

onError

To react when submitted form data are invalid, pass an onError handler. It will be passed the list of encountered errors:

const schema = {
type: "string"
};
const onError = (errors) => console.log("I have", errors.length, "errors to fix");

render((
<Form schema={schema}
onError={onError} />
), document.getElementById("app"));

onFocus

Sometimes you may want to trigger events or modify external state when a field has been focused, so you can pass an onFocus handler, which will receive the id of the input that is focused and the field value.

onSubmit

You can pass a function as the onSubmit prop of your Form component to listen to when the form is submitted and its data are valid. It will be passed a result object having a formData attribute, which is the valid form data you're usually after. The original event will also be passed as a second parameter:

const schema = {
type: "string"
};
const onSubmit = ({formData}, e) => console.log("Data submitted: ", formData);

render((
<Form schema={schema}
onSubmit={onSubmit} />
), document.getElementById("app"));

Note: If there are fields in the formData that are not represented in the schema, they will be retained by default. If you would like to remove those extra values on form submission, you may need to set the omitExtraData and/or liveOmit props.

schema

Form schema. We support JSON schema draft-07 by default. See Schema Reference for more information.

showErrorList

When this prop is set to true, a list of errors (or the custom error list defined in the ErrorList) will also show. When set to false, only inline input validation errors will be shown. Set to true by default. See Validation for more information.

tagName

It's possible to change the default form tag name to a different HTML tag, which can be helpful if you are nesting forms. However, native browser form behaviour, such as submitting when the Enter key is pressed, may no longer work.

<Form
tagName="div"
/>

You can also provide a class/function component.

const CustomForm = props => <form {...props} style={...} className={...} />
// ...
<Form
tagName={CustomForm}
/>

target

The value of this prop will be passed to the target HTML attribute on the form.

transformErrors

A function can be passed to this prop in order to make modifications to the default errors resulting from JSON Schema validation. See Validation for more information.

uiSchema

Form uiSchema. See uiSchema Reference for more information.

validate

The validate prop requires a function that specifies custom validation rules for the form. See Validation for more information.

widgets

Dictionary of registered widgets in the form. See Custom Widgets and Fields for more information.

- + \ No newline at end of file diff --git a/docs/version-3.2.1/api-reference/index.html b/docs/version-3.2.1/api-reference/index.html index e3b9aa1d34..fad8cc13f6 100644 --- a/docs/version-3.2.1/api-reference/index.html +++ b/docs/version-3.2.1/api-reference/index.html @@ -4,13 +4,13 @@ API Reference | react-jsonschema-form - + - + \ No newline at end of file diff --git a/docs/version-3.2.1/api-reference/themes/semantic-ui/uiSchema/index.html b/docs/version-3.2.1/api-reference/themes/semantic-ui/uiSchema/index.html index 524241e8d9..081d5db8d8 100644 --- a/docs/version-3.2.1/api-reference/themes/semantic-ui/uiSchema/index.html +++ b/docs/version-3.2.1/api-reference/themes/semantic-ui/uiSchema/index.html @@ -4,13 +4,13 @@ uiSchema Options for Semantic-UI | react-jsonschema-form - +
Version: v3

uiSchema Options for Semantic-UI

There are various options to pass to semantic theme fields.

Note that every semantic property within uiSchema can be rendered in one of two ways: {"ui:options": {semantic:{[property]: [value]}}}

In other words, the following uiSchema is equivalent:

Note: All fields have the following settings below as their default

fluid: Take on the size of its container.
inverted: Format to appear on dark backgrounds.
{
"ui:options": {
"semantic" : {
"fluid": true,
"inverted": false,
"errorOptions": {
"size": "small",
"pointing": "above",
}
}
}
}

Semantic Widget Optional Properties

errorOptions

The uiSchema semantic object accepts an errorOptions property for each field of the schema:

size: determines the size of the error message dialog
pointing: determines the direction of the arrow on the error message dialog

Below are the current defaults

const uiSchema = {
"ui:options": {
"semantic" : {
"errorOptions": {
"size": "small",
"pointing": "above",
}
}
}
};

semantic options uiSchema for array items

To specify a uiSchema that applies to array items, specify the semantic uiSchema value within the ui:options property:

wrapItem: wrap each array item in a Segment
horizontalButtons: horizontal buttons instead of the default vertical
const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
"ui:options": {
"semantic": {
"wrapItem": true,
"horizontalButtons": true
}
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

formContext

The formContext semantic object accepts wrapContent ,wrapLabel properties.

wrapContent: wrap all inputs  field content in a div, for custom styling
wrapLabel: wrap all labels in a div, for custom styling via CSS
<Form
formContext={{
"semantic" : {
"wrapLabel": true,
"wrapContent": true
}
// other props...
}}
/>
- + \ No newline at end of file diff --git a/docs/version-3.2.1/api-reference/uiSchema/index.html b/docs/version-3.2.1/api-reference/uiSchema/index.html index 898b82a133..bd3425022b 100644 --- a/docs/version-3.2.1/api-reference/uiSchema/index.html +++ b/docs/version-3.2.1/api-reference/uiSchema/index.html @@ -4,13 +4,13 @@ uiSchema | react-jsonschema-form - +
Version: v3

uiSchema

JSON Schema is limited for describing how a given data type should be rendered as a form input component. That's why this library introduces the concept of uiSchema.

A UI schema is basically an object literal providing information on how the form should be rendered, while the JSON schema tells what.

The uiSchema object follows the tree structure of the form field hierarchy, and defines how each property should be rendered.

Note that every property within uiSchema can be rendered in one of two ways: {"ui:options": {[property]: [value]}}, or {"ui:[property]": value}.

In other words, the following uiSchemas are equivalent:

{
"ui:title": "Title",
"ui:description": "Description"
}
{
"ui:options": {
"title": "Title",
"description": "Description"
}
}

classNames

The uiSchema object accepts a classNames property for each field of the schema:

const uiSchema = {
title: {
classNames: "task-title foo-bar"
}
};

Will result in:

<div class="field field-string task-title foo-bar" >
<label>
<span>Title*</span>
<input value="My task" required="" type="text">
</label>
</div>

autofocus

If you want to automatically focus on a text input or textarea input, set the ui:autofocus uiSchema directive to true.

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "textarea",
"ui:autofocus": true
}

description

Sometimes it's convenient to change the description of a field. This is the purpose of the ui:description uiSchema directive:

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "password",
"ui:description": "The best password"
};

disabled

The ui:disabled uiSchema directive will disable all child widgets from a given field.

Note: If you're wondering about the difference between a disabled field and a readonly one: Marking a field as read-only will render it greyed out, but its text value will be selectable. Disabling it will prevent its value to be selected at all.

enumDisabled

To disable an option, use the enumDisabled property in uiSchema.

const schema = {
type: "string",
enum: ["one", "two", "three"],
};

const uiSchema={
"ui:enumDisabled": ['two'],
}

help

Sometimes it's convenient to add text next to a field to guide the end user filling it. This is the purpose of the ui:help uiSchema directive:

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "password",
"ui:help": "Hint: Make it strong!"
};

Help texts work for any kind of field at any level, and will always be rendered immediately below the field component widget(s) (after contextualized errors, if any).

inputType

To change the input type (for example, tel or email) you can specify the inputType in the ui:options uiSchema directive.

const schema = {type: "string"};
const uiSchema = {
"ui:options": {
inputType: 'tel'
}
};

label

Field labels are rendered by default. Labels may be omitted by setting the label option to false in the ui:options uiSchema directive.

const schema = {type: "string"};
const uiSchema = {
"ui:options": {
label: false
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

order

This property allows you to reorder the properties that are shown for a particular object. See Objects for more information.

placeholder

You can add placeholder text to an input by using the ui:placeholder uiSchema directive:

const schema = {type: "string", format: "uri"};
const uiSchema = {
"ui:placeholder": "http://"
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

Fields using enum can also use ui:placeholder. The value will be used as the text for the empty option in the select widget.

const schema = {type: "string", enum: ["First", "Second"]};
const uiSchema = {
"ui:placeholder": "Choose an option"
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

readonly

The ui:readonly uiSchema directive will mark all child widgets from a given field as read-only. This is equivalent to setting the readOnly property in the schema.

Note: If you're wondering about the difference between a disabled field and a readonly one: Marking a field as read-only will render it greyed out, but its text value will be selectable. Disabling it will prevent its value to be selected at all.

rootFieldId

By default, this library will generate ids unique to the form for all rendered widgets. If you plan on using multiple instances of the Form component in a same page, it's wise to declare a root prefix for these, using the ui:rootFieldId uiSchema directive:

const uiSchema = {
"ui:rootFieldId": "myform"
};

This will make all widgets have an id prefixed with myform.

rows

You can set the initial height of a textarea widget by specifying rows option.

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "textarea",
"ui:options": {
rows: 15
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

title

Sometimes it's convenient to change a field's title. This is the purpose of the ui:title uiSchema directive:

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "password",
"ui:title": "Your password"
};

Theme Options

Semantic UI

- + \ No newline at end of file diff --git a/docs/version-3.2.1/quickstart/index.html b/docs/version-3.2.1/quickstart/index.html index 06089a68fc..3906fb18ba 100644 --- a/docs/version-3.2.1/quickstart/index.html +++ b/docs/version-3.2.1/quickstart/index.html @@ -4,7 +4,7 @@ Quickstart | react-jsonschema-form - + @@ -14,7 +14,7 @@ uiSchema should be {key: value}, where key is the property key and value is an object with the uiSchema configuration for that particular property. For example:

const schema = {
title: "Test form",
type: "object",
properties: {
name: {
type: "string"
},
age: {
type: "number"
}
}
};

const uiSchema = {
name: {
classNames: "custom-class-name"
},
age: {
classNames: "custom-class-age"
}
}

render((
<Form schema={schema} />
), document.getElementById("app"));

Form initialization

Often you'll want to prefill a form with existing data; this is done by passing a formData prop object matching the schema:

const schema = {
type: "object",
properties: {
title: {
type: "string"
},
done: {
type: "boolean"
}
}
};

const formData = {
title: "First task",
done: true
};

render((
<Form schema={schema}
formData={formData} />
), document.getElementById("app"));

Note: If your form has a single field, pass a single value to formData. ex: formData="Charlie"

WARNING: If you have situations where your parent component can re-render, make sure you listen to the onChange event and update the data you pass to the formData attribute.

Form event handlers

You can use event handlers such as onChange, onError, onSubmit, onFocus, and onBlur on the <Form /> component; see the Form Props Reference for more details.

Controlled component

By default, <Form /> is an uncontrolled component. To make it a controlled component, use the onChange and formData props as in the below example:

const App = () => {
const [formData, setFormData] = React.useState(null);
return (<Form
schema={{type: "string"}}
formData={formData}
onChange={e => setFormData(e.formData)}
/>);
};

render((
<App />
), document.getElementById("app"));
- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/arrays/index.html b/docs/version-3.2.1/usage/arrays/index.html index 853be9a7e8..35fae2ad19 100644 --- a/docs/version-3.2.1/usage/arrays/index.html +++ b/docs/version-3.2.1/usage/arrays/index.html @@ -4,13 +4,13 @@ Arrays | react-jsonschema-form - +
Version: v3

Arrays

Arrays are defined with a type equal to array, and array items' schemas are specified in the items keyword.

Arrays of a single field

Arrays of a single field type can be specified as follows:

const schema = {
type: "array",
items: {
type: "string"
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Arrays of objects

Arrays of objects can be specified as follows:

const schema = {
type: "array",
items: {
type: "object",
properties: {
name: {
type: "string"
}
}
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

uiSchema for array items

To specify a uiSchema that applies to array items, specify the uiSchema value within the items property:

const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
items: {
"ui:widget": "textarea"
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

The additionalItems keyword

The additionalItems keyword allows the user to add additional items of a given schema. For example:

const schema = {
type: "array",
items: {
type: "string"
},
additionalItems: {
type: "boolean"
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Array item options

orderable option

Array items are orderable by default, and react-jsonschema-form renders move up/down buttons alongside them. The uiSchema orderable options allows you to disable ordering:

const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
"ui:options": {
orderable: false
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

addable option

If either items or additionalItems contains a schema object, an add button for new items is shown by default. You can turn this off with the addable option in uiSchema:

const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
"ui:options": {
addable: false
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

removable option

A remove button is shown by default for an item if items contains a schema object, or the item is an additionalItems instance. You can turn this off with the removable option in uiSchema:

const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
"ui:options": {
removable: false
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

Multiple-choice list

The default behavior for array fields is a list of text inputs with add/remove buttons. There are two alternative widgets for picking multiple elements from a list of choices. Typically this applies when a schema has an enum list for the items property of an array field, and the uniqueItems property set to true.

Example:

const schema = {
type: "array",
title: "A multiple-choice list",
items: {
type: "string",
enum: ["foo", "bar", "fuzz", "qux"],
},
uniqueItems: true
};

render((
<Form schema={schema} />
), document.getElementById("app"));

By default, this will render a multiple select box. If you prefer a list of checkboxes, just set the uiSchema ui:widget directive to checkboxes for that field:

const schema = {
type: "array",
title: "A multiple-choice list",
items: {
type: "string",
enum: ["foo", "bar", "fuzz", "qux"],
},
uniqueItems: true
};

const uiSchema = {
"ui:widget": "checkboxes"
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

Specifying the minimum or maximum number of items

Note that when an array property is marked as required, an empty array is considered valid. If the array needs to be populated, you can specify the minimum number of items using the minItems property.

Example:

const schema = {
type: "array",
minItems: 2,
title: "A multiple-choice list",
items: {
type: "string",
enum: ["foo", "bar", "fuzz", "qux"],
},
uniqueItems: true
};

render((
<Form schema={schema} />
), document.getElementById("app"));

You can also specify the maximum number of items in an array using the maxItems property.

Inline checkboxes

By default, checkboxes are stacked. If you prefer them inline, set the inline property to true:

const schema = {
type: "array",
minItems: 2,
title: "A multiple-choice list",
items: {
type: "string",
enum: ["foo", "bar", "fuzz", "qux"],
},
uniqueItems: true
};

const uiSchema = {
"ui:widget": "checkboxes",
"ui:options": {
inline: true
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));
- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/definitions/index.html b/docs/version-3.2.1/usage/definitions/index.html index 57c9052e20..d3f9f676e5 100644 --- a/docs/version-3.2.1/usage/definitions/index.html +++ b/docs/version-3.2.1/usage/definitions/index.html @@ -4,13 +4,13 @@ Schema definitions and references | react-jsonschema-form - +
Version: v3

Schema definitions and references

This library partially supports inline schema definition dereferencing, which is Barbarian for avoiding to copy and paste commonly used field schemas:

const schema = {
"definitions": {
"address": {
"type": "object",
"properties": {
"street_address": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" }
},
"required": ["street_address", "city", "state"]
}
},
"type": "object",
"properties": {
"billing_address": { "$ref": "#/definitions/address" },
"shipping_address": { "$ref": "#/definitions/address" }
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Note that this library only supports local definition referencing. The value in the $ref keyword should be a JSON Pointer in URI fragment identifier format.

- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/dependencies/index.html b/docs/version-3.2.1/usage/dependencies/index.html index 557f52400a..29a4f0b97d 100644 --- a/docs/version-3.2.1/usage/dependencies/index.html +++ b/docs/version-3.2.1/usage/dependencies/index.html @@ -4,14 +4,14 @@ Dependencies | react-jsonschema-form - +
Version: v3

Dependencies

react-jsonschema-form supports the dependencies keyword from an earlier draft of JSON Schema (note that this is not part of the latest JSON Schema spec, though). Dependencies can be used to create dynamic schemas that change fields based on what data is entered.

Property dependencies

This library supports conditionally making fields required based on the presence of other fields.

Unidirectional

In the following example the billing_address field will be required if credit_card is defined.

const schema = {
"type": "object",

"properties": {
"name": { "type": "string" },
"credit_card": { "type": "number" },
"billing_address": { "type": "string" }
},

"required": ["name"],

"dependencies": {
"credit_card": ["billing_address"]
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Bidirectional

In the following example the billing_address field will be required if credit_card is defined and the credit_card field will be required if billing_address is defined, making them both required if either is defined.

const schema = {
"type": "object",

"properties": {
"name": { "type": "string" },
"credit_card": { "type": "number" },
"billing_address": { "type": "string" }
},

"required": ["name"],

"dependencies": {
"credit_card": ["billing_address"],
"billing_address": ["credit_card"]
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

(Sample schemas courtesy of the Space Telescope Science Institute)

Schema dependencies

This library also supports modifying portions of a schema based on form data.

Conditional

const schema = {
"type": "object",

"properties": {
"name": { "type": "string" },
"credit_card": { "type": "number" }
},

"required": ["name"],

"dependencies": {
"credit_card": {
"properties": {
"billing_address": { "type": "string" }
},
"required": ["billing_address"]
}
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

In this example the billing_address field will be displayed in the form if credit_card is defined.

(Sample schemas courtesy of the Space Telescope Science Institute)

Dynamic

The JSON Schema standard says that the dependency is triggered if the property is present. However, sometimes it's useful to have more sophisticated rules guiding the application of the dependency. For example, maybe you have three possible values for a field, and each one should lead to adding a different question. For this, we support a very restricted use of the oneOf keyword.

const schema = {
"title": "Person",
"type": "object",
"properties": {
"Do you have any pets?": {
"type": "string",
"enum": [
"No",
"Yes: One",
"Yes: More than one"
],
"default": "No"
}
},
"required": [
"Do you have any pets?"
],
"dependencies": {
"Do you have any pets?": {
"oneOf": [
{
"properties": {
"Do you have any pets?": {
"enum": [
"No"
]
}
}
},
{
"properties": {
"Do you have any pets?": {
"enum": [
"Yes: One"
]
},
"How old is your pet?": {
"type": "number"
}
},
"required": [
"How old is your pet?"
]
},
{
"properties": {
"Do you have any pets?": {
"enum": [
"Yes: More than one"
]
},
"Do you want to get rid of any?": {
"type": "boolean"
}
},
"required": [
"Do you want to get rid of any?"
]
}
]
}
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

In this example the user is prompted with different follow-up questions dynamically based on their answer to the first question.

In these examples, the "Do you have any pets?" question is validated against the corresponding property in each schema in the oneOf array. If exactly one matches, the rest of that schema is merged with the existing schema.

- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/index.html b/docs/version-3.2.1/usage/index.html index e729de5e93..a857aaa89c 100644 --- a/docs/version-3.2.1/usage/index.html +++ b/docs/version-3.2.1/usage/index.html @@ -4,13 +4,13 @@ Usage and Customization | react-jsonschema-form - +
- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/objects/index.html b/docs/version-3.2.1/usage/objects/index.html index 698bf1bc24..bf8f90b6f9 100644 --- a/docs/version-3.2.1/usage/objects/index.html +++ b/docs/version-3.2.1/usage/objects/index.html @@ -4,13 +4,13 @@ Objects | react-jsonschema-form - +
Version: v3

Objects

Object properties

Objects are defined with a type equal to object and properties specified in the properties keyword.

const schema = {
"title": "My title",
"description": "My description",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Required properties

You can specify which properties are required using the required attribute:

const schema = {
"title": "My title",
"description": "My description",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"required": ["name"]
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Specifying property order

Since the order of object properties in Javascript and JSON is not guaranteed, the uiSchema object spec allows you to define the order in which properties are rendered using the ui:order property:

const schema = {
type: "object",
properties: {
foo: {type: "string"},
bar: {type: "string"}
}
};

const uiSchema = {
"ui:order": ["bar", "foo"]
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

If a guaranteed fixed order is only important for some fields, you can insert a wildcard "*" item in your ui:order definition. All fields that are not referenced explicitly anywhere in the list will be rendered at that point:

const uiSchema = {
"ui:order": ["bar", "*"]
};

Additional properties

The additionalProperties keyword allows the user to add properties with arbitrary key names. Set this keyword equal to a schema object:

const schema = {
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"additionalProperties": {
"type": "number",
"enum": [1, 2, 3]
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

In this way, an add button for new properties is shown by default.

You can also define uiSchema options for additionalProperties by setting the additionalProperties attribute in the uiSchema.

expandable option

You can turn support for additionalProperties off with the expandable option in uiSchema:

const uiSchema = {
"ui:options": {
expandable: false
}
};
- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/oneof/index.html b/docs/version-3.2.1/usage/oneof/index.html index 1a361fd9d1..b53aed114a 100644 --- a/docs/version-3.2.1/usage/oneof/index.html +++ b/docs/version-3.2.1/usage/oneof/index.html @@ -4,13 +4,13 @@ oneOf, anyOf, and allOf | react-jsonschema-form - +
Version: v3

oneOf, anyOf, and allOf

react-jsonschema-form supports custom widgets for oneOf, anyOf, and allOf.

  • A schema with oneOf is valid if exactly one of the subschemas is valid.
  • A schema with anyOf is valid if at least one of the subschemas is valid.
  • A schema with allOf is valid if all of the subschemas are valid.

oneOf

const schema = {
type: "object",
oneOf: [
{
properties: {
lorem: {
type: "string",
},
},
required: ["lorem"],
},
{
properties: {
ipsum: {
type: "string",
},
},
required: ["ipsum"],
},
],
};

render((
<Form schema={schema} />
), document.getElementById("app"));

anyOf

const schema = {
type: "object",
anyOf: [
{
properties: {
lorem: {
type: "string",
},
},
required: ["lorem"],
},
{
properties: {
lorem: {
type: "string",
},
ipsum: {
type: "string",
},
}
},
],
};

render((
<Form schema={schema} />
), document.getElementById("app"));

allOf

When allOf is specified in a schema, react-jsonschema-form uses the json-schema-merge-allof library to merge the specified subschemas to create a combined subschema that is valid. For example, the below schema evaluates to a combined subschema of {type: "boolean"}:

const schema = {
title: "Field",
allOf: [
{
type: ["string", "boolean"]
},
{
type: "boolean"
},
],
};

render((
<Form schema={schema} />
), document.getElementById("app"));
- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/single/index.html b/docs/version-3.2.1/usage/single/index.html index a31a11438e..87057a5ec2 100644 --- a/docs/version-3.2.1/usage/single/index.html +++ b/docs/version-3.2.1/usage/single/index.html @@ -4,13 +4,13 @@ Single fields | react-jsonschema-form - +
Version: v3

Single fields

The simplest example of a JSON Schema contains only a single field. The field type is determined by the type parameter.

Field types

The base field types in JSON Schema include:

  • string
  • number
  • integer
  • boolean
  • null

Here is an example of a string field:

const schema = {
type: "string"
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Titles and descriptions

Fields can have titles and descriptions specified by the title keyword in the schema and description keyword in the schema, respectively. These two can also be overriden by the ui:title and ui:description keywords in the uiSchema.

const schema = {
title: "My form",
description: "My description",
type: "string"
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Enumerated values

All base schema types support the enum attribute, which restricts the user to select among a list of options. For example:

const schema = {
type: "string",
enum: ["one", "two", "three"]
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Custom labels for enum fields

This library supports a custom enumNames property for enum fields, which, however is not JSON-Schema compliant (see below for a compliant approach). The enumNames property allows defining custom labels for each option of an enum:

const schema = {
type: "number",
enum: [1, 2, 3],
enumNames: ["one", "two", "three"]
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Alternative JSON-Schema compliant approach

JSON Schema has an alternative approach to enumerations using anyOf; react-jsonschema-form supports it as well.

const schema = {
"type": "number",
"anyOf": [
{
"type": "number",
"title": "one",
"enum": [
1
]
},
{
"type": "number",
"title": "two",
"enum": [
2
]
},
{
"type": "number",
"title": "three",
"enum": [
3
]
}
]
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Disabled attribute for enum fields

To disable an option, use the ui:enumDisabled property in the uiSchema.

const schema = {
type: "boolean",
enum: [true, false]
};

const uiSchema={
"ui:enumDisabled": [true],
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

Nullable types

JSON Schema supports specifying multiple types in an array; however, react-jsonschema-form only supports a restricted subset of this -- nullable types, in which an element is either a given type or equal to null.

const schema = {
type: ["string", "null"]
};

render((
<Form schema={schema} />
), document.getElementById("app"));
- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/themes/index.html b/docs/version-3.2.1/usage/themes/index.html index f34aea0f92..b225b15b1e 100644 --- a/docs/version-3.2.1/usage/themes/index.html +++ b/docs/version-3.2.1/usage/themes/index.html @@ -4,7 +4,7 @@ Themes | react-jsonschema-form - + @@ -12,7 +12,7 @@
Version: v3

Themes

By default, this library renders form fields and widgets leveraging the Bootstrap semantics, meaning that you must load the Bootstrap stylesheet on the page to view the form properly. You can use another theme by importing one of the packages listed below.

Supported themes

Theme NameStatusPackage Name / Link
Bootstrap 3 (default)Published@rjsf/core
Bootstrap 4Published@rjsf/bootstrap-4
material-uiPublished@rjsf/material-ui
fluent-uiPublished@rjsf/fluent-ui
antdPublished@rjsf/antd
Semantic UIPublished@rjsf/semantic-ui

Using themes

To use a theme from a package, just import the <Form /> component from that package. For example, to use the material ui form, first install both @rjsf/core and @rjsf/material-ui. Then you can import the form by doing:

import Form from "@rjsf/material-ui";

If you would like to contribute a theme with a new UI framework, please develop the theme using the withTheme component described in Theme Customization and make a PR!

You can also use the uiSchema to add custom CSS class names to your form.

Customizing with other frameworks

The default theme is bootstrap 3. In order to use another theme, you must first install @rjsf/core.

For example, to use the standard bootstrap 3 form, you can run:

import Form from "@rjsf/core";

To use the material-ui form, you should first install both @rjsf/core and @rjsf/material-ui. Then, you can run:

import Form from "@rjsf/material-ui";

For more information on how to create a custom theme, see documentation on the withTheme component.

- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/validation/index.html b/docs/version-3.2.1/usage/validation/index.html index dfee029ba1..06d56108d7 100644 --- a/docs/version-3.2.1/usage/validation/index.html +++ b/docs/version-3.2.1/usage/validation/index.html @@ -4,14 +4,14 @@ Validation | react-jsonschema-form - +
Version: v3

Validation

When the form is submitted, the form data is validated to conform to the given JSON schema; this library uses the ajv validator by default.

Live validation

By default, form data are only validated when the form is submitted or when a new formData prop is passed to the Form component.

You can enable live form data validation by passing a liveValidate prop to the Form component, and set it to true. Then, every time a value changes within the form data tree (e.g. the user entering a character in a field), a validation operation is performed, and the validation results are reflected into the form state.

Be warned that this is an expensive strategy, with possibly strong impact on performances.

const schema = {
type: ["string"],
const: "test"
};

const formData = "a";

render((
<Form schema={schema} formData={formData} liveValidate />
), document.getElementById("app"));

HTML5 Validation

By default, the form uses HTML5 validation. This may cause unintuitive results because the HTML5 validation errors (such as when a field is required) may be displayed before the form is submitted, and thus these errors will display differently from the react-jsonschema-form validation errors. You can turn off HTML validation by setting the noHtml5Validate to true.

const schema = {
type: "object",
properties: {
name: {
type: "string",
required: true
}
}
};

render((
<Form schema={schema} noHtml5Validate />
), document.getElementById("app"));

Custom validation rules

Form data is always validated against the JSON schema.

But it is possible to define your own custom validation rules. This is especially useful when the validation depends on several interdependent fields.

function validate(formData, errors) {
if (formData.pass1 !== formData.pass2) {
errors.pass2.addError("Passwords don't match");
}
return errors;
}

const schema = {
type: "object",
properties: {
pass1: {type: "string", minLength: 3},
pass2: {type: "string", minLength: 3},
}
};

render((
<Form schema={schema}
validate={validate} />
), document.getElementById("app"));

Notes:

  • The validate() function must always return the errors object received as second argument.
  • The validate() function is called after the JSON schema validation.

Custom error messages

Validation error messages are provided by the JSON Schema validation by default. If you need to change these messages or make any other modifications to the errors from the JSON Schema validation, you can define a transform function that receives the list of JSON Schema errors and returns a new list.

function transformErrors(errors) {
return errors.map(error => {
if (error.name === "pattern") {
error.message = "Only digits are allowed"
}
return error;
});
}

const schema = {
type: "object",
properties: {
onlyNumbersString: {type: "string", pattern: "^\\d*$"},
}
};

render((
<Form schema={schema}
transformErrors={transformErrors} />
), document.getElementById("app"));

Notes:

  • The transformErrors() function must return the list of errors. Modifying the list in place without returning it will result in an error.

Each element in the errors list passed to transformErrors has the following properties:

  • name: name of the error, for example, "required" or "minLength"
  • message: message, for example, "is a required property" or "should NOT be shorter than 3 characters"
  • params: an object with the error params returned by ajv (see doc for more info).
  • property: a string in Javascript property accessor notation to the data path of the field with the error. For example, .name or ['first-name'].
  • stack: full error name, for example ".name is a required property".
  • schemaPath: JSON pointer to the schema of the keyword that failed validation. For example, #/fields/firstName/required. (Note: this may sometimes be wrong due to a bug in ajv).

Error List Display

To take control over how the form errors are displayed, you can define an error list template for your form. This list is the form global error list that appears at the top of your forms.

An error list template is basically a React stateless component being passed errors as props so you can render them as you like:

function ErrorListTemplate(props) {
const { errors } = props;
return (
<div>
<h2>Custom error list</h2>
<ul>
{errors.map(error => (
<li key={error.stack}>
{error.stack}
</li>
))}
</ul>
</div>
);
}

const schema = {
type: "string",
const: "test"
};

render((
<Form schema={schema}
showErrorList={true}
formData={""}
liveValidate
ErrorList={ErrorListTemplate} />
), document.getElementById("app"));

Note: Your custom ErrorList template will only render when showErrorList is true.

The following props are passed to ErrorList

  • errors: An array of the errors.
  • errorSchema: The errorSchema constructed by Form.
  • schema: The schema that was passed to Form.
  • uiSchema: The uiSchema that was passed to Form.
  • formContext: The formContext object that you passed to Form.

The case of empty strings

When a text input is empty, the field in form data is set to undefined. String fields that use enum and a select widget will have an empty option at the top of the options list that when selected will result in the field being undefined.

One consequence of this is that if you have an empty string in your enum array, selecting that option in the select input will cause the field to be set to undefined, not an empty string.

If you want to have the field set to a default value when empty you can provide a ui:emptyValue field in the uiSchema object.

Custom meta schema validation

To have your schemas validated against any other meta schema than draft-07 (the current version of JSON Schema), make sure your schema has a $schema attribute that enables the validator to use the correct meta schema. For example:

{
"$schema": "http://json-schema.org/draft-04/schema#",
...
}

Note that react-jsonschema-form only supports the latest version of JSON Schema, draft-07, by default. To support additional meta schemas pass them through the additionalMetaSchemas prop to the Form component.

additionalMetaSchemas

The additionalMetaSchemas prop allows you to validate the form data against one (or more than one) JSON Schema meta schema, for example, JSON Schema draft-04. You can import a meta schema as follows:

const metaSchemaDraft04 = require("ajv/lib/refs/json-schema-draft-04.json");

In this example schema passed as props to Form component can be validated against draft-07 (default) and by draft-04 (added), depending on the value of $schema attribute.

const schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
type: "string"
};

return (<Form schema={schema}
additionalMetaSchemas={[metaSchemaDraft04]} />);

customFormats

Pre-defined semantic formats are limited. react-jsonschema-form adds two formats, color and data-url, to support certain alternative widgets. You can add formats of your own through the customFormats prop to your Form component:

const schema = {
type: 'string',
format: 'phone-us'
};

const customFormats = {
'phone-us': /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/
};

render((
<Form schema={schema}
customFormats={customFormats}/>
), document.getElementById("app"));

Format values can be anything AJV's addFormat method accepts.

Async validation

Handling async errors is an important part of many applications. Support for this is added in the form of the extraErrors prop.

For example, a request could be made to some backend when the user submits the form. If that request fails, the errors returned by the backend should be formatted like in the following example.

const schema = {
type: "object",
properties: {
foo: {
type: "string",
},
candy: {
type: "object",
properties: {
bar: {
type: "string",
}
}
}
}
};

const extraErrors = {
foo: {
__errors: ["some error that got added as a prop"],
},
candy: {
bar: {
__errors: ["some error that got added as a prop"],
}
}
};

render((
<Form schema={schema}
extraErrors={extraErrors} />
), document.getElementById("app"));

An important note is that these errors are "display only" and will not block the user from submitting the form again.

- + \ No newline at end of file diff --git a/docs/version-3.2.1/usage/widgets/index.html b/docs/version-3.2.1/usage/widgets/index.html index 49cb55e4c3..d9d8f424ed 100644 --- a/docs/version-3.2.1/usage/widgets/index.html +++ b/docs/version-3.2.1/usage/widgets/index.html @@ -4,13 +4,13 @@ Widgets | react-jsonschema-form - +
Version: v3

Widgets

The uiSchema ui:widget property tells the form which UI widget should be used to render a field.

Example:

const schema = {
type: "object",
properties: {
done: {
type: "boolean"
}
}
};

const uiSchema =  {
done: {
"ui:widget": "radio" // could also be "select"
}
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

Here's a list of supported alternative widgets for different JSON Schema data types:

For boolean fields

  • radio: a radio button group with true and false as selectable values;
  • select: a select box with true and false as options;
  • by default, a checkbox is used

Note: To set the labels for a boolean field, instead of using true and false you can set enumNames in your schema. Note that enumNames belongs in your schema, not the uiSchema, and the order is always [true, false].

For string fields

  • textarea: a textarea element is used;
  • password: an input[type=password] element is used;
  • color: an input[type=color] element is used;
  • by default, a regular input[type=text] element is used.

String formats

The built-in string field also supports the JSON Schema format property, and will render an appropriate widget by default for the following string formats:

  • email: An input[type=email] element is used;
  • uri: An input[type=url] element is used;
  • data-url: By default, an input[type=file] element is used; in case the string is part of an array, multiple files will be handled automatically (see File widgets).
  • date: By default, an input[type=date] element is used;
  • date-time: By default, an input[type=datetime-local] element is used.

Please note that, even though they are standardized, datetime-local and date input elements are not yet supported by Firefox and IE. If you plan on targeting these platforms, two alternative widgets are available:

  • alt-datetime: Six select elements are used to select the year, the month, the day, the hour, the minute and the second;
  • alt-date: Three select elements are used to select the year, month and the day.

Firefox 57 - 66: Firefox partially supporting date and time input types, but not datetime-local, month or week

You can customize the list of years displayed in the year dropdown by providing a yearsRange property to ui:options in your uiSchema. Its also possible to remove the Now and Clear buttons with the hideNowButton and hideClearButton options.

const schema = {
type: "string"
};

const uiSchema = {
"ui:widget": "alt-datetime",
"ui:options": {
yearsRange: [1980, 2030],
hideNowButton: true,
hideClearButton: true,
}
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

For number and integer fields

  • updown: an input[type=number] updown selector;
  • range: an input[type=range] slider;
  • radio: a radio button group with enum values. This can only be used when enum values are specified for this input.
  • By default, a regular input[type=text] element is used.

Note: If JSON Schema's minimum, maximum and multipleOf values are defined, the min, max and step input attributes values will take those values.

Hidden widgets

It's possible to use a hidden widget for a field by setting its ui:widget uiSchema directive to hidden:

const schema = {
type: "object",
properties: {
foo: {type: "boolean"}
}
};

const uiSchema = {
foo: {"ui:widget": "hidden"}
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

Notes:

  • Hiding widgets is only supported for boolean, string, number and integer schema types;
  • A hidden widget takes its value from the formData prop.

File widgets

This library supports a limited form of input[type=file] widgets, in the sense that it will propagate file contents to form data state as data-urls.

There are two ways to use file widgets.

  1. By declaring a string json schema type along a data-url format:
const schema = {
type: "string",
format: "data-url",
};

render((
<Form schema={schema} />
), document.getElementById("app"));
  1. By specifying a ui:widget field uiSchema directive as file:
const schema = {
type: "string",
};

const uiSchema = {
"ui:widget": "file",
};

Multiple files

Multiple files selectors are supported by defining an array of strings having data-url as a format:

const schema = {
type: "array",
items: {
type: "string",
format: "data-url",
}
};

Note that storing large dataURIs into form state might slow rendering.

File widget input ref

The included FileWidget exposes a reference to the <input type="file" /> element node as an inputRef component property.

This allows you to programmatically trigger the browser's file selector, which can be used in a custom file widget.

accept option

You can use the accept attribute to specify a filter for what file types the user can upload:

const schema = {
type: "string",
format: "data-url"
};

const uiSchema = {
"ui:options": { accept: ".pdf" }
};
- + \ No newline at end of file diff --git a/docs/version-4.2.3/advanced-customization/custom-templates/index.html b/docs/version-4.2.3/advanced-customization/custom-templates/index.html index 7cf1adf3fa..13cf7ca1df 100644 --- a/docs/version-4.2.3/advanced-customization/custom-templates/index.html +++ b/docs/version-4.2.3/advanced-customization/custom-templates/index.html @@ -4,14 +4,14 @@ Custom Templates | react-jsonschema-form - +
Version: v4

Custom Templates

This is an advanced feature that lets you customize even more aspects of the form:

_Custom FieldCustom TemplateCustom Widget
What it doesOverrides all behaviourOverrides just the layout (not behaviour)Overrides just the input box (not layout, labels, or help, or validation)
UsageGlobal or per-fieldGlobal or per-fieldGlobal or per-field
Global Example<Form fields={MyCustomField} /><Form ArrayFieldTemplate={MyArrayTemplate} /><Form widgets={MyCustomWidget} />
Per-Field Example"ui:field": MyCustomField"ui:ArrayFieldTemplate": MyArrayTemplate"ui:widget":MyCustomWidget
DocumentationCustom FieldsFieldTemplate / ArrayFieldTemplate / ObjectFieldTemplateCustom Widgets

ArrayFieldTemplate

You can use an ArrayFieldTemplate to customize how your arrays are rendered. This allows you to customize your array, and each element in the array. You can also customize arrays by specifying a widget in the relevant ui:widget schema, more details over on Custom Widgets.

const schema = {
type: "array",
items: {
type: "string"
}
};

function ArrayFieldTemplate(props) {
return (
<div>
{props.items.map(element => element.children)}
{props.canAdd && <button type="button" onClick={props.onAddClick}></button>}
</div>
);
}

render((
<Form schema={schema}
ArrayFieldTemplate={ArrayFieldTemplate} />
), document.getElementById("app"));

You also can provide your own field template to a uiSchema by specifying a ui:ArrayFieldTemplate property.

const uiSchema = {
"ui:ArrayFieldTemplate": ArrayFieldTemplate
}

Please see customArray.js for another example.

The following props are passed to each ArrayFieldTemplate:

  • DescriptionField: The DescriptionField from the registry (in case you wanted to utilize it)
  • TitleField: The TitleField from the registry (in case you wanted to utilize it).
  • canAdd: A boolean value stating whether new elements can be added to the array.
  • className: The className string.
  • disabled: A boolean value stating if the array is disabled.
  • idSchema: Object
  • items: An array of objects representing the items in the array. Each of the items represent a child with properties described below.
  • onAddClick: (event?) => void: A function that adds a new item to the array.
  • readonly: A boolean value stating if the array is read-only.
  • required: A boolean value stating if the array is required.
  • schema: The schema object for this array.
  • uiSchema: The uiSchema object for this array field.
  • title: A string value containing the title for the array.
  • formContext: The formContext object that you passed to Form.
  • formData: The formData for this array.
  • registry: The registry object.

The following props are part of each element in items:

  • children: The html for the item's content.
  • className: The className string.
  • disabled: A boolean value stating if the array item is disabled.
  • hasMoveDown: A boolean value stating whether the array item can be moved down.
  • hasMoveUp: A boolean value stating whether the array item can be moved up.
  • hasRemove: A boolean value stating whether the array item can be removed.
  • hasToolbar: A boolean value stating whether the array item has a toolbar.
  • index: A number stating the index the array item occurs in items.
  • key: A stable, unique key for the array item.
  • onAddIndexClick: (index) => (event?) => void: Returns a function that adds a new item at index.
  • onDropIndexClick: (index) => (event?) => void: Returns a function that removes the item at index.
  • onReorderClick: (index, newIndex) => (event?) => void: Returns a function that swaps the items at index with newIndex.
  • readonly: A boolean value stating if the array item is read-only.

Note: Array and object field templates are always rendered inside of the FieldTemplate. To fully customize an array field template, you may need to specify both ui:FieldTemplate and ui:ArrayFieldTemplate.

FieldTemplate

To take control over the inner organization of each field (each form row), you can define a field template for your form.

A field template is basically a React stateless component being passed field-related props, allowing you to structure your form row as you like.

const schema = {
type: "string"
};

function CustomFieldTemplate(props) {
const {id, classNames, label, help, required, description, errors, children} = props;
return (
<div className={classNames}>
<label htmlFor={id}>{label}{required ? "*" : null}</label>
{description}
{children}
{errors}
{help}
</div>
);
}

render((
<Form schema={schema}
FieldTemplate={CustomFieldTemplate} />
), document.getElementById("app"));

You also can provide your own field template to a uiSchema by specifying a ui:FieldTemplate property.

const uiSchema = {
"ui:FieldTemplate": CustomFieldTemplate
}

If you want to handle the rendering of each element yourself, you can use the props rawHelp, rawDescription and rawErrors.

The following props are passed to a custom field template component:

  • id: The id of the field in the hierarchy. You can use it to render a label targeting the wrapped widget.
  • classNames: A string containing the base Bootstrap CSS classes, merged with any custom ones defined in your uiSchema.
  • label: The computed label for this field, as a string.
  • description: A component instance rendering the field description, if one is defined (this will use any custom DescriptionField defined).
  • rawDescription: A string containing any ui:description uiSchema directive defined.
  • children: The field or widget component instance for this field row.
  • errors: A component instance listing any encountered errors for this field.
  • rawErrors: An array of strings listing all generated error messages from encountered errors for this field.
  • help: A component instance rendering any ui:help uiSchema directive defined.
  • rawHelp: A string containing any ui:help uiSchema directive defined. NOTE: rawHelp will be undefined if passed ui:help is a React component instead of a string.
  • hidden: A boolean value stating if the field should be hidden.
  • required: A boolean value stating if the field is required.
  • readonly: A boolean value stating if the field is read-only.
  • hideError: A boolean value stating if the field is hiding its errors
  • disabled: A boolean value stating if the field is disabled.
  • displayLabel: A boolean value stating if the label should be rendered or not. This is useful for nested fields in arrays where you don't want to clutter the UI.
  • fields: An array containing all Form's fields including your custom fields and the built-in fields.
  • schema: The schema object for this field.
  • uiSchema: The uiSchema object for this field.
  • onChange: The value change event handler; Can be called with a new value to change the value for this field.
  • formContext: The formContext object that you passed to Form.
  • formData: The formData for this field.
  • registry: The registry object.

Note: you can only define a single global field template for a form, but you can set individual field templates per property using "ui:FieldTemplate".

ObjectFieldTemplate

const schema = {
type: "object",
title: "Object title",
description: "Object description",
properties: {
name: {
type: "string"
},
age: {
type: "number"
}
}
};

function ObjectFieldTemplate(props) {
return (
<div>
{props.title}
{props.description}
{props.properties.map(element => <div className="property-wrapper">{element.content}</div>)}
</div>
);
}

render((
<Form schema={schema}
ObjectFieldTemplate={ObjectFieldTemplate} />
), document.getElementById("app"));

You also can provide your own field template to a uiSchema by specifying a ui:ObjectFieldTemplate property.

const uiSchema = {
"ui:ObjectFieldTemplate": ObjectFieldTemplate
};

Please see customObject.js for a better example.

The following props are passed to each ObjectFieldTemplate:

  • DescriptionField: The DescriptionField from the registry (in case you wanted to utilize it)
  • TitleField: The TitleField from the registry (in case you wanted to utilize it).
  • title: A string value containing the title for the object.
  • description: A string value containing the description for the object.
  • disabled: A boolean value stating if the object is disabled.
  • properties: An array of object representing the properties in the array. Each of the properties represent a child with properties described below.
  • onAddClick: (schema: JSONSchema7) => () => void: Returns a function that adds a new property to the object (to be used with additionalProperties)
  • readonly: A boolean value stating if the object is read-only.
  • required: A boolean value stating if the object is required.
  • schema: The schema object for this object.
  • uiSchema: The uiSchema object for this object field.
  • idSchema: An object containing the id for this object & ids for it's properties.
  • formData: The form data for the object.
  • formContext: The formContext object that you passed to Form.
  • registry: The registry object.

The following props are part of each element in properties:

  • content: The html for the property's content.
  • name: A string representing the property name.
  • disabled: A boolean value stating if the object property is disabled.
  • readonly: A boolean value stating if the property is read-only.
  • hidden: A boolean value stating if the property should be hidden.

Note: Array and object field templates are always rendered inside of the FieldTemplate. To fully customize an object field template, you may need to specify both ui:FieldTemplate and ui:ObjectFieldTemplate.

- + \ No newline at end of file diff --git a/docs/version-4.2.3/advanced-customization/custom-themes/index.html b/docs/version-4.2.3/advanced-customization/custom-themes/index.html index 688ae1d608..d3e63ad38d 100644 --- a/docs/version-4.2.3/advanced-customization/custom-themes/index.html +++ b/docs/version-4.2.3/advanced-customization/custom-themes/index.html @@ -4,13 +4,13 @@ Custom Themes | react-jsonschema-form - +
Version: v4

Custom Themes

The withTheme component provides an easy way to extend the functionality of react-jsonschema-form by passing in a theme object that defines custom/overridden widgets and fields, as well as any of the other possible properties of the standard rjsf Form component. This theme-defining object is passed as the only parameter to the HOC (withTheme(ThemeObj)), and the HOC will return a themed-component which you use instead of the standard Form component.

Usage

import React, { Component } from 'react';
import { withTheme } from '@rjsf/core';

const theme = { widgets: {test: () => (<div>test</div>) } };

const ThemedForm = withTheme(theme);

const Demo = () => (
<ThemedForm schema={schema} uiSchema={uiSchema} />
);

Theme object properties

The Theme object consists of the same properties as the rjsf Form component (such as widgets and fields). The themed-Form component merges together any theme-specific widgets and fields with the default widgets and fields. For instance, providing a single widget in widgets will merge this widget with all the default widgets of the rjsf Form component, but overrides the default if the theme's widget's name matches the default widget's name. Thus, for each default widget or field not specified/overridden, the themed-form will rely on the defaults from the rjsf Form. Note that you are not required to pass in either custom widgets or fields when using the custom-themed HOC component; you can make the essentially redefine the default Form by simply doing const Form = withTheme({});.

Widgets and fields

widgets and fields should be in the same format as shown here.

Example theme with custom widget:

const MyCustomWidget = (props) => {
return (
<input type="text"
className="custom"
value={props.value}
required={props.required}
onChange={(event) => props.onChange(event.target.value)} />
);
};

const myWidgets = {
myCustomWidget: MyCustomWidget
};

const ThemeObject = {widgets: myWidgets};
export default ThemeObject;

The above can be similarly done for fields.

Templates

Each template should be passed directly into the theme object just as you would into the rjsf Form component. Here is an example of how to use a custom ArrayFieldTemplate and ErrorListTemplate in the theme object:

function MyArrayFieldTemplate(props) {
return (
<div>
{props.items.map(element => element.children)}
{props.canAdd && <button type="button" onClick={props.onAddClick}></button>}
</div>
);
}

function MyErrorListTemplate(props) {
const {errors} = props;
return (
<ul>
{errors.map(error => (
<li key={error.stack}>
{error.stack}
</li>
))}
</ul>
);
}

const ThemeObject = {
ArrayFieldTemplate: MyArrayFieldTemplate,
ErrorList: MyErrorListTemplate,
widgets: myWidgets
};

export default ThemeObject;

Overriding other Form props

Just as the theme can override widgets, fields, any of the field templates, and set default values to properties like showErrorList, you can do the same with the instance of the withTheme() Form component.

const ThemeObject = {
ArrayFieldTemplate: MyArrayFieldTemplate,
fields: myFields,
showErrorList: false,
widgets: myWidgets
};

Thus, the user has higher priority than the withTheme HOC, and the theme has higher priority than the default values of the rjsf Form component (User > Theme > Defaults).

- + \ No newline at end of file diff --git a/docs/version-4.2.3/advanced-customization/custom-widgets-fields/index.html b/docs/version-4.2.3/advanced-customization/custom-widgets-fields/index.html index 18add193c5..0657d1f135 100644 --- a/docs/version-4.2.3/advanced-customization/custom-widgets-fields/index.html +++ b/docs/version-4.2.3/advanced-customization/custom-widgets-fields/index.html @@ -4,13 +4,13 @@ Custom Widgets and Fields | react-jsonschema-form - +
Version: v4

Custom Widgets and Fields

The API allows to specify your own custom widget and field components:

  • A widget represents a HTML tag for the user to enter data, eg. input, select, etc.
  • A field usually wraps one or more widgets and most often handles internal field state; think of a field as a form row, including the labels.

Customizing the default fields and widgets

You can override any default field and widget, including the internal widgets like the CheckboxWidget that ObjectField renders for boolean values. You can override any field and widget just by providing the customized fields/widgets in the fields and widgets props:

const schema = {
type: "boolean",
default: true
};

const uiSchema = {
"ui:widget": "checkbox"
};

const CustomCheckbox = function(props) {
return (
<button id="custom" className={props.value ? "checked" : "unchecked"} onClick={() => props.onChange(!props.value)}>
{String(props.value)}
</button>
);
};

const widgets = {
CheckboxWidget: CustomCheckbox
};

render((
<Form schema={schema}
uiSchema={uiSchema}
widgets={widgets} />
), document.getElementById("app"));

This allows you to create a reusable customized form class with your custom fields and widgets:

const customFields = {StringField: CustomString};
const customWidgets = {CheckboxWidget: CustomCheckbox};

function MyForm(props) {
return <Form fields={customFields} widgets={customWidgets} {...props} />;
}

The default fields you can override are:

  • ArrayField
  • BooleanField
  • DescriptionField
  • OneOfField
  • AnyOfField
  • NullField
  • NumberField
  • ObjectField
  • SchemaField
  • StringField
  • TitleField
  • UnsupportedField

The default widgets you can override are:

  • AltDateTimeWidget
  • AltDateWidget
  • CheckboxesWidget
  • CheckboxWidget
  • ColorWidget
  • DateTimeWidget
  • DateWidget
  • EmailWidget
  • FileWidget
  • HiddenWidget
  • PasswordWidget
  • RadioWidget
  • RangeWidget
  • SelectWidget
  • TextareaWidget
  • TextWidget
  • UpDownWidget
  • URLWidget

Adding your own custom widgets

You can provide your own custom widgets to a uiSchema for the following json data types:

  • string
  • number
  • integer
  • boolean
  • array
const schema = {
type: "string"
};

const uiSchema = {
"ui:widget": (props) => {
return (
<input type="text"
className="custom"
value={props.value}
required={props.required}
onChange={(event) => props.onChange(event.target.value)} />
);
}
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

The following props are passed to custom widget components:

  • id: The generated id for this widget;
  • schema: The JSONSchema subschema object for this widget;
  • uiSchema: The uiSchema for this widget;
  • value: The current value for this widget;
  • placeholder: the placeholder for the field, if any;
  • required: The required status of this widget;
  • disabled: true if the widget is disabled;
  • readonly: true if the widget is read-only;
  • autofocus: true if the widget should autofocus;
  • onChange: The value change event handler; call it with the new value every time it changes;
  • onKeyChange: The key change event handler (only called for fields with additionalProperties); pass the new value every time it changes;
  • onBlur: The input blur event handler; call it with the the widget id and value;
  • onFocus: The input focus event handler; call it with the the widget id and value;
  • options: A map of options passed as a prop to the component (see Custom widget options).
  • options.enumOptions: For enum fields, this property contains the list of options for the enum as an array of { label, value } objects. If the enum is defined using the oneOf/anyOf syntax, the entire schema object for each option is appended onto the { schema, label, value } object.
  • formContext: The formContext object that you passed to Form.
  • rawErrors: An array of strings listing all generated error messages from encountered errors for this widget.
  • registry: A registry object (read next).

Custom component registration

Alternatively, you can register them all at once by passing the widgets prop to the Form component, and reference their identifier from the uiSchema:

const MyCustomWidget = (props) => {
return (
<input type="text"
className="custom"
value={props.value}
required={props.required}
onChange={(event) => props.onChange(event.target.value)} />
);
};

const widgets = {
myCustomWidget: MyCustomWidget
};

const schema = {
type: "string"
};

const uiSchema = {
"ui:widget": "myCustomWidget"
}

render((
<Form
schema={schema}
uiSchema={uiSchema}
widgets={widgets} />
), document.getElementById("app"));

This is useful if you expose the uiSchema as pure JSON, which can't carry functions.

Custom widget options

If you need to pass options to your custom widget, you can add a ui:options object containing those properties. If the widget has defaultProps, the options will be merged with the (optional) options object from defaultProps:

const schema = {
type: "string"
};

function MyCustomWidget(props) {
const {options} = props;
const {color, backgroundColor} = options;
return <input 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"));

Note: This also applies to registered custom components.

Note: Since v0.41.0, the ui:widget object API, where a widget and options were specified with "ui:widget": {component, options} shape, is deprecated. It will be removed in a future release.

Customizing widgets text input

All the widgets that render a text input use the BaseInput component internally. If you need to customize all text inputs without customizing all widgets individually, you can provide a BaseInput component in the widgets property of Form (see Custom component registration).

Custom field components

You can provide your own field components to a uiSchema for basically any json schema data type, by specifying a ui:field property.

For example, let's create and register a dumb geo component handling a latitude and a longitude:

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

// Define a custom component for handling the root position object
class GeoPosition extends React.Component {
constructor(props) {
super(props);
this.state = {...props.formData};
}

onChange(name) {
return (event) => {
this.setState({
[name]: parseFloat(event.target.value)
}, () => this.props.onChange(this.state));
};
}

render() {
const {lat, lon} = this.state;
return (
<div>
<input type="number" value={lat} onChange={this.onChange("lat")} />
<input type="number" value={lon} onChange={this.onChange("lon")} />
</div>
);
}
}

// 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"));

Note: Registered fields can be reused across the entire schema.

Field props

A field component will always be passed the following props:

  • schema: The JSON schema for this field;
  • uiSchema: The uiSchema for this field;
  • idSchema: The tree of unique ids for every child field;
  • formData: The data for this field;
  • errorSchema: The tree of errors for this field and its children;
  • registry: A registry object (read next).
  • formContext: A formContext object (read next).

The registry object

The registry is an object containing the registered custom fields and widgets as well as the root schema definitions.

The registry is passed down the component tree, so you can access it from your custom field, custom widget, and SchemaField components.

Custom SchemaField

Warning: This is a powerful feature as you can override the whole form behavior and easily mess it up. Handle with care.

You can provide your own implementation of the SchemaField base React component for rendering any JSONSchema field type, including objects and arrays. This is useful when you want to augment a given field type with supplementary powers.

To proceed so, pass a fields object having a SchemaField property to your Form component; here's an example:


const CustomSchemaField = function(props) {
return (
<div id="custom">
<p>Yeah, I'm pretty dumb.</p>
<div>My props are: {JSON.stringify(props)}</div>
</div>
);
};

const fields = {
SchemaField: CustomSchemaField
};

const schema = {
type: "string"
};

render((
<Form schema={schema}
fields={fields} />
), document.getElementById("app"));

If you're curious how this could ever be useful, have a look at the Kinto formbuilder repository to see how it's used to provide editing capabilities to any form field.

Props passed to a custom SchemaField are the same as the ones passed to a custom field.

NOTE: If you are using the material-ui theme and are considering customizing a widget or a field, checkout this guide.

- + \ No newline at end of file diff --git a/docs/version-4.2.3/advanced-customization/index.html b/docs/version-4.2.3/advanced-customization/index.html index 6e03a37cd7..547d96fa09 100644 --- a/docs/version-4.2.3/advanced-customization/index.html +++ b/docs/version-4.2.3/advanced-customization/index.html @@ -4,13 +4,13 @@ Advanced Customization | react-jsonschema-form - + - + \ No newline at end of file diff --git a/docs/version-4.2.3/advanced-customization/internals/index.html b/docs/version-4.2.3/advanced-customization/internals/index.html index 80abf33794..b19dc71977 100644 --- a/docs/version-4.2.3/advanced-customization/internals/index.html +++ b/docs/version-4.2.3/advanced-customization/internals/index.html @@ -4,14 +4,14 @@ Internals | react-jsonschema-form - +
Version: v4

Internals

Miscellaneous internals of react-jsonschema-form are listed here.

JSON Schema supporting status

This component follows JSON Schema specs. We currently support JSON Schema-07 by default, but we also support other JSON schema versions through the custom schema validation feature. Due to the limitation of form widgets, there are some exceptions as follows:

  • additionalItems keyword for arrays

    This keyword works when items is an array. additionalItems: true is not supported because there's no widget to represent an item of any type. In this case it will be treated as no additional items allowed. additionalItems being a valid schema is supported.

  • anyOf, allOf, and oneOf, or multiple types (i.e. "type": ["string", "array"])

    The anyOf and oneOf keywords are supported; however, properties declared inside the anyOf/oneOf should not overlap with properties "outside" of the anyOf/oneOf.

    You can also use oneOf with schema dependencies to dynamically add schema properties based on input data.

    The allOf keyword is supported; it uses json-schema-merge-allof to merge subschemas to render the final combined schema in the form. When these subschemas are incompatible, though (or if the library has an error merging it), the allOf keyword is dropped from the schema.

  • "additionalProperties":false produces incorrect schemas when used with schema dependencies. This library does not remove extra properties, which causes validation to fail. It is recommended to avoid setting "additionalProperties":false when you use schema dependencies. See #848 #902 #992

Handling of schema defaults

This library automatically fills default values defined in the JSON Schema as initial values in your form. This also works for complex structures in the schema. If a field has a default defined, it should always appear as default value in form. This also works when using schema dependencies.

Since there is a complex interaction between any supplied original form data and any injected defaults, this library tries to do the injection in a way which keeps the original intention of the original form data.

Check out the defaults example on the live playground to see this in action.

Merging of defaults into the form data

There are three different cases which need to be considered for the merging. Objects, arrays and scalar values. This library always deeply merges any defaults with the existing form data for objects.

This are the rules which are used when injecting the defaults:

  • When there is a scalar in the form data, nothing is changed.
  • When the value is undefined in the form data, the default is created in the form data.
  • When the value is an object in the form data, the defaults are deeply merged into the form data, using the rules defined here for the deep merge.
  • Then the value is an array in the form data, defaults are only injected in existing array items. No new array items will be created, even if the schema has minItems or additional items defined.

Merging of defaults within the schema

In the schema itself, defaults of parent elements are propagated into children. So when you have a schema which defines a deeply nested object as default, these defaults will be applied to children of the current node. This also merges objects defined at different levels together with the "deeper" not having precedence. If the parent node defines properties, which are not defined in the child, they will be merged so that the default for the child will be the merged defaults of parent and child.

For arrays this is not the case. Defining an array, when a parent also defines an array, will be overwritten. This is only true when arrays are used in the same level, for objects within these arrays, they will be deeply merged again.

Custom array field buttons

The ArrayField component provides a UI to add, remove and reorder array items, and these buttons use Bootstrap glyphicons. If you don't use glyphicons but still want to provide your own icons or texts for these buttons, you can easily do so using CSS:

i.glyphicon { display: none; }
.btn-add::after { content: 'Add'; }
.array-item-move-up::after { content: 'Move Up'; }
.array-item-move-down::after { content: 'Move Down'; }
.array-item-remove::after { content: 'Remove'; }

Submit form programmatically

You can use the reference to get your Form component and call the submit method to submit the form programmatically without a submit button. This method will dispatch the submit event of the form, and the function, that is passed to onSubmit props, will be called.

const onSubmit = ({formData}) => console.log("Data submitted: ",  formData);
let yourForm;

const schema = {
type: "string"
};

render((
<Form schema={schema}
onSubmit={onSubmit} ref={(form) => {yourForm = form;}}/>
), document.getElementById("app"));

yourForm.submit();
- + \ No newline at end of file diff --git a/docs/version-4.2.3/advanced-customization/material-ui/customizing-material-ui/index.html b/docs/version-4.2.3/advanced-customization/material-ui/customizing-material-ui/index.html index 8894663f73..7ccde1bfe6 100644 --- a/docs/version-4.2.3/advanced-customization/material-ui/customizing-material-ui/index.html +++ b/docs/version-4.2.3/advanced-customization/material-ui/customizing-material-ui/index.html @@ -4,7 +4,7 @@ Customizing material-ui fields and widgets | react-jsonschema-form - + @@ -13,7 +13,7 @@ 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"));
- + \ No newline at end of file diff --git a/docs/version-4.2.3/api-reference/form-props/index.html b/docs/version-4.2.3/api-reference/form-props/index.html index 5e5ce59e74..59a634a3bf 100644 --- a/docs/version-4.2.3/api-reference/form-props/index.html +++ b/docs/version-4.2.3/api-reference/form-props/index.html @@ -4,7 +4,7 @@ <Form /> props | react-jsonschema-form - + @@ -12,7 +12,7 @@
Version: v4

<Form /> props

acceptcharset

The value of this prop will be passed to the accept-charset HTML attribute on the form.

action

The value of this prop will be passed to the action HTML attribute on the form.

Note that this just renders the action attribute in the HTML markup. There is no real network request being sent to this action on submit. Instead, react-jsonschema-form catches the submit event with event.preventDefault() and then calls the onSubmit function, where you could send a request programmatically with fetch or similar.

additionalMetaSchemas

This prop allows you to validate the form data against another JSON Schema meta schema, for example, JSON Schema draft-04. See Validation for more information.

ArrayFieldTemplate

React component used to customize how alls arrays are rendered on the form. See Custom Templates for more information.

autoComplete

The value of this prop will be passed to the autocomplete HTML attribute on the form.

autocomplete

Deprecated, same functionality as autoComplete

className

The value of this prop will be passed to the class HTML attribute on the form.

children

You can provide custom buttons to your form via the Form component's children. Otherwise a default submit button will be rendered.

const schema = {
type: "string"
};

render((
<Form schema={schema}>
<div>
<button type="submit">Submit</button>
<button type="button">Cancel</button>
</div>
</Form>
), document.getElementById("app"));

Warning: There needs to be a button or an input with type="submit" to trigger the form submission (and then the form validation).

customFormats

This prop allows you to define custom formats for validation. See Validation for more information.

disabled

It's possible to disable the whole form by setting the disabled prop. The disabled prop is then forwarded down to each field of the form.

const schema = {
type: "string"
};

render((
<Form schema={schema}
disabled />
), document.getElementById("app"));

If you just want to disable some of the fields, see the ui:disabled parameter in uiSchema.

readonly

It's possible to make the whole form read-only by setting the readonly prop. The readonly prop is then forwarded down to each field of the form.

const schema = {
type: "string"
};

render((
<Form schema={schema}
readonly />
), document.getElementById("app"));

If you just want to make some of the fields read-only, see the ui:readonly parameter in uiSchema.

enctype

The value of this prop will be passed to the enctype HTML attribute on the form.

extraErrors

This prop allows passing in custom errors that are augmented with the existing JSON Schema errors on the form; it can be used to implement asynchronous validation. See Validation for more information.

ErrorList

You can pass a React component to this prop to customize how form errors are displayed. See Validation for more information.

fields

Dictionary of registered fields in the form. See Custom Widgets and Fields for more information.

FieldTemplate

React component used to customize each field of the form. See Custom Templates for more information.

formContext

You can provide a formContext object to the Form, which is passed down to all fields and widgets. Useful for implementing context aware fields and widgets. Setting {readonlyAsDisabled: false} on the formContext will make the antd theme treat readOnly fields as disabled.

formData

Often you'll want to prefill a form with existing data; this is done by passing a formData prop object matching the schema.

id

The value of this prop will be passed to the id HTML attribute on the form.

idPrefix

To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids (the default is root).

const schema = {
type: "string"
};

render((
<Form schema={schema}
idPrefix={"rjsf_prefix"}/>
), document.getElementById("app"));

This will render <input id="rjsf_prefix_key"> instead of <input id="root_key">

idSeparator

To avoid using a path separator that is present in field names, it is possible to change the separator used for ids (the default is _).

const schema = {
type: "object",
properties: {
first: {
type: "string"
}
}
};

render((
<Form schema={schema}
idSeparator={"/"}/>
), document.getElementById("app"));

This will render <input id="root/first"> instead of <input id="root_first"> when rendering first.

liveOmit

If omitExtraData and liveOmit are both set to true, then extra form data values that are not in any form field will be removed whenever onChange is called. Set to false by default.

liveValidate

If set to true, the form will perform validation and show any validation errors whenever the form data is changed, rather than just on submit.

method

The value of this prop will be passed to the method HTML attribute on the form.

name

The value of this prop will be passed to the name HTML attribute on the form.

noHtml5Validate

If set to true, turns off HTML5 validation on the form. Set to false on default.

noValidate

If set to true, turns off all validation. Set to false by default.

ObjectFieldTemplate

React component used to customize how all objects are rendered in the form. See Custom Templates for more information.

omitExtraData

If set to true, then extra form data values that are not in any form field will be removed whenever onSubmit is called. Set to false by default.

onBlur

Sometimes you may want to trigger events or modify external state when a field has been touched, so you can pass an onBlur handler, which will receive the id of the input that was blurred and the field value.

onChange

If you plan on being notified every time the form data are updated, you can pass an onChange handler, which will receive the same args as onSubmit any time a value is updated in the form.

onError

To react when submitted form data are invalid, pass an onError handler. It will be passed the list of encountered errors:

const schema = {
type: "string"
};
const onError = (errors) => console.log("I have", errors.length, "errors to fix");

render((
<Form schema={schema}
onError={onError} />
), document.getElementById("app"));

onFocus

Sometimes you may want to trigger events or modify external state when a field has been focused, so you can pass an onFocus handler, which will receive the id of the input that is focused and the field value.

onSubmit

You can pass a function as the onSubmit prop of your Form component to listen to when the form is submitted and its data are valid. It will be passed a result object having a formData attribute, which is the valid form data you're usually after. The original event will also be passed as a second parameter:

const schema = {
type: "string"
};
const onSubmit = ({formData}, e) => console.log("Data submitted: ", formData);

render((
<Form schema={schema}
onSubmit={onSubmit} />
), document.getElementById("app"));

Note: If there are fields in the formData that are not represented in the schema, they will be retained by default. If you would like to remove those extra values on form submission, you may need to set the omitExtraData and/or liveOmit props.

schema

Form schema. We support JSON schema draft-07 by default. See Schema Reference for more information.

showErrorList

When this prop is set to true, a list of errors (or the custom error list defined in the ErrorList) will also show. When set to false, only inline input validation errors will be shown. Set to true by default. See Validation for more information.

tagName

It's possible to change the default form tag name to a different HTML tag, which can be helpful if you are nesting forms. However, native browser form behaviour, such as submitting when the Enter key is pressed, may no longer work.

<Form
tagName="div"
/>

You can also provide a class/function component.

const CustomForm = props => <form {...props} style={...} className={...} />
// ...
<Form
tagName={CustomForm}
/>

target

The value of this prop will be passed to the target HTML attribute on the form.

transformErrors

A function can be passed to this prop in order to make modifications to the default errors resulting from JSON Schema validation. See Validation for more information.

uiSchema

Form uiSchema. See uiSchema Reference for more information.

validate

The validate prop requires a function that specifies custom validation rules for the form. See Validation for more information.

widgets

Dictionary of registered widgets in the form. See Custom Widgets and Fields for more information.

- + \ No newline at end of file diff --git a/docs/version-4.2.3/api-reference/index.html b/docs/version-4.2.3/api-reference/index.html index 441f9125f0..4bd0388125 100644 --- a/docs/version-4.2.3/api-reference/index.html +++ b/docs/version-4.2.3/api-reference/index.html @@ -4,13 +4,13 @@ API Reference | react-jsonschema-form - + - + \ No newline at end of file diff --git a/docs/version-4.2.3/api-reference/themes/chakra-ui/uiSchema/index.html b/docs/version-4.2.3/api-reference/themes/chakra-ui/uiSchema/index.html index 00318be92b..18e21258fe 100644 --- a/docs/version-4.2.3/api-reference/themes/chakra-ui/uiSchema/index.html +++ b/docs/version-4.2.3/api-reference/themes/chakra-ui/uiSchema/index.html @@ -4,14 +4,14 @@ uiSchema Options for Chakra-UI | react-jsonschema-form - +
Version: v4

uiSchema Options for Chakra-UI

When using @rjsf/chakra-ui there are a couple of ways to customize the feel of the form.

Styling

You can use ChakraProvider, where you can customize the components at a theme level.\ And, uiSchema allows for the use of a "chakra" "ui:option" to customize the styling of the form widgets.

{
"ui:options": {
"chakra": {
"p": "1rem",
"color": "blue.200",
"sx": {
"margin": "0 auto"
}
}
}
}

It accepts the theme accessible style props provided by Chakra and Emotion.

Limitations

  • The chakra option is only available for the Chakra-UI theme.
  • The props are given to the parent component in the individual widget. To pass styles to the inner components, use the sx prop.
- + \ No newline at end of file diff --git a/docs/version-4.2.3/api-reference/themes/semantic-ui/uiSchema/index.html b/docs/version-4.2.3/api-reference/themes/semantic-ui/uiSchema/index.html index 9b0c1db8ca..a711003e28 100644 --- a/docs/version-4.2.3/api-reference/themes/semantic-ui/uiSchema/index.html +++ b/docs/version-4.2.3/api-reference/themes/semantic-ui/uiSchema/index.html @@ -4,13 +4,13 @@ uiSchema Options for Semantic-UI | react-jsonschema-form - +
Version: v4

uiSchema Options for Semantic-UI

There are various options to pass to semantic theme fields.

Note that every semantic property within uiSchema can be rendered in one of two ways: {"ui:options": {semantic:{[property]: [value]}}}

In other words, the following uiSchema is equivalent:

Note: All fields have the following settings below as their default

fluid: Take on the size of its container.
inverted: Format to appear on dark backgrounds.
{
"ui:options": {
"semantic" : {
"fluid": true,
"inverted": false,
"errorOptions": {
"size": "small",
"pointing": "above",
}
}
}
}

Semantic Widget Optional Properties

errorOptions

The uiSchema semantic object accepts an errorOptions property for each field of the schema:

size: determines the size of the error message dialog
pointing: determines the direction of the arrow on the error message dialog

Below are the current defaults

const uiSchema = {
"ui:options": {
"semantic" : {
"errorOptions": {
"size": "small",
"pointing": "above",
}
}
}
};

semantic options uiSchema for array items

To specify a uiSchema that applies to array items, specify the semantic uiSchema value within the ui:options property:

wrapItem: wrap each array item in a Segment
horizontalButtons: horizontal buttons instead of the default vertical
const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
"ui:options": {
"semantic": {
"wrapItem": true,
"horizontalButtons": true
}
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

formContext

The formContext semantic object accepts wrapContent ,wrapLabel properties.

wrapContent: wrap all inputs  field content in a div, for custom styling
wrapLabel: wrap all labels in a div, for custom styling via CSS
<Form
formContext={{
"semantic" : {
"wrapLabel": true,
"wrapContent": true
}
// other props...
}}
/>
- + \ No newline at end of file diff --git a/docs/version-4.2.3/api-reference/uiSchema/index.html b/docs/version-4.2.3/api-reference/uiSchema/index.html index 13058f5a7e..0d60aadc71 100644 --- a/docs/version-4.2.3/api-reference/uiSchema/index.html +++ b/docs/version-4.2.3/api-reference/uiSchema/index.html @@ -4,14 +4,14 @@ uiSchema | react-jsonschema-form - +
Version: v4

uiSchema

JSON Schema is limited for describing how a given data type should be rendered as a form input component. That's why this library introduces the concept of uiSchema.

A UI schema is basically an object literal providing information on how the form should be rendered, while the JSON schema tells what.

The uiSchema object follows the tree structure of the form field hierarchy, and defines how each property should be rendered.

Note that every property within uiSchema can be rendered in one of two ways: {"ui:options": {[property]: [value]}}, or {"ui:[property]": value}.

In other words, the following uiSchemas are equivalent:

{
"ui:title": "Title",
"ui:description": "Description",
"ui:submitButtonOptions": {
"props": {
"disabled": false,
"className": "btn btn-info",
},
"norender": false,
"submitText": "Submit"
},
}
{
"ui:options": {
"title": "Title",
"description": "Description",
"submitButtonOptions": {
"props": {
"disabled": false,
"className": "btn btn-info",
},
"norender": false,
"submitText": "Submit"
},
}
}

classNames

The uiSchema object accepts a classNames property for each field of the schema:

const uiSchema = {
title: {
classNames: "task-title foo-bar"
}
};

Will result in:

<div class="field field-string task-title foo-bar" >
<label>
<span>Title*</span>
<input value="My task" required="" type="text">
</label>
</div>

autofocus

If you want to automatically focus on a text input or textarea input, set the ui:autofocus uiSchema directive to true.

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "textarea",
"ui:autofocus": true
}

description

Sometimes it's convenient to change the description of a field. This is the purpose of the ui:description uiSchema directive:

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "password",
"ui:description": "The best password"
};

disabled

The ui:disabled uiSchema directive will disable all child widgets from a given field.

Note: If you're wondering about the difference between a disabled field and a readonly one: Marking a field as read-only will render it greyed out, but its text value will be selectable. Disabling it will prevent its value to be selected at all.

enumDisabled

To disable an option, use the enumDisabled property in uiSchema.

const schema = {
type: "string",
enum: ["one", "two", "three"],
};

const uiSchema={
"ui:enumDisabled": ['two'],
}

help

Sometimes it's convenient to add text next to a field to guide the end user filling it. This is the purpose of the ui:help uiSchema directive:

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "password",
"ui:help": "Hint: Make it strong!"
};

Help texts work for any kind of field at any level, and will always be rendered immediately below the field component widget(s) (after contextualized errors, if any).

hideError

The ui:hideError uiSchema directive will, if set to true, hide the default error display for the given field AND all of its child fields in the hierarchy.

If you need to enable the default error display of a child in the hierarchy after setting hideError: true on the parent field, simply set hideError: false on the child.

This is useful when you have a custom field or widget that utilizes either the rawErrors or the errorSchema to manipulate and/or show the error(s) for the field/widget itself.

inputType

To change the input type (for example, tel or email) you can specify the inputType in the ui:options uiSchema directive.

const schema = {type: "string"};
const uiSchema = {
"ui:options": {
inputType: 'tel'
}
};

label

Field labels are rendered by default. Labels may be omitted by setting the label option to false in the ui:options uiSchema directive.

const schema = {type: "string"};
const uiSchema = {
"ui:options": {
label: false
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

order

This property allows you to reorder the properties that are shown for a particular object. See Objects for more information.

placeholder

You can add placeholder text to an input by using the ui:placeholder uiSchema directive:

const schema = {type: "string", format: "uri"};
const uiSchema = {
"ui:placeholder": "http://"
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

Fields using enum can also use ui:placeholder. The value will be used as the text for the empty option in the select widget.

const schema = {type: "string", enum: ["First", "Second"]};
const uiSchema = {
"ui:placeholder": "Choose an option"
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

readonly

The ui:readonly uiSchema directive will mark all child widgets from a given field as read-only. This is equivalent to setting the readOnly property in the schema.

Note: If you're wondering about the difference between a disabled field and a readonly one: Marking a field as read-only will render it greyed out, but its text value will be selectable. Disabling it will prevent its value to be selected at all.

rootFieldId

By default, this library will generate ids unique to the form for all rendered widgets. If you plan on using multiple instances of the Form component in a same page, it's wise to declare a root prefix for these, using the ui:rootFieldId uiSchema directive:

const uiSchema = {
"ui:rootFieldId": "myform"
};

This will make all widgets have an id prefixed with myform.

rows

You can set the initial height of a textarea widget by specifying rows option.

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "textarea",
"ui:options": {
rows: 15
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

title

Sometimes it's convenient to change a field's title. This is the purpose of the ui:title uiSchema directive:

const schema = {type: "string"};
const uiSchema = {
"ui:widget": "password",
"ui:title": "Your password"
};

submitButtonOptions

Sometimes it's convenient to change the behavior of the submit button for the form. This is the purpose of the ui:submitButtonOptions uiSchema directive:

You can pass any other prop to the submit button if you want, by default, this library will set the following options / props mentioned below for all submit buttons:

norender option

You can set this property to true to remove the submit button completely from the form. Nice option, if the form is just for viewing purposes.

submitText option

You can use this option to change the text of the submit button. Set to "Submit" by default.

props section

You can pass any other prop to the submit button if you want, via this section.

disabled prop

You can use this option to disable the submit button.

className prop

You can use this option to specify a class name for the submit button.

const uiSchema = {
"ui:submitButtonOptions": {
"props": {
"disabled": false,
"className": "btn btn-info",
},
"norender": false,
"submitText": "Submit"
}
};

Theme Options

Semantic UI Chakra UI

- + \ No newline at end of file diff --git a/docs/version-4.2.3/quickstart/index.html b/docs/version-4.2.3/quickstart/index.html index e091aa69de..fb9537a9d5 100644 --- a/docs/version-4.2.3/quickstart/index.html +++ b/docs/version-4.2.3/quickstart/index.html @@ -4,7 +4,7 @@ Quickstart | react-jsonschema-form - + @@ -14,7 +14,7 @@ uiSchema should be {key: value}, where key is the property key and value is an object with the uiSchema configuration for that particular property. For example:

const schema = {
title: "Test form",
type: "object",
properties: {
name: {
type: "string"
},
age: {
type: "number"
}
}
};

const uiSchema = {
name: {
classNames: "custom-class-name"
},
age: {
classNames: "custom-class-age"
}
}

render((
<Form schema={schema} />
), document.getElementById("app"));

Form initialization

Often you'll want to prefill a form with existing data; this is done by passing a formData prop object matching the schema:

const schema = {
type: "object",
properties: {
title: {
type: "string"
},
done: {
type: "boolean"
}
}
};

const formData = {
title: "First task",
done: true
};

render((
<Form schema={schema}
formData={formData} />
), document.getElementById("app"));

Note: If your form has a single field, pass a single value to formData. ex: formData="Charlie"

WARNING: If you have situations where your parent component can re-render, make sure you listen to the onChange event and update the data you pass to the formData attribute.

Form event handlers

You can use event handlers such as onChange, onError, onSubmit, onFocus, and onBlur on the <Form /> component; see the Form Props Reference for more details.

Controlled component

By default, <Form /> is an uncontrolled component. To make it a controlled component, use the onChange and formData props as in the below example:

const App = () => {
const [formData, setFormData] = React.useState(null);
return (<Form
schema={{type: "string"}}
formData={formData}
onChange={e => setFormData(e.formData)}
/>);
};

render((
<App />
), document.getElementById("app"));
- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/arrays/index.html b/docs/version-4.2.3/usage/arrays/index.html index 7de83cd7fa..b0a1babb4d 100644 --- a/docs/version-4.2.3/usage/arrays/index.html +++ b/docs/version-4.2.3/usage/arrays/index.html @@ -4,13 +4,13 @@ Arrays | react-jsonschema-form - +
Version: v4

Arrays

Arrays are defined with a type equal to array, and array items' schemas are specified in the items keyword.

Arrays of a single field

Arrays of a single field type can be specified as follows:

const schema = {
type: "array",
items: {
type: "string"
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Arrays of objects

Arrays of objects can be specified as follows:

const schema = {
type: "array",
items: {
type: "object",
properties: {
name: {
type: "string"
}
}
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

uiSchema for array items

To specify a uiSchema that applies to array items, specify the uiSchema value within the items property:

const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
items: {
"ui:widget": "textarea"
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

The additionalItems keyword

The additionalItems keyword allows the user to add additional items of a given schema. For example:

const schema = {
type: "array",
items: {
type: "string"
},
additionalItems: {
type: "boolean"
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Array item options

orderable option

Array items are orderable by default, and react-jsonschema-form renders move up/down buttons alongside them. The uiSchema orderable options allows you to disable ordering:

const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
"ui:options": {
orderable: false
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

addable option

If either items or additionalItems contains a schema object, an add button for new items is shown by default. You can turn this off with the addable option in uiSchema:

const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
"ui:options": {
addable: false
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

removable option

A remove button is shown by default for an item if items contains a schema object, or the item is an additionalItems instance. You can turn this off with the removable option in uiSchema:

const schema = {
type: "array",
items: {
type: "string"
}
};

const uiSchema = {
"ui:options": {
removable: false
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

Multiple-choice list

The default behavior for array fields is a list of text inputs with add/remove buttons. There are two alternative widgets for picking multiple elements from a list of choices. Typically this applies when a schema has an enum list for the items property of an array field, and the uniqueItems property set to true.

Example:

const schema = {
type: "array",
title: "A multiple-choice list",
items: {
type: "string",
enum: ["foo", "bar", "fuzz", "qux"],
},
uniqueItems: true
};

render((
<Form schema={schema} />
), document.getElementById("app"));

By default, this will render a multiple select box. If you prefer a list of checkboxes, just set the uiSchema ui:widget directive to checkboxes for that field:

const schema = {
type: "array",
title: "A multiple-choice list",
items: {
type: "string",
enum: ["foo", "bar", "fuzz", "qux"],
},
uniqueItems: true
};

const uiSchema = {
"ui:widget": "checkboxes"
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

Custom widgets

In addition to ArrayFieldTemplate you use your own widget by providing it to the uiSchema with the property of ui:widget.

Example:

const CustomSelectComponent = props => {
return (
<select>
{props.value.map((item, index) => (
<option key={index} id="custom-select">
{item}
</option>
))}
</select>
);
};

const schema = {
type: "array",
title: "A multiple-choice list",
items: {
type: "string",
},
};

const uiSchema = {
"ui:widget": "CustomSelect"
};

const widgets = {
CustomSelect: CustomSelectComponent,
},

render((<Form schema={schema} uiSchema={uiSchema} widgets={widgets} />), document.getElementById("app"));

Specifying the minimum or maximum number of items

Note that when an array property is marked as required, an empty array is considered valid. If the array needs to be populated, you can specify the minimum number of items using the minItems property.

Example:

const schema = {
type: "array",
minItems: 2,
title: "A multiple-choice list",
items: {
type: "string",
enum: ["foo", "bar", "fuzz", "qux"],
},
uniqueItems: true
};

render((
<Form schema={schema} />
), document.getElementById("app"));

You can also specify the maximum number of items in an array using the maxItems property.

Inline checkboxes

By default, checkboxes are stacked. If you prefer them inline, set the inline property to true:

const schema = {
type: "array",
minItems: 2,
title: "A multiple-choice list",
items: {
type: "string",
enum: ["foo", "bar", "fuzz", "qux"],
},
uniqueItems: true
};

const uiSchema = {
"ui:widget": "checkboxes",
"ui:options": {
inline: true
}
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));
- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/definitions/index.html b/docs/version-4.2.3/usage/definitions/index.html index 77d2fc9b91..f56902f574 100644 --- a/docs/version-4.2.3/usage/definitions/index.html +++ b/docs/version-4.2.3/usage/definitions/index.html @@ -4,13 +4,13 @@ Schema definitions and references | react-jsonschema-form - +
Version: v4

Schema definitions and references

This library partially supports inline schema definition dereferencing, which is Barbarian for avoiding to copy and paste commonly used field schemas:

const schema = {
"definitions": {
"address": {
"type": "object",
"properties": {
"street_address": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" }
},
"required": ["street_address", "city", "state"]
}
},
"type": "object",
"properties": {
"billing_address": { "$ref": "#/definitions/address" },
"shipping_address": { "$ref": "#/definitions/address" }
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Note that this library only supports local definition referencing. The value in the $ref keyword should be a JSON Pointer in URI fragment identifier format.

- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/dependencies/index.html b/docs/version-4.2.3/usage/dependencies/index.html index b21e35b8a9..c074bcda91 100644 --- a/docs/version-4.2.3/usage/dependencies/index.html +++ b/docs/version-4.2.3/usage/dependencies/index.html @@ -4,14 +4,14 @@ Dependencies | react-jsonschema-form - +
Version: v4

Dependencies

react-jsonschema-form supports the dependencies keyword from an earlier draft of JSON Schema (note that this is not part of the latest JSON Schema spec, though). Dependencies can be used to create dynamic schemas that change fields based on what data is entered.

Property dependencies

This library supports conditionally making fields required based on the presence of other fields.

Unidirectional

In the following example the billing_address field will be required if credit_card is defined.

const schema = {
"type": "object",

"properties": {
"name": { "type": "string" },
"credit_card": { "type": "number" },
"billing_address": { "type": "string" }
},

"required": ["name"],

"dependencies": {
"credit_card": ["billing_address"]
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Bidirectional

In the following example the billing_address field will be required if credit_card is defined and the credit_card field will be required if billing_address is defined, making them both required if either is defined.

const schema = {
"type": "object",

"properties": {
"name": { "type": "string" },
"credit_card": { "type": "number" },
"billing_address": { "type": "string" }
},

"required": ["name"],

"dependencies": {
"credit_card": ["billing_address"],
"billing_address": ["credit_card"]
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

(Sample schemas courtesy of the Space Telescope Science Institute)

Schema dependencies

This library also supports modifying portions of a schema based on form data.

Conditional

const schema = {
"type": "object",

"properties": {
"name": { "type": "string" },
"credit_card": { "type": "number" }
},

"required": ["name"],

"dependencies": {
"credit_card": {
"properties": {
"billing_address": { "type": "string" }
},
"required": ["billing_address"]
}
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

In this example the billing_address field will be displayed in the form if credit_card is defined.

(Sample schemas courtesy of the Space Telescope Science Institute)

Dynamic

The JSON Schema standard says that the dependency is triggered if the property is present. However, sometimes it's useful to have more sophisticated rules guiding the application of the dependency. For example, maybe you have three possible values for a field, and each one should lead to adding a different question. For this, we support a very restricted use of the oneOf keyword.

const schema = {
"title": "Person",
"type": "object",
"properties": {
"Do you have any pets?": {
"type": "string",
"enum": [
"No",
"Yes: One",
"Yes: More than one"
],
"default": "No"
}
},
"required": [
"Do you have any pets?"
],
"dependencies": {
"Do you have any pets?": {
"oneOf": [
{
"properties": {
"Do you have any pets?": {
"enum": [
"No"
]
}
}
},
{
"properties": {
"Do you have any pets?": {
"enum": [
"Yes: One"
]
},
"How old is your pet?": {
"type": "number"
}
},
"required": [
"How old is your pet?"
]
},
{
"properties": {
"Do you have any pets?": {
"enum": [
"Yes: More than one"
]
},
"Do you want to get rid of any?": {
"type": "boolean"
}
},
"required": [
"Do you want to get rid of any?"
]
}
]
}
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

In this example the user is prompted with different follow-up questions dynamically based on their answer to the first question.

In these examples, the "Do you have any pets?" question is validated against the corresponding property in each schema in the oneOf array. If exactly one matches, the rest of that schema is merged with the existing schema.

- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/index.html b/docs/version-4.2.3/usage/index.html index 8207ab335d..3c530f777a 100644 --- a/docs/version-4.2.3/usage/index.html +++ b/docs/version-4.2.3/usage/index.html @@ -4,13 +4,13 @@ Usage and Customization | react-jsonschema-form - +
- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/objects/index.html b/docs/version-4.2.3/usage/objects/index.html index 09675fdb22..4f9ced44bd 100644 --- a/docs/version-4.2.3/usage/objects/index.html +++ b/docs/version-4.2.3/usage/objects/index.html @@ -4,13 +4,13 @@ Objects | react-jsonschema-form - +
Version: v4

Objects

Object properties

Objects are defined with a type equal to object and properties specified in the properties keyword.

const schema = {
"title": "My title",
"description": "My description",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Required properties

You can specify which properties are required using the required attribute:

const schema = {
"title": "My title",
"description": "My description",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "number"
}
},
"required": ["name"]
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Specifying property order

Since the order of object properties in Javascript and JSON is not guaranteed, the uiSchema object spec allows you to define the order in which properties are rendered using the ui:order property:

const schema = {
type: "object",
properties: {
foo: {type: "string"},
bar: {type: "string"}
}
};

const uiSchema = {
"ui:order": ["bar", "foo"]
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

If a guaranteed fixed order is only important for some fields, you can insert a wildcard "*" item in your ui:order definition. All fields that are not referenced explicitly anywhere in the list will be rendered at that point:

const uiSchema = {
"ui:order": ["bar", "*"]
};

Additional properties

The additionalProperties keyword allows the user to add properties with arbitrary key names. Set this keyword equal to a schema object:

const schema = {
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"additionalProperties": {
"type": "number",
"enum": [1, 2, 3]
}
};

render((
<Form schema={schema} />
), document.getElementById("app"));

In this way, an add button for new properties is shown by default.

You can also define uiSchema options for additionalProperties by setting the additionalProperties attribute in the uiSchema.

expandable option

You can turn support for additionalProperties off with the expandable option in uiSchema:

const uiSchema = {
"ui:options": {
expandable: false
}
};
- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/oneof/index.html b/docs/version-4.2.3/usage/oneof/index.html index 42b53eb332..34c68ee186 100644 --- a/docs/version-4.2.3/usage/oneof/index.html +++ b/docs/version-4.2.3/usage/oneof/index.html @@ -4,13 +4,13 @@ oneOf, anyOf, and allOf | react-jsonschema-form - +
Version: v4

oneOf, anyOf, and allOf

react-jsonschema-form supports custom widgets for oneOf, anyOf, and allOf.

  • A schema with oneOf is valid if exactly one of the subschemas is valid.
  • A schema with anyOf is valid if at least one of the subschemas is valid.
  • A schema with allOf is valid if all of the subschemas are valid.

oneOf

const schema = {
type: "object",
oneOf: [
{
properties: {
lorem: {
type: "string",
},
},
required: ["lorem"],
},
{
properties: {
ipsum: {
type: "string",
},
},
required: ["ipsum"],
},
],
};

render((
<Form schema={schema} />
), document.getElementById("app"));

anyOf

const schema = {
type: "object",
anyOf: [
{
properties: {
lorem: {
type: "string",
},
},
required: ["lorem"],
},
{
properties: {
lorem: {
type: "string",
},
ipsum: {
type: "string",
},
}
},
],
};

render((
<Form schema={schema} />
), document.getElementById("app"));

allOf

When allOf is specified in a schema, react-jsonschema-form uses the json-schema-merge-allof library to merge the specified subschemas to create a combined subschema that is valid. For example, the below schema evaluates to a combined subschema of {type: "boolean"}:

const schema = {
title: "Field",
allOf: [
{
type: ["string", "boolean"]
},
{
type: "boolean"
},
],
};

render((
<Form schema={schema} />
), document.getElementById("app"));
- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/single/index.html b/docs/version-4.2.3/usage/single/index.html index 31b7a9aa98..16bfbce7aa 100644 --- a/docs/version-4.2.3/usage/single/index.html +++ b/docs/version-4.2.3/usage/single/index.html @@ -4,13 +4,13 @@ Single fields | react-jsonschema-form - +
Version: v4

Single fields

The simplest example of a JSON Schema contains only a single field. The field type is determined by the type parameter.

Field types

The base field types in JSON Schema include:

  • string
  • number
  • integer
  • boolean
  • null

Here is an example of a string field:

const schema = {
type: "string"
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Titles and descriptions

Fields can have titles and descriptions specified by the title keyword in the schema and description keyword in the schema, respectively. These two can also be overriden by the ui:title and ui:description keywords in the uiSchema.

const schema = {
title: "My form",
description: "My description",
type: "string"
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Enumerated values

All base schema types support the enum attribute, which restricts the user to select among a list of options. For example:

const schema = {
type: "string",
enum: ["one", "two", "three"]
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Custom labels for enum fields

This library supports a custom enumNames property for enum fields, which, however is not JSON-Schema compliant (see below for a compliant approach). The enumNames property allows defining custom labels for each option of an enum:

const schema = {
type: "number",
enum: [1, 2, 3],
enumNames: ["one", "two", "three"]
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Alternative JSON-Schema compliant approach

JSON Schema has an alternative approach to enumerations using anyOf; react-jsonschema-form supports it as well.

const schema = {
"type": "number",
"anyOf": [
{
"type": "number",
"title": "one",
"enum": [
1
]
},
{
"type": "number",
"title": "two",
"enum": [
2
]
},
{
"type": "number",
"title": "three",
"enum": [
3
]
}
]
};

render((
<Form schema={schema} />
), document.getElementById("app"));

Disabled attribute for enum fields

To disable an option, use the ui:enumDisabled property in the uiSchema.

const schema = {
type: "boolean",
enum: [true, false]
};

const uiSchema={
"ui:enumDisabled": [true],
};

render((
<Form schema={schema} uiSchema={uiSchema} />
), document.getElementById("app"));

Nullable types

JSON Schema supports specifying multiple types in an array; however, react-jsonschema-form only supports a restricted subset of this -- nullable types, in which an element is either a given type or equal to null.

const schema = {
type: ["string", "null"]
};

render((
<Form schema={schema} />
), document.getElementById("app"));
- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/themes/index.html b/docs/version-4.2.3/usage/themes/index.html index b2acc1a874..14e8a9c22e 100644 --- a/docs/version-4.2.3/usage/themes/index.html +++ b/docs/version-4.2.3/usage/themes/index.html @@ -4,7 +4,7 @@ Themes | react-jsonschema-form - + @@ -12,7 +12,7 @@
Version: v4

Themes

By default, this library renders form fields and widgets leveraging the Bootstrap semantics, meaning that you must load the Bootstrap stylesheet on the page to view the form properly. You can use another theme by importing one of the packages listed below.

Supported themes

Theme NameStatusPackage Name / Link
Bootstrap 3 (default)Published@rjsf/core
Bootstrap 4Published@rjsf/bootstrap-4
material-ui 4 & 5Published@rjsf/material-ui
fluent-uiPublished@rjsf/fluent-ui
antdPublished@rjsf/antd
Semantic UIPublished@rjsf/semantic-ui
Chakra UIPublished@rjsf/chakra-ui

Using themes

To use a theme from a package, just import the <Form /> component from that package. For example, to use the material ui form, first install both @rjsf/core and @rjsf/material-ui. Then you can import the form by doing:

import Form from "@rjsf/material-ui";

If you would like to contribute a theme with a new UI framework, please develop the theme using the withTheme component described in Theme Customization and make a PR!

You can also use the uiSchema to add custom CSS class names to your form.

Customizing with other frameworks

The default theme is bootstrap 3. In order to use another theme, you must first install @rjsf/core.

For example, to use the standard bootstrap 3 form, you can run:

import Form from "@rjsf/core";

To use the material-ui form, you should first install both @rjsf/core and @rjsf/material-ui. Then, you can run:

import Form from "@rjsf/material-ui";

For more information on how to create a custom theme, see documentation on the withTheme component.

- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/validation/index.html b/docs/version-4.2.3/usage/validation/index.html index 1a2759c42d..bcfb6c66f8 100644 --- a/docs/version-4.2.3/usage/validation/index.html +++ b/docs/version-4.2.3/usage/validation/index.html @@ -4,14 +4,14 @@ Validation | react-jsonschema-form - +
Version: v4

Validation

When the form is submitted, the form data is validated to conform to the given JSON schema; this library uses the ajv validator by default.

Live validation

By default, form data are only validated when the form is submitted or when a new formData prop is passed to the Form component.

You can enable live form data validation by passing a liveValidate prop to the Form component, and set it to true. Then, every time a value changes within the form data tree (e.g. the user entering a character in a field), a validation operation is performed, and the validation results are reflected into the form state.

Be warned that this is an expensive strategy, with possibly strong impact on performances.

const schema = {
type: ["string"],
const: "test"
};

const formData = "a";

render((
<Form schema={schema} formData={formData} liveValidate />
), document.getElementById("app"));

HTML5 Validation

By default, the form uses HTML5 validation. This may cause unintuitive results because the HTML5 validation errors (such as when a field is required) may be displayed before the form is submitted, and thus these errors will display differently from the react-jsonschema-form validation errors. You can turn off HTML validation by setting the noHtml5Validate to true.

const schema = {
type: "object",
properties: {
name: {
type: "string",
required: true
}
}
};

render((
<Form schema={schema} noHtml5Validate />
), document.getElementById("app"));

Custom validation rules

Form data is always validated against the JSON schema.

But it is possible to define your own custom validation rules. This is especially useful when the validation depends on several interdependent fields.

function validate(formData, errors) {
if (formData.pass1 !== formData.pass2) {
errors.pass2.addError("Passwords don't match");
}
return errors;
}

const schema = {
type: "object",
properties: {
pass1: {type: "string", minLength: 3},
pass2: {type: "string", minLength: 3},
}
};

render((
<Form schema={schema}
validate={validate} />
), document.getElementById("app"));

Notes:

  • The validate() function must always return the errors object received as second argument.
  • The validate() function is called after the JSON schema validation.

Custom error messages

Validation error messages are provided by the JSON Schema validation by default. If you need to change these messages or make any other modifications to the errors from the JSON Schema validation, you can define a transform function that receives the list of JSON Schema errors and returns a new list.

function transformErrors(errors) {
return errors.map(error => {
if (error.name === "pattern") {
error.message = "Only digits are allowed"
}
return error;
});
}

const schema = {
type: "object",
properties: {
onlyNumbersString: {type: "string", pattern: "^\\d*$"},
}
};

render((
<Form schema={schema}
transformErrors={transformErrors} />
), document.getElementById("app"));

Notes:

  • The transformErrors() function must return the list of errors. Modifying the list in place without returning it will result in an error.

Each element in the errors list passed to transformErrors has the following properties:

  • name: name of the error, for example, "required" or "minLength"
  • message: message, for example, "is a required property" or "should NOT be shorter than 3 characters"
  • params: an object with the error params returned by ajv (see doc for more info).
  • property: a string in Javascript property accessor notation to the data path of the field with the error. For example, .name or ['first-name'].
  • stack: full error name, for example ".name is a required property".
  • schemaPath: JSON pointer to the schema of the keyword that failed validation. For example, #/fields/firstName/required. (Note: this may sometimes be wrong due to a bug in ajv).

Error List Display

To take control over how the form errors are displayed, you can define an error list template for your form. This list is the form global error list that appears at the top of your forms.

An error list template is basically a React stateless component being passed errors as props so you can render them as you like:

function ErrorListTemplate(props) {
const { errors } = props;
return (
<div>
<h2>Custom error list</h2>
<ul>
{errors.map(error => (
<li key={error.stack}>
{error.stack}
</li>
))}
</ul>
</div>
);
}

const schema = {
type: "string",
const: "test"
};

render((
<Form schema={schema}
showErrorList={true}
formData={""}
liveValidate
ErrorList={ErrorListTemplate} />
), document.getElementById("app"));

Note: Your custom ErrorList template will only render when showErrorList is true.

The following props are passed to ErrorList

  • errors: An array of the errors.
  • errorSchema: The errorSchema constructed by Form.
  • schema: The schema that was passed to Form.
  • uiSchema: The uiSchema that was passed to Form.
  • formContext: The formContext object that you passed to Form.

The case of empty strings

When a text input is empty, the field in form data is set to undefined. String fields that use enum and a select widget will have an empty option at the top of the options list that when selected will result in the field being undefined.

One consequence of this is that if you have an empty string in your enum array, selecting that option in the select input will cause the field to be set to undefined, not an empty string.

If you want to have the field set to a default value when empty you can provide a ui:emptyValue field in the uiSchema object.

Custom meta schema validation

To have your schemas validated against any other meta schema than draft-07 (the current version of JSON Schema), make sure your schema has a $schema attribute that enables the validator to use the correct meta schema. For example:

{
"$schema": "http://json-schema.org/draft-04/schema#",
...
}

Note that react-jsonschema-form only supports the latest version of JSON Schema, draft-07, by default. To support additional meta schemas pass them through the additionalMetaSchemas prop to the Form component.

additionalMetaSchemas

The additionalMetaSchemas prop allows you to validate the form data against one (or more than one) JSON Schema meta schema, for example, JSON Schema draft-04. You can import a meta schema as follows:

const metaSchemaDraft04 = require("ajv/lib/refs/json-schema-draft-04.json");

In this example schema passed as props to Form component can be validated against draft-07 (default) and by draft-04 (added), depending on the value of $schema attribute.

const schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
type: "string"
};

return (<Form schema={schema}
additionalMetaSchemas={[metaSchemaDraft04]} />);

customFormats

Pre-defined semantic formats are limited. react-jsonschema-form adds two formats, color and data-url, to support certain alternative widgets. You can add formats of your own through the customFormats prop to your Form component:

const schema = {
type: 'string',
format: 'phone-us'
};

const customFormats = {
'phone-us': /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/
};

render((
<Form schema={schema}
customFormats={customFormats}/>
), document.getElementById("app"));

Format values can be anything AJV's addFormat method accepts.

Async validation

Handling async errors is an important part of many applications. Support for this is added in the form of the extraErrors prop.

For example, a request could be made to some backend when the user submits the form. If that request fails, the errors returned by the backend should be formatted like in the following example.

const schema = {
type: "object",
properties: {
foo: {
type: "string",
},
candy: {
type: "object",
properties: {
bar: {
type: "string",
}
}
}
}
};

const extraErrors = {
foo: {
__errors: ["some error that got added as a prop"],
},
candy: {
bar: {
__errors: ["some error that got added as a prop"],
}
}
};

render((
<Form schema={schema}
extraErrors={extraErrors} />
), document.getElementById("app"));

An important note is that these errors are "display only" and will not block the user from submitting the form again.

- + \ No newline at end of file diff --git a/docs/version-4.2.3/usage/widgets/index.html b/docs/version-4.2.3/usage/widgets/index.html index f3389e3e0a..1c213d8cec 100644 --- a/docs/version-4.2.3/usage/widgets/index.html +++ b/docs/version-4.2.3/usage/widgets/index.html @@ -4,13 +4,13 @@ Widgets | react-jsonschema-form - +
Version: v4

Widgets

The uiSchema ui:widget property tells the form which UI widget should be used to render a field.

Example:

const schema = {
type: "object",
properties: {
done: {
type: "boolean"
}
}
};

const uiSchema =  {
done: {
"ui:widget": "radio" // could also be "select"
}
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

Here's a list of supported alternative widgets for different JSON Schema data types:

For boolean fields

  • radio: a radio button group with true and false as selectable values;
  • select: a select box with true and false as options;
  • by default, a checkbox is used

Note: To set the labels for a boolean field, instead of using true and false you can set enumNames in your schema. Note that enumNames belongs in your schema, not the uiSchema, and the order is always [true, false].

For string fields

  • textarea: a textarea element is used;
  • password: an input[type=password] element is used;
  • color: an input[type=color] element is used;
  • by default, a regular input[type=text] element is used.

String formats

The built-in string field also supports the JSON Schema format property, and will render an appropriate widget by default for the following string formats:

  • email: An input[type=email] element is used;
  • uri: An input[type=url] element is used;
  • data-url: By default, an input[type=file] element is used; in case the string is part of an array, multiple files will be handled automatically (see File widgets).
  • date: By default, an input[type=date] element is used;
  • date-time: By default, an input[type=datetime-local] element is used.

Please note that, even though they are standardized, datetime-local and date input elements are not yet supported by Firefox and IE. If you plan on targeting these platforms, two alternative widgets are available:

  • alt-datetime: Six select elements are used to select the year, the month, the day, the hour, the minute and the second;
  • alt-date: Three select elements are used to select the year, month and the day.

Firefox 57 - 66: Firefox partially supporting date and time input types, but not datetime-local, month or week

You can customize the list of years displayed in the year dropdown by providing a yearsRange property to ui:options in your uiSchema. Its also possible to remove the Now and Clear buttons with the hideNowButton and hideClearButton options.

const schema = {
type: "string"
};

const uiSchema = {
"ui:widget": "alt-datetime",
"ui:options": {
yearsRange: [1980, 2030],
hideNowButton: true,
hideClearButton: true,
}
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

For number and integer fields

  • updown: an input[type=number] updown selector;
  • range: an input[type=range] slider;
  • radio: a radio button group with enum values. This can only be used when enum values are specified for this input.
  • By default, a regular input[type=text] element is used.

Note: If JSON Schema's minimum, maximum and multipleOf values are defined, the min, max and step input attributes values will take those values.

Hidden widgets

It's possible to use a hidden widget for a field by setting its ui:widget uiSchema directive to hidden:

const schema = {
type: "object",
properties: {
foo: {type: "boolean"}
}
};

const uiSchema = {
foo: {"ui:widget": "hidden"}
};

render((
<Form schema={schema}
uiSchema={uiSchema} />
), document.getElementById("app"));

Notes:

  • Hiding widgets is only supported for boolean, string, number and integer schema types;
  • A hidden widget takes its value from the formData prop.

File widgets

This library supports a limited form of input[type=file] widgets, in the sense that it will propagate file contents to form data state as data-urls.

There are two ways to use file widgets.

  1. By declaring a string json schema type along a data-url format:
const schema = {
type: "string",
format: "data-url",
};

render((
<Form schema={schema} />
), document.getElementById("app"));
  1. By specifying a ui:widget field uiSchema directive as file:
const schema = {
type: "string",
};

const uiSchema = {
"ui:widget": "file",
};

Multiple files

Multiple files selectors are supported by defining an array of strings having data-url as a format:

const schema = {
type: "array",
items: {
type: "string",
format: "data-url",
}
};

Note that storing large dataURIs into form state might slow rendering.

File widget input ref

The included FileWidget exposes a reference to the <input type="file" /> element node as an inputRef component property.

This allows you to programmatically trigger the browser's file selector, which can be used in a custom file widget.

accept option

You can use the accept attribute to specify a filter for what file types the user can upload:

const schema = {
type: "string",
format: "data-url"
};

const uiSchema = {
"ui:options": { accept: ".pdf" }
};
- + \ No newline at end of file