react-jsonschema-form Documentation

A React component for building Web forms from JSON Schema.

15,922 stars TypeScript TypeScript 1 file · ~125,743 tokens #data-validation#forms#json#json-schema#react#ui#web
RAW Doc

Technical Documentation: rjsf-team/react-jsonschema-form

ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference

Overview (`README.md`)

Build Status
Contributors
Apache 2.0 License

Supported Themes

API Libraries

Documentation

Read our documentation, powered by Docusaurus.

Live Playground

A live playground is hosted on GitHub Pages.

Contributing

Read our contributors' guide to get started.

Credits

Testing powered by BrowserStack


Overview (`docs/README.md`)

docs (DEPRECATED)

The react-jsonschema-form documentation has been moved here


Overview (`packages/antd/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Ant Design theme, fields and widgets for react-jsonschema-form.

Built With

Getting Started

Prerequisites

  • antd >= 5
  • @ant-design/icons >= 5
  • dayjs >= 1.8.0
  • @rjsf/core >= 6
  • @rjsf/utils >= 6
  • @rjsf/validator-ajv8 >= 6
sh
npm install antd @ant-design/icons dayjs @rjsf/core @rjsf/utils @rjsf/validator-ajv8

Installation

sh
npm install @rjsf/antd

Usage

javascript
import Form from '@rjsf/antd';

or

javascript
import { withTheme } from '@rjsf/core';
import { Theme as AntDTheme } from '@rjsf/antd';

// Make modifications to the theme with your own fields and widgets

const Form = withTheme(AntDTheme);

Roadmap

See the general open issues.

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/chakra-ui/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Exports chakra-ui theme, fields and widgets for react-jsonschema-form.

Built With

Getting Started

Prerequisites

  • @chakra-ui/react >= 3
  • chakra-react-select >= 6
  • @rjsf/core >= 6
  • @rjsf/utils >= 6
  • @rjsf/validator-ajv8 >= 6

Refer to the rjsf installation guide and chakra-ui installation guide and for more details.


Installation

bash
yarn add @chakra-ui/react chakra-react-select @rjsf/core @rjsf/utils @rjsf/validator-ajv8

Usage

bash
yarn add @rjsf/chakra-ui
js
import Form from '@rjsf/chakra-ui';

or

js
import { withTheme } from '@rjsf/core';
import { Theme as ChakraUITheme } from '@rjsf/chakra-ui';

// Make modifications to the theme with your own fields and widgets

const Form = withTheme(ChakraUITheme);

Optional Chakra UI Theme properties

  • To pass additional properties to widgets, see this guide.

You can use ChakraProvider, to 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.

Custom Chakra uiSchema Chakra Property

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

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

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/core/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Core logic and classic Bootstrap 3 theme for react-jsonschema-form.

Built With

Getting Started

Prerequisites

  • Bootstrap 3

To use the default Bootstrap 3 theme, add a Bootstrap 3 CSS tag to your HTML page:

html
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />

Installation

sh
npm install @rjsf/core

Usage

javascript
import Form from '@rjsf/core';

Roadmap

See the general open issues.

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/daisyui/README.md`)

@rjsf/daisyui

Build Status
npm
npm downloads
Contributors
License

A DaisyUI theme for react-jsonschema-form.

This package integrates DaisyUI, Tailwind CSS, and RJSF to provide a modern, customizable form experience.

Screenshots

Features

  • Complete DaisyUI styling for all RJSF form elements
  • Responsive design with mobile-friendly layouts
  • Connected card styling for nested elements and arrays
  • Consistent visual hierarchy for complex forms
  • Support for all RJSF field types including:
    • Text inputs with proper styling and validation states
    • Select dropdowns with customizable option rendering
    • Checkboxes and radio buttons with optimized layouts
    • Arrays with add/remove/reorder functionality
    • Objects with proper nesting and visual hierarchy
    • Date/time inputs with cross-browser compatibility
  • Support for custom themes via DaisyUI's theme system
  • Accessible form components following WAI-ARIA practices

Getting Started

Prerequisites

  • daisyui >= 5
  • @fluentui/react-icons >= 2
  • @fluentui/react-migration-v0-v9 >= 9
  • @rjsf/core >= 6
  • @rjsf/utils >= 6
  • @rjsf/validator-ajv8 >= 6

Installation

bash
npm install @rjsf/daisyui @rjsf/core @rjsf/utils @rjsf/validator-ajv8 tailwindcss daisyui

Usage

jsx
import { Form } from '@rjsf/daisyui';
import validator from '@rjsf/validator-ajv8';

function App() {
  return (
    <Form schema={schema} uiSchema={uiSchema} validator={validator} onChange={console.log} onSubmit={console.log} />
  );
}

Theme Customization

The form components use DaisyUI's theme system. You can customize the theme by adding DaisyUI theme classes to your HTML:

html
<html data-theme="light">
  
</html>

For dynamic theme switching, you can change the data-theme attribute in your application code.

Tailwind Configuration

Make sure your src/index.css includes the DaisyUI plugin:

css
@import 'tailwindcss';
@source "../node_modules/@rjsf/daisyui";
@plugin "daisyui" {
  themes: all;
}

It's necessary to explicitely include the library as a source, as tailwindcss by default ignores everything in .gitignore

Customization

Grid Layout

The DaisyUI theme supports the standard RJSF layout grid system. You can use grid layouts by incorporating the LayoutGridField in your UI schema:

text
/* Detailed source-code truncated for AI context efficiency. */

The DaisyUI theme uses a flexible grid system based on Tailwind CSS's flex utilities. This grid layout integrates with the standard RJSF layout system, providing a consistent experience across all themes.

Theme Configuration

DaisyUI itself provides a variety of themes. To use a specific theme, add the data-theme attribute to your root element:

jsx
<div data-theme='dark'>
  <Form schema={schema} validator={validator} />
</div>

You can also dynamically change themes in your application:

jsx
import { useState } from 'react';
import { Form } from '@rjsf/daisyui';
import validator from '@rjsf/validator-ajv8';

function App() {
  const [theme, setTheme] = useState('light');

  return (
    <div data-theme={theme}>
      <select value={theme} onChange={(e) => setTheme(e.target.value)}>
        <option value='light'>Light</option>
        <option value='dark'>Dark</option>
        <option value='cupcake'>Cupcake</option>
        <option value='cyberpunk'>Cyberpunk</option>
        <option value='synthwave'>Synthwave</option>
        {/* Add more themes as needed */}
      </select>

      <Form schema={schema} validator={validator} />
    </div>
  );
}

Development

To develop locally:

bash
# Clone the repository
git clone https://github.com/rjsf-team/react-jsonschema-form.git
cd react-jsonschema-form

# Install dependencies
npm install

# Build packages
npm run build

# Run playground
npm run start:playground

To test the DaisyUI theme specifically, select it from the themes dropdown in the playground.

License

Apache-2.0


Overview (`packages/docs/README.md`)

react-jsonschema-form Documentation

This website is built using Docusaurus 2, a modern static website generator.

Installation

text
$ pnpm install

Local Development

text
$ pnpm start

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

Build

text
$ pnpm build

This command generates static content into the build directory and can be served using any static contents hosting service.

Deployment

Deployment is handled automatically by GitHub pages.


Overview (`packages/fluentui-rc/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Fluent UI React Components (v9) theme, fields and widgets for react-jsonschema-form.

Built With

Getting Started

Prerequisites

  • @fluentui/react-components >= 9
  • @fluentui/react-icons >= 2
  • @fluentui/react-migration-v0-v9 >= 9
  • @rjsf/core >= 6
  • @rjsf/utils >= 6
  • @rjsf/validator-ajv8 >= 6
bash
yarn add @fluentui/react-components @fluentui/react-icons @fluentui/react-migration-v0-v9 @rjsf/core @rjsf/utils @rjsf/validator-ajv8

Installation

bash
yarn add @rjsf/fluentui-rc

Usage

js
import Form from '@rjsf/fluentui-rc';

or

js
import { withTheme } from '@rjsf/core';
import { Theme as FluentUIRCTheme } from '@rjsf/fluentui-rc';

// Make modifications to the theme with your own fields and widgets

const Form = withTheme(FluentUIRCTheme);

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/mantine/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Mantine theme, fields and widgets for react-jsonschema-form.

Built With

Getting Started

Prerequisites

  • @mantine/core >= 8
  • @mantine/hooks >= 8
  • @mantine/dates >= 8
  • dayjs >= 1.8.0
  • @rjsf/core >= 6.0.0
sh
npm install @mantine/core @mantine/hooks @mantine/dates dayjs @rjsf/core

Installation

sh
npm install @rjsf/mantine

Usage

javascript
import Form from '@rjsf/mantine';

or

javascript
import { withTheme } from '@rjsf/core';
import { Theme as MantineTheme } from '@rjsf/mantine';

// Make modifications to the theme with your own fields and widgets

const Form = withTheme(MantineTheme);

Optional Mantine Theme properties

  • To pass additional properties to widgets, see this guide.

Mantine Widget Optional Properties

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/mui/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Exports MUI version 5 theme, fields, and widgets for react-jsonschema-form.

Built With

Getting Started

Prerequisites

NOTE: Material UI 7 requires React 18, so you will need to upgrade

  • @mui/material >= 7
  • @mui/icons-material >= 7
  • @emotion/react >= 11
  • @emotion/styled >= 11
  • @rjsf/core >= 6
  • @rjsf/utils >= 6
  • @rjsf/validator-ajv8 >= 6
bash
yarn add @mui/material @mui/icons-material @emotion/react @emotion/styled @rjsf/core @rjsf/utils @rjsf/validator-ajv8

Installation

bash
yarn add @rjsf/mui

Usage

Material UI version 7

js
import Form from '@rjsf/mui';

or

js
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);

Customizing MUI-specific props

You can pass MUI-specific props (like sx, rjsfSlotProps, variant, etc.) directly to any MUI component rendered by a Template or Widget via ui:options in the uiSchema.

json
"myField": {
  "ui:options": {
    "mui": {
      "variant": "filled",
      "sx": {
        "backgroundColor": "background.paper"
      },
      "rjsfSlotProps": {
        "input": {
          "endAdornment": "kg"
        }
      }
    }
  }
}

For more details on available properties and rjsfSlotProps targets, see the Material UI Customization Documentation.

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/primereact/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

PrimeReact theme, fields, and widgets for react-jsonschema-form.

Built With

Getting Started

Prerequisites

  • primereact >= 8.0.0
  • primeicons >= 6.0.0
  • @rjsf/core >= 6
  • @rjsf/utils >= 6
  • @rjsf/validator-ajv8 >= 6
sh
npm install primereact primeicons @rjsf/core

Installation

sh
npm install @rjsf/primereact

Usage

javascript
import Form from '@rjsf/primereact';

or

javascript
import { withTheme } from '@rjsf/core';
import { Theme as PrimeReactTheme } from '@rjsf/primereact';

// Customize the theme with your own fields and widgets

const Form = withTheme(PrimeReactTheme);

Roadmap

See the general open issues.

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub
build-shield: https://github.com/rjsf-team/react-jsonschema-form/workflows/CI/badge.svg


Overview (`packages/react-bootstrap/README.md`)

Table of Contents

About The Project

Exports react-bootstrap theme, fields and widgets for react-jsonschema-form.

Built With

Getting Started

Prerequisites

  • react-bootstrap >= 2.0.0
  • @rjsf/core >= 6
  • @rjsf/utils >= 6
  • @rjsf/validator-ajv8 >= 6
bash
yarn add react-bootstrap @rjsf/core @rjsf/utils @rjsf/validator-ajv8

Installation

bash
yarn add @rjsf/react-bootstrap

Usage

js
import Form from 'packages/react-bootstrap';

or

js
import { withTheme } from '@rjsf/core';
import { Theme as BootstrapTheme } from 'packages/react-bootstrap';

const Form = withTheme(BootstrapTheme);

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/semantic-ui/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Exports semantic-ui theme, fields and widgets for react-jsonschema-form.

Built With

Getting Started

Prerequisites

sh
yarn add semantic-ui-css semantic-ui-react @rjsf/core

Installation

sh
yarn add @rjsf/semantic-ui

Usage

javascript
import Form from '@rjsf/semantic-ui';

or

javascript
import { withTheme } from '@rjsf/core';
import { Theme as SemanticUITheme } from '@rjsf/semantic-ui';

// Make modifications to the theme with your own fields and widgets

const Form = withTheme(SemanticUITheme);

Optional Semantic UI Theme properties

  • To pass additional properties to widgets, see this guide.

Semantic Widget Optional Properties

Custom Semantic Widget Properties

Below are the current default options for all widgets:

json
{
  "ui:options": {
    "semantic": {
      "fluid": true,
      "inverted": false,
      "errorOptions": {
        "size": "small",
        "pointing": "above"
      }
    }
  }
}

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/shadcn/README.md`)

Table of Contents

About The Project

Exports shadcn theme, fields and widgets for react-jsonschema-form.

Live demo

Built With

Getting Started

Prerequisites

  • @rjsf/core >= 6
  • @rjsf/utils >= 6
  • @rjsf/validator-ajv8 >= 6
bash
yarn add @rjsf/core @rjsf/utils @rjsf/validator-ajv8

Installation

bash
yarn add @rjsf/shadcn

Usage

js
import Form from '@rjsf/shadcn';

or

js
import {withTheme} from '@rjsf/core';
import {Theme as shadcnTheme} from '@rjsf/shadcn';

const Form = withTheme(shadcnTheme);

Theming

Using Tailwind

Follow shadCN installation guide here for your application

The color of the RJSF will automatically apply with your shadCN config.

Tailwind v3

Add the following line to your tailwind.config.ts

typescript
content: [
    "./src/**/*.{html,js}",
    "node_modules/@rjsf/shadcn/src/**/*.{js,ts,jsx,tsx,mdx}" // Add this line
  ],

Tailwind v4

Add the following line to your equivalent global.css

css
@source "../node_modules/@rjsf/shadcn";

Not using Tailwind

Use the theme on demo site

A prebuilt stylesheet for each bundled theme is included in the npm package. Simply do

text
import '@rjsf/shadcn/dist/[theme].css';
e.g:
import '@rjsf/shadcn/dist/default.css';

Note that these stylesheets are complete Tailwind builds and include Tailwind's preflight reset, so importing one
will also restyle the rest of your page. If your application already builds Tailwind, use the
Using Tailwind section above instead.

Supported themes are:

  • default
  • amethyst-haze
  • caffeine
  • claude
  • clean-slate
  • neo-brutalism
  • pastel-dreams
  • soft-pop
  • twitter
  • vercel

Coloring

  • Generate a theme from official shadCN site
    or tweakcn
  • Navigate to packages/shadcn/src/css, create a new file called [your-theme].css
  • Replace the base layer code with your new color
  • Follow the next section to build your CSS file

Build your CSS file

If you are not using tailwind but still wants to use this theme, you can follow these steps:

  • Clone the repository
text
cd packages/shadcn
npm i
npm run build:css
  • Include the built dist/[your-theme].css in your application

Dark mode (Tailwind only)

Check out this section by shadCN

RTL (Tailwind only)

Installation

bash
npm install @radix-ui/react-direction --save

Implementation

  1. Wrap your layout with DirectionProvider:

    tsx
    import {DirectionProvider as RadixDirectionProvider} from '@radix-ui/react-direction;
    
    function Layout({children, direction}) {
        return (
            <RadixDirectionProvider dir={direction}>
                {children}
            </RadixDirectionProvider>
        );
    }
  2. Set HTML direction attribute:

    html
    <html dir="rtl" lang="en">
  3. You can refer to direction-context.tsx, direction-provider.tsx and rtl-toggle.tsx from demo repository for
    implementation.

Updating to latest shadCN version

  • Simply copy the shadcn components into shadcn/src/components/ui and rebuilt the packages or using the shadcn CLI at
    the root level with the components.json
  • For RTL version, you might need component from here
    by nahasco
  • Fancy multi-select

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub
build-shield: https://github.com/rjsf-team/react-jsonschema-form/workflows/CI/badge.svg


Overview (`packages/snapshot-tests/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Package with snapshot test suits for testing themes for react-jsonschema-form.

Getting Started

Installation

sh
npm install @rjsf/snapshot-tests

Usage

tsx
import { arrayTests } from '@rjsf/snapshot-tests'; // OR
// import { formTests } from '@rjsf/snapshot-tests';
// import { gridTests } from '@rjsf/snapshot-tests';
// import { objectTests } from '@rjsf/snapshot-tests';

import Form from '../src';

arrayTests(Form); // OR
// formTests(Form);
// gridTests(Form);
// objectTests(Form);

Roadmap

See the general open issues.

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/utils/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Exports utils functions for react-jsonschema-form.

Built With

Getting Started

Installation

bash
yarn add @rjsf/utils

Usage

jsx
import * as Utils from '@rjsf/utils';

Documentation

Utility function documentation

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/validator-ajv8/README.md`)

Build Status
npm
npm downloads
Contributors
Apache 2.0 License

Table of Contents

About The Project

Exports validator-ajv8 plugin for react-jsonschema-form.

Built With

Getting Started

Prerequisites

React JsonSchema Form Utils

  • @rjsf/utils >= 5.0.0
bash
yarn add @rjsf/core

Installation

bash
yarn add @rjsf/validator-ajv8

Usage

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

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

<Form schema={schema} validator={validator} />;

or, using a more complex example using custom validator with custom formats

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

const customFormats = {
  'phone-us': /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/,
};

const validator = customizeValidator({
  customFormats,
});

const schema: RJSFSchema = {
  type: 'string',
  format: 'phone-us',
};

<Form schema={schema} validator={validator} />;

or, using a more complex example using a custom with additional meta schema

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

const metaSchemaDraft06 = require('ajv/lib/refs/json-schema-draft-06.json');

const validator = customizeValidator({
  additionalMetaSchemas: [metaSchemaDraft06],
});

const schema: RJSFSchema = {
  $schema: 'http://json-schema.org/draft-06/schema#',
  type: 'string',
};

<Form schema={schema} validator={validator} />;

or, using a more complex example using custom validator config override options

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

const validator = customizeValidator({
  ajvOptionsOverrides: {
    $data: true,
    verbose: true,
  },
});

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

<Form schema={schema} validator={validator} />;

or, using a more complex example using ajv-formats custom format options.

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

const validator = customizeValidator({
  ajvFormatOptions: {
    keywords: true,
    formats: ['date', 'time'],
  },
});

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

<Form schema={schema} validator={validator} />;

Finally, you can combine both additional meta schemas, custom formats, custom validator config override options and ajv-formats custom format options.

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

const metaSchemaDraft06 = require('ajv/lib/refs/json-schema-draft-06.json');

const customFormats = {
  'phone-us': /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/,
};

const validator = customizeValidator({
  additionalMetaSchemas: [metaSchemaDraft06],
  customFormats,
  ajvOptionsOverrides: {
    $data: true,
    verbose: true,
  },
  ajvFormatOptions: {
    keywords: true,
    formats: ['date', 'time'],
  },
});

const schema: RJSFSchema = {
  $schema: 'http://json-schema.org/draft-06/schema#',
  type: 'string',
  format: 'phone-us',
};

<Form schema={schema} validator={validator} />;

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Read our contributors' guide to get started.

Contact

rjsf team: https://github.com/orgs/rjsf-team/people

GitHub repository: https://github.com/rjsf-team/react-jsonschema-form


Overview (`packages/validator-ata/README.md`)

Apache 2.0 License

Table of Contents

About

@rjsf/validator-ata plugs ata-validator into react-jsonschema-form as a drop-in alternative to @rjsf/validator-ajv8. The public API mirrors validator-ajv8 so swapping is a one-line change in the validator import. Error format, custom-format hook, custom validation, and error transformation all work the same way.

ata is a JSON Schema validator that targets Draft 2020-12 (98.5% spec compliance, 95.3% schemasafe pass rate) and is Standard Schema compliant. Its differentiators relative to AJV: pattern checks are RE2-backed (no ReDoS surface), and schemas can be compiled at build time for environments where bundle size or CSP restricts runtime codegen.

Installation

bash
npm install @rjsf/validator-ata

ata-validator is a dependency of this package and is installed with it.

Usage

ts
import Form from '@rjsf/core';
import validator from '@rjsf/validator-ata';

<Form schema={schema} validator={validator} />;

Customization

ts
import { customizeValidator } from '@rjsf/validator-ata';

const validator = customizeValidator({
  customFormats: {
    'phone-us': /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/,
    'area-code': /\d{3}/,
  },
  ataOptionsOverrides: {
    verbose: true,
  },
});

customizeValidator accepts:

  • customFormats — same shape as validator-ajv8. Values may be a RegExp, an anchored regex source string, or a (value: string) => boolean predicate.
  • ataOptionsOverrides — plain ata-validator options spread on top of the defaults; use this to flip coerceTypes, removeAdditional, verbose, or abortEarly.
  • additionalMetaSchemas — extra schemas registered via Validator#addSchema for cross-schema $ref resolution.
  • extenderFn — hook applied against a freshly-built Validator (e.g. for adding additional formats or schemas in one place).
  • suppressDuplicateFiltering — passthrough to the RJSF error processor; same semantics as in validator-ajv8.

A Localizer may be supplied as the second argument. ata error objects use the same field names as AJV (keyword, instancePath, schemaPath, params, message, parentSchema), so localizers that mutate message in place port across without changes. The pre-quote dance that the AJV validator runs against ajv-i18n is intentionally not replicated here — ata's error params are frozen, and the existing locale catalogues for AJV are not portable to ata's keyword set.

Differences from validator-ajv8

The ValidatorType contract is identical, and the shared @rjsf/utils schema test suite passes against this validator with the deltas below. Behavior outside of this list mirrors validator-ajv8.

  • Precompiled validators are supported. See Precompiled validators in the docs.
  • ajvOptionsOverrides, ajvFormatOptions, AjvClass have no equivalents and are intentionally not accepted. ataOptionsOverrides replaces the first; built-in formats are always installed and don't require an opt-in flag.
  • isValid and rawValidation deep-clone formData before passing it to ata. ata's default-applier writes default values into the input object during validation, while AJV treats validation as a pure operation. The clone preserves the AJV contract RJSF expects when probing data through repeated isValid calls (oneOf/anyOf option resolution).
  • Custom-keyword extensions (e.g. ajv-errors, ajv-merge-patch) have no ata-side counterpart yet. Schemas using these keywords will validate (ata silently ignores unknown keywords) but the extension semantics are not applied.

Contributing

See the monorepo CONTRIBUTING.md. Issues and PRs welcome on either the validator package or ata-validator itself.


Overview (`packages/validator-cfworker/README.md`)

@rjsf/validator-cfworker

@rjsf/validator-cfworker is an additional validator option for CSP-constrained RJSF users.
It uses @cfworker/json-schema to interpret schemas without eval or new Function, and defaults to JSON Schema draft 2020-12.

It is not an AJV replacement. Choose it when an eval-free runtime is more important than AJV-specific keywords, extensions, localization, or code generation.

tsx
import Form from '@rjsf/core';
import validator from '@rjsf/validator-cfworker';

export default function Example() {
  return <Form schema={{ type: 'string' }} validator={validator} />;
}

Behavior

  • Implements RJSF's ValidatorType<T, S, F> interface.
  • Normalizes undefined before validation: undefined object members are omitted so required errors surface, while undefined array entries become null.
  • Caches schema-bound engine instances by schema $id (or the RJSF schema hash) and refreshes them when the schema or root schema changes.
  • Supports customValidate, transformErrors, custom formats, duplicate anyOf/oneOf filtering, and the RJSF color and data-url formats.
  • Supports draft 4, draft 7, draft 2019-09, and draft 2020-12 through the draft customization option; the default is draft 2020-12.
ts
import { customizeValidator } from '@rjsf/validator-cfworker';

const validator = customizeValidator({
  draft: '2020-12',
  shortCircuit: false,
  customFormats: {
    'phone-us': /\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}$/,
  },
});

Unsupported-keyword matrix

Unknown keywords are annotations to the underlying engine, so unsupported extensions are not validation constraints.

Keyword or extension Status Notes
$dynamicRef / $dynamicAnchor Unsupported Tracked upstream in cfworker/json-schema#150.
AJV $data references Unsupported AJV-specific extension; use literal schema values.
OpenAPI discriminator Unsupported Use standard oneOf constraints without discriminator semantics.
errorMessage from ajv-errors Unsupported Use RJSF's transformErrors hook instead.

Precompiled-validator mode is intentionally outside this initial package. Runtime error messages also differ from AJV, and there is no ajv-i18n equivalent.

Upstream state and provenance

This package is ported from glama-ai/rjsf-validator-cfworker, whose structure was intentionally kept compatible with RJSF.
The original MIT copyright and license are preserved in LICENSE; the RJSF integration and subsequent changes are distributed under the monorepo's Apache-2.0 license.

The underlying @cfworker/json-schema package's latest release is from January 2025. Its tracker includes open correctness reports for duplicate schema URIs (#335) and additionalProperties behavior (#336), as well as the $dynamicRef gap above.
This wrapper's per-schema cache avoids repeat registration on RJSF's isValid path, but it does not change the upstream engine's other semantics.
The package is therefore presented as an additional option for CSP-constrained users.


Index (`docs/index.md`)

react-jsonschema-form

The react-jsonschema-form docs have been moved here.


Packages Docs Docs 01 Quickstart (`packages/docs/docs/01-quickstart.md`)

Quickstart

Let's walk through setup of a form after installing the dependency properly.
NOTE: As of version 5, the Form now requires you to provide a validator implementation. We recommend the one from @rjsf/validator-ajv8.

Form schema

First, specify a schema using the JSON Schema specification. The below schema renders a single string field:

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

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

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

You can also render an object with multiple fields with the below schema:

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

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

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

For more information and examples of JSON Schema properties that this library supports, see Using JSON Schema.

Form uiSchema

The uiSchema is used to add more customization to the form's look and feel. Use the classNames
attribute of the uiSchema to add a custom CSS class name to the form:

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

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

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

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

To customize object fields in the uiSchema, the structure of the
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:

tsx
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:

tsx
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:

tsx
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'));

Packages Docs Docs Advanced Customization Index (`packages/docs/docs/advanced-customization/index.mdx`)


title: Advanced Customization

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Docs Api Reference Index (`packages/docs/docs/api-reference/index.mdx`)


title: API Reference

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Docs Json Schema Index (`packages/docs/docs/json-schema/index.mdx`)


title: JSON Schema

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Docs Migration Guides Index (`packages/docs/docs/migration-guides/index.mdx`)


title: Migration Guides

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Docs Usage Index (`packages/docs/docs/usage/index.mdx`)


title: Usage and Customization

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 3.2.1 00 Quickstart (`packages/docs/versioned_docs/version-3.2.1/00-quickstart.md`)

Quickstart

Let's walk through setup of a form after installing the dependency properly.

Form schema

First, specify a schema using the JSON Schema specification. The below schema renders a single string field:

jsx
const schema = {
  title: "Test form",
  type: "string"
};

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

You can also render an object with multiple fields with the below schema:

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

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

For more information and examples of JSON Schema properties that this library supports, see Using JSON Schema.

Form uiSchema

The uiSchema is used to add more customization to the form's look and feel. Use the classNames
attribute of the uiSchema to add a custom CSS class name to the form:

jsx
const schema = {
  title: "Test form",
  type: "string"
};

const uiSchema = {
  classNames: "custom-css-class"
};

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

To customize object fields in the uiSchema, the structure of the
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:

jsx
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:

jsx
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:

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

Packages Docs Versioned Docs Version 4.2.3 00 Quickstart (`packages/docs/versioned_docs/version-4.2.3/00-quickstart.md`)

Quickstart

Let's walk through setup of a form after installing the dependency properly.

Form schema

First, specify a schema using the JSON Schema specification. The below schema renders a single string field:

jsx
const schema = {
  title: "Test form",
  type: "string"
};

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

You can also render an object with multiple fields with the below schema:

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

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

For more information and examples of JSON Schema properties that this library supports, see Using JSON Schema.

Form uiSchema

The uiSchema is used to add more customization to the form's look and feel. Use the classNames
attribute of the uiSchema to add a custom CSS class name to the form:

jsx
const schema = {
  title: "Test form",
  type: "string"
};

const uiSchema = {
  classNames: "custom-css-class"
};

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

To customize object fields in the uiSchema, the structure of the
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:

jsx
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:

jsx
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:

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

Packages Docs Versioned Docs Version 5.24.10 01 Quickstart (`packages/docs/versioned_docs/version-5.24.10/01-quickstart.md`)

Quickstart

Let's walk through setup of a form after installing the dependency properly.
NOTE: As of version 5, the Form now requires you to provide a validator implementation. We recommend the one from @rjsf/validator-ajv8.

Form schema

First, specify a schema using the JSON Schema specification. The below schema renders a single string field:

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

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

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

You can also render an object with multiple fields with the below schema:

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

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

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

For more information and examples of JSON Schema properties that this library supports, see Using JSON Schema.

Form uiSchema

The uiSchema is used to add more customization to the form's look and feel. Use the classNames
attribute of the uiSchema to add a custom CSS class name to the form:

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

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

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

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

To customize object fields in the uiSchema, the structure of the
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:

tsx
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:

tsx
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:

tsx
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'));

Packages Docs Versioned Docs Version 3.2.1 Advanced Customization Index (`packages/docs/versioned_docs/version-3.2.1/advanced-customization/index.mdx`)


title: Advanced Customization

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 3.2.1 Api Reference Index (`packages/docs/versioned_docs/version-3.2.1/api-reference/index.mdx`)


title: API Reference

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 3.2.1 Usage Index (`packages/docs/versioned_docs/version-3.2.1/usage/index.mdx`)


title: Usage and Customization

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 4.2.3 Advanced Customization Index (`packages/docs/versioned_docs/version-4.2.3/advanced-customization/index.mdx`)


title: Advanced Customization

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 4.2.3 Api Reference Index (`packages/docs/versioned_docs/version-4.2.3/api-reference/index.mdx`)


title: API Reference

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 4.2.3 Usage Index (`packages/docs/versioned_docs/version-4.2.3/usage/index.mdx`)


title: Usage and Customization

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 5.24.10 Advanced Customization Index (`packages/docs/versioned_docs/version-5.24.10/advanced-customization/index.mdx`)


title: Advanced Customization

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 5.24.10 Api Reference Index (`packages/docs/versioned_docs/version-5.24.10/api-reference/index.mdx`)


title: API Reference

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 5.24.10 Json Schema Index (`packages/docs/versioned_docs/version-5.24.10/json-schema/index.mdx`)


title: JSON Schema

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 5.24.10 Migration Guides Index (`packages/docs/versioned_docs/version-5.24.10/migration-guides/index.mdx`)


title: Migration Guides

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Versioned Docs Version 5.24.10 Usage Index (`packages/docs/versioned_docs/version-5.24.10/usage/index.mdx`)


title: Usage and Customization

import DocCardList from '@theme/DocCardList';

{frontMatter.description}


Packages Docs Package.Json (`packages/docs/package.json`)

{
"name": "@rjsf/docs",
"version": "6.11.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc",
"precommit": "lint-staged",
"cs-check": "oxfmt --check "src//*.{ts,tsx}"",
"cs-format": "oxfmt "src/
/.{ts,tsx}""
},
"lint-staged": {
"src/**/
.{ts,tsx}": [
"oxfmt"
]
},
"dependencies": {
"@docusaurus/core": "^3.10.2",
"@docusaurus/preset-classic": "^3.10.2",
"@mdx-js/react": "^3.1.1",
"prism-react-renderer": "^2.4.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.10.2",
"@docusaurus/plugin-content-docs": "^3.10.2",
"@docusaurus/types": "^3.10.2",
"@tsconfig/docusaurus": "^2.0.9"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"engines": {
"node": ">=20"
}
}


Packages Docs Tsconfig.Json (`packages/docs/tsconfig.json`)

{
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@tsconfig/docusaurus/tsconfig.json",
"compilerOptions": {
"resolveJsonModule": true
}
}


Packages Docs Docs 00 Introduction (`packages/docs/docs/00-introduction.mdx`)


id: intro title: Introduction slug: /

react-jsonschema-form

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

A live playground is hosted on GitHub Pages:

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):

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

Then import the dependencies as follows:

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

Our latest version requires React 16+.

Usage

tsx
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

This project initially started as a mozilla-services project.
Testing is powered by BrowserStack.
Deploy Previews are provided by Netlify.

Who uses react-jsonschema-form?

  • ...

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


Packages Docs Docs Contributing (`packages/docs/docs/contributing.md`)

Contributing

Development server

We are using Vite to power our playground, which caches all the built @rjsf/* distributions.
In order to test the playground locally after a new clone or fresh pull from main, run the following from the root directory of the monorepo:

bash
pnpm install
pnpm run build
cd packages/playground
pnpm start

This will start the live development server showcasing components at localhost:8080.

Whenever you make changes to source code, stop the running playground and return to the root directory and rerun pnpm run build.
Thanks to nx caching, this should only rebuild what is necessary.
After the build is complete, return to the root of the playground and restart the server via pnpm start.

First time step

If this is the first time you have cloned the repo, run the pnpm run prepare script that will set up husky to provide a git precommit hook that will format and lint any code you have added to a PR.

Optional development process

With the large number of packages, sometimes running pnpm run build or pnpm start from the root directory will overwhelm an underpowered computer.
If that is the situation for you, you can instead use pnpm run build-serial to build the packages one at a time instead of all at once.
Also, if you are only working on one package, you can pnpm run build and pnpm run test from within the subdirectory.
Finally, you can simply pnpm start inside of the playground directory to test changes if you have already built all of your packages, without needing to watch all of the packages via the root directory pnpm start.

Troubleshooting build failures

Sometimes your local builds fail and you can't figure out why. This is most likely to happen after rebase to main due
to package.json changes upstream. There are two commands you can use to (hopefully) get your environment back to a
working state. Try running the following two commands:

bash
pnpm run refresh-node-modules
pnpm run clean-build

The first command will delete all of the node_modules directories in the environment and then rerun pnpm install.
The second command cleans up the typescript build cache files before retrying the build.

Worst case scenario when neither of those commands work, try running pnpm run nuke-build-env and then rerun the two commands.

Cloud builds

When building in environments with limited memory, such as Netlify, it's recommended to use pnpm run build-serial that builds the packages serially.

Coding style

All the JavaScript/Typescript code in this project conforms to the prettier coding style.
Code is automatically prettified upon commit using precommit hooks, assuming you followed the First time step above.

You can also run pnpm cs-format within any package directory you are changing.

Documentation

We use Docusaurus to build our documentation. To run documentation locally, run:

bash
cd packages/docs
pnpm start

Documentation will be served on localhost:3000.

Tests

You can run all tests from the root directory OR from packages subdirectory using the following command:

bash
pnpm run test

Snapshot testing

All the themes, including core use snapshot testing (NOTE: core also has extensive non-snapshot tests).
The source-code of these snapshot tests reside in the core package in the testSnap directory and are shared with all the themes.
In order to support the various themes, the code for the tests are actually functions that take two parameters:

  • Form: ComponentType<FormProps> - The component from the theme implementation
  • [customOptions]: { [key: string]: TestRendererOptions } - an optional map of react-test-renderer TestRendererOptions implementations that some themes need to be able properly run

There are functions in the testSnap directory: arrayTests, formTests and objectTests, each with its own definition of customOptions

Each theme will basically run these functions by creating a Xxx.test.tsx file (where Xxx is Array, Form or Object) that looks like the following:

tsx
import { arrayTests } from '@rjsf/snapshot-tests'; // OR
// import { formTests } from '@rjsf/snapshot-tests';
// import { objectTests } from '@rjsf/snapshot-tests';

import Form from '../src';

arrayTests(Form); // OR
// formTests(Form);
// objectTests(Form);

Anytime you add a new feature, be sure to update the appropriate xxxTests() function in the testSnap directory and do pnpm run test from the root directory to update all the snapshots.
If you add a theme-only feature, it is ok to update the appropriate Xxx.test.tsx file to add (or update) the theme-specific describe() block.
For example:

tsx
import { RJSFSchema, UiSchema } from '@rjsf/utils';
import { arrayTests } from '@rjsf/snapshot-tests';

import Form from '../src';

formTests(Form);

describe('Theme specific tests', () => {
  it('test a theme-specific option', () => {
    const schema: RJSFSchema = {
      type: 'object',
      properties: {
        name: {
          type: 'string',
        },
      },
    };
    const uiSchema: UiSchema = {
      // Enable the theme specific feature
    };
    const tree = renderer.create(<Form schema={schema} uiSchema={uiSchema} validator={validator} />).toJSON();
    expect(tree).toMatchSnapshot();
  });
});

See the antd Form.test.tsx for a specific example of this.

Code coverage

Code coverage reports are currently available only for the @rjsf/core theme package.
They are generated using nyc each time the pnpm test-coverage script is run.
The full report can be seen by opening ./coverage/lcov-report/index.html.

Utils and validator-ajv8 code coverage

100% code coverage is required by the @rjsf/utils and @rjsf/validator-ajv8 tests.
If you make changes to those libraries, you will have to maintain that coverage, otherwise the tests will fail.

NOTE: All three of these directories share the same tests for verifying validator based APIs. See the documentation in the getTestValidator() functions for more information.

Releasing

To release, go to the main branch (NOT a fork) and then create a new branch with the version number (with an rc prefix instead of v).
For instance if you are about to create the new 6.100.10 branch, then you would run the following commands:

bash
git checkout -b rc6.100.10
pnpm exec nx release version --git-tag
git commit -m "Releasing 6.100.10"
git push
pnpm run update-version-tags

Make sure you use semver for version numbering when selecting the version.
The pnpm exec nx release version --git-tag command will update the package*.json files and create a new version tag.
Committing and pushing the branch will allow you to create the PR on GitHub.
The pnpm run update-version-tags will push the tags up to GitHub.

Then, make a PR to main. Merge the PR into main -- make sure you use "merge commit", not squash and merge, so that
the original commit where the tag was based on is still present in the main branch.

Then, create a release in the GitHub "Releases" tab, select the new tag that you have added,
and add a description of the changes in the new release. You can copy
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:

bash
cd packages/playground
pnpm run publish-to-gh-pages

Releasing a new package

Publishing a new @rjsf/* package requires additional setup. The package must first be published locally, then in the NPM web app, you must set up "Trusted Publishing" so future releases can be published via GitHub Actions. The steps to accomplish this are:

  1. Create the new release as described above. Existing packages will be published, but the jobs to publish new package(s) will fail.
  2. Locally, check out the release tag (e.g. git checkout v6.8.0). You may need to git fetch --tags. Make sure your git status is clean.
  3. cd packages/new-package
  4. pnpm login (login to an account with RJSF publishing privileges)
  5. pnpm publish --no-git-checks.

The new package will be released. Then, set up Trusted Publishing:

  1. Navigate to the new package in NPM (e.g. https://www.npmjs.com/package/@rjsf/new-package)
  2. Go to Settings -> Trusted Publisher -> GitHub Actions
  3. Set up the fields to match an existing package (e.g. look at @rjsf/core).
    1. Organization or user: rjsf-team
    2. Repository: react-jsonschema-form
    3. Workflow filename: release.yml
    4. Allow npm publish

Packages Docs Versioned Sidebars Version 3.2.1 Sidebars.Json (`packages/docs/versioned_sidebars/version-3.2.1-sidebars.json`)

{
"docs": [
{
"type": "autogenerated",
"dirName": "."
}
]
}


Packages Docs Versioned Sidebars Version 4.2.3 Sidebars.Json (`packages/docs/versioned_sidebars/version-4.2.3-sidebars.json`)

{
"docs": [
{
"type": "autogenerated",
"dirName": "."
}
]
}


Packages Docs Versioned Sidebars Version 5.24.10 Sidebars.Json (`packages/docs/versioned_sidebars/version-5.24.10-sidebars.json`)

{
"docs": [
{
"type": "autogenerated",
"dirName": "."
}
]
}


Packages Docs Docs Advanced Customization Custom Templates (`packages/docs/docs/advanced-customization/custom-templates.md`)

Custom Templates

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

Custom Field Custom Template Custom Widget
What it does Overrides all behaviour Overrides just the layout (not behaviour) Overrides just the input box (not layout, labels, or help, or validation)
Usage Global or per-field Global or per-field Global or per-field
Global Example <Form fields={{ MyCustomField }} /> <Form templates={{ ArrayFieldTemplate: MyArrayTemplate }} /> <Form widgets={{ MyCustomWidget }} />
Per-Field Example "ui:field": MyCustomField "ui:ArrayFieldTemplate": MyArrayTemplate "ui:widget":MyCustomWidget
Documentation Custom Fields See documentation below Custom Widgets

In version 5, all existing templates were consolidated into a new TemplatesType interface that is provided as part of the Registry.
They can also be overloaded globally on the Form via the templates prop as well as globally or per-field through the uiSchema.
Further, many new templates were added or repurposed from existing widgets and fields in an effort to simplify the effort needed by theme authors to build new and/or maintain current themes.
These new templates can also be overridden by individual users to customize the specific needs of their application.
A special category of templates, ButtonTemplates, were also added to support the easy replacement of the Submit button on the form, the Add and Remove buttons associated with additionalProperties and patternProperties on objects and elements of arrays, as well as the Move up and Move down buttons used for reordering arrays.
This category, unlike the others, can only be overridden globally via the templates prop on Form.

Below is the table that lists all the templates, their props interface, their uiSchema name and from where they originated in the previous version of RJSF:

Template Props Type UiSchema name Origin
ArrayFieldTemplate ArrayFieldTemplateProps ui:ArrayFieldTemplate Formerly Form.ArrayFieldTemplate or Registry.ArrayFieldTemplate
ArrayFieldDescriptionTemplate ArrayFieldDescriptionProps ui:ArrayFieldDescriptionTemplate Formerly part of @rjsf/core ArrayField, refactored as a template, used in all ArrayFieldTemplate implementations
ArrayFieldItemTemplate ArrayFieldItemTemplateProps ui:ArrayFieldItemTemplate Formerly an internal class for ArrayFieldTemplates in all themes, refactored as a template in each theme, used in all ArrayFieldTemplate implementations
ArrayFieldItemButtonsTemplate ArrayFieldItemButtonsTemplateProps ui:ArrayFieldItemButonsTemplate Formerly an internal class for ArrayFieldItemTemplates in all themes, refactored as a template in the core, used in all ArrayFieldItemTemplate implementations
ArrayFieldTitleTemplate ArrayFieldTitleProps ui:ArrayFieldTitleTemplate Formerly part of @rjsf/core ArrayField, refactored as a template, used in all ArrayFieldTemplate implementations.
BaseInputTemplate WidgetProps ui:BaseInputTemplate Formerly a widget in @rjsf.core moved to templates and newly implemented in each theme to maximize code reuse.
CyclicSchemaExpandTemplate CyclicSchemaExpandProps ui:CyclicSchemaExpandTemplate Added in RJSF v6 to support circular $ref cycle detection
DescriptionFieldTemplate DescriptionFieldProps ui:DescriptionFieldTemplate Formerly a field in @rjsf.core moved to templates with the Template suffix. Previously implemented in each theme.
ErrorListTemplate ErrorListProps ui:ErrorListTemplate Formerly Form.ErrorList moved to templates with the Templates suffix. Previously implemented in each theme.
FallbackFieldTemplate FallbackFieldTemplateProps ui:FallbackFieldTemplate Added in RJSF v6
FieldErrorTemplate FieldErrorProps ui:FieldErrorTemplate Formerly internal ErrorList component accessible only to SchemaField
FieldHelpTemplate FieldHelpProps ui:FieldHelpTemplate Formerly internal Help component accessible only to SchemaField
FieldTemplate FieldTemplateProps ui:FieldTemplate Formerly Form.FieldTemplate or Registry.FieldTemplate
GridTemplate GridTemplateProps ui:GridTemplate Theme dependent implementations of a Grid element for either rows or columns
MultiSchemaFieldTemplate MultiSchemaFieldTemplateProps ui:MultiSchemaFieldTemplate Formerly part of @rjsf/core MultiSchemaField`, refactored as a template
ObjectFieldTemplate ObjectFieldTemplateProps ui:ObjectFieldTemplate Formerly Form.ObjectFieldTemplate or Registry.ObjectFieldTemplate
OptionalDataControlsTemplate OptionalDataControlsTemplateProps ui:OptionalDataControlsTemplate New feature in V6
TitleFieldTemplate TitleFieldProps ui:TitleFieldTemplate Formerly a field in @rjsf.core moved to templates with the Template suffix. Previously implemented in each theme.
UnsupportedFieldTemplate UnsupportedFieldProps ui:UnsupportedFieldTemplate Formerly a field in @rjsf.core moved to templates with the Template suffix.
WrapIfAdditionalTemplate WrapIfAdditionalTemplateProps ui:WrapIfAdditionalTemplate Formerly an internal component in @rjsf.core. Previously implemented in most themes.
ButtonTemplates.AddButton IconButtonProps n/a Formerly an internal implementation in each theme
ButtonTemplates.MoveDownButton IconButtonProps n/a Formerly an internal implementation in each theme
ButtonTemplates.MoveUpButton IconButtonProps n/a Formerly an internal implementation in each theme
ButtonTemplates.RemoveButton IconButtonProps n/a Formerly an internal implementation in each theme
ButtonTemplates.SubmitButton SubmitButtonProps n/a Formerly a field in each theme move to templates.ButtonTemplates

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.
If you only want to customize how the array's title, description or how the array items are presented, you may want to consider providing your own ArrayFieldDescriptionTemplate, ArrayFieldItemTemplate and/or ArrayFieldTitleTemplate instead.
You can also customize arrays by specifying a widget in the relevant ui:widget schema, more details over on Custom Widgets.

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

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

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

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

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

tsx
import { UiSchema } from '@rjsf/utils';
import ArrayFieldTemplate from './ArrayFieldTemplate';

const uiSchema: UiSchema = {
  'ui:ArrayFieldTemplate': ArrayFieldTemplate,
};

or a string value from the Registry :

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

const uiSchema: UiSchema = {
  'ui:ArrayFieldTemplate': 'CustomArrayFieldTemplate',
};

Please see the customArray.tsx sample from the playground for another example.

The following props are passed to each ArrayFieldTemplate:

  • 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.
  • fieldPathId: An object containing the id for this object & ids for its properties.
  • items: An array of React nodes representing the items in the array.
  • onAddClick: (event?) => void: A function that adds a new item to the end of the array.
  • readonly: A boolean value stating if the array is read-only.
  • required: A boolean value stating if the array is required.
  • hideError: A boolean value stating if the field is hiding its errors.
  • 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.
  • formData: The formData for this array.
  • errorSchema: The optional validation errors for the array field and the items within it, in the form of an ErrorSchema
  • rawErrors: An array of strings listing all generated error messages from encountered errors for this widget
  • registry: The registry object.

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

ArrayFieldDescriptionTemplate

The out-of-the-box version of this template will render the DescriptionFieldTemplate with a generated id, if there is a description otherwise nothing is rendered.
If you want different behavior for the rendering of the description of an array field, you can customize this template.
If you want a different behavior for the rendering of ALL descriptions in the Form, see DescriptionFieldTemplate

tsx
import { ArrayFieldDescriptionProps, RJSFSchema, descriptionId } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

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

function ArrayFieldDescriptionTemplate(props: ArrayFieldDescriptionProps) {
  const { description, fieldPathId } = props;
  const id = descriptionId(fieldPathId);
  return (
    <details id={id}>
      <summary>Description</summary>
      {description}
    </details>
  );
}

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

You also can provide your own field template to a uiSchema by specifying a ui:ArrayFieldDescriptionTemplate property with your Component :

tsx
import { UiSchema } from '@rjsf/utils';
import ArrayFieldDescriptionTemplate from './ArrayFieldDescriptionTemplate';

const uiSchema: UiSchema = {
  'ui:ArrayFieldDescriptionTemplate': ArrayFieldDescriptionTemplate,
};

or a string value from the Registry :

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

const uiSchema: UiSchema = {
  'ui:ArrayFieldDescriptionTemplate': 'CustomArrayFieldDescriptionTemplate',
};

The following props are passed to each ArrayFieldDescriptionTemplate:

  • description: The description of the array field being rendered.
  • fieldPathId: The FieldPathId of the field in the hierarchy
  • schema: The schema object for this array field.
  • uiSchema: The uiSchema object for this array field.
  • registry: The registry object.

ArrayFieldItemTemplate

The ArrayFieldItemTemplate is used to render the representation of a single item in an array.
All of the ArrayFieldTemplate implementations in all themes get this template from the registry in order to render array fields items.
Each theme has an implementation of the ArrayFieldItemTemplate to render an array field item in a manner best suited to the theme.
If you want to change how an array field item is rendered you can customize this template (for instance to remove the buttons rendered by ArrayFieldItemButtonsTemplate).

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

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

function ArrayFieldItemTemplate(props: ArrayFieldItemTemplateProps) {
  const { children, className } = props;
  return <div className={className}>{children}</div>;
}

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

The following props are passed to each ArrayFieldItemTemplate:

  • children: The html for the item's content.
  • buttonsProps: The props to pass to the ArrayFieldItemButtonTemplate.
  • className: The className string.
  • disabled: A boolean value stating if the array item is disabled.
  • hasToolbar: A boolean value stating whether the array item has a toolbar.
  • index: A number stating the index the array item occurs in items.
  • totalItems: A number stating the total number items in the array.
  • itemKey: A stable, unique key for the array item.
  • readonly: A boolean value stating if the array item is read-only.
  • schema: The schema object for this array item.
  • uiSchema: The uiSchema object for this array item.
  • registry: The registry object.
  • parentUiSchema: The UI schema of the array item's parent array field, used for customization in some themes

ArrayFieldItemButtonTemplate

The ArrayFieldItemButtonTemplate is used to render the representation of the buttons used for copying, moving and deleting an item in an array.
All of the ArrayFieldItemTemplate implementations in all themes get this template from the registry in order to render array fields items' buttons.
Currently, only the core them has an implementation of this template as the button rendering is identical across all themes.
If you want to change how an array field item's buttons are rendered you can customize this template (for instance to remove the move up/down and remove buttons).

tsx
import { useMemo } from 'react';
import { ArrayFieldTemplateItemButtonsType, buttonId, RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

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

function ArrayFieldItemButtonsTemplate(props: ArrayFieldTemplateItemButtonsType) {
  const { disabled, readonly, hasCopy, fieldPathId, index, onCopyIndexClick, registry, uiSchema } = props;
  const { CopyButton } = registry.templates.ButtonTemplates;
  const onCopyClick = useMemo(() => onCopyIndexClick(index), [index, onCopyIndexClick]);
  if (!hasCopy) {
    return undefined;
  }
  return (
    <CopyButton
      id={buttonId(fieldPathId, 'copy')}
      className='array-item-copy'
      disabled={disabled || readonly}
      onClick={onCopyClick}
      uiSchema={uiSchema}
      registry={registry}
    />
  );
}

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

The following props are passed to each ArrayFieldItemButtonsTemplate:

  • className: The className string.
  • disabled: A boolean value stating if the array item is disabled.
  • canAdd: A boolean value stating whether new elements can be added to the array.
  • hasCopy: A boolean value stating whether the array item can be copied.
  • 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.
  • fieldPathId: The FieldPathId of the field in the hierarchy.
  • index: A number stating the index the array item occurs in items.
  • totalItems: A number stating the total number items in the array.
  • onAddItem: event?) => void: Callback function that adds a new item below this item.
  • onCopyItem: (event?) => void: Callback function that copies this item below itself.
  • onRemoveItem: (event?) => void: Callback function that removes the item from the list.
  • onMoveUpItem: (event?) => void: Callback function that moves the item up one spot in the list
  • onMoveDownItem: (event?) => void: Callback function that moves the item down one spot in the list
  • readonly: A boolean value stating if the array item is read-only.
  • schema: The schema object for this array item.
  • style: The optional style to pass to all of the buttons
  • uiSchema: The uiSchema object for this array item.
  • registry: The registry object.

ArrayFieldTitleTemplate

The out-of-the-box version of this template will render the TitleFieldTemplate with a generated id, if there is a title otherwise nothing is rendered.
If you want a different behavior for the rendering of the title of an array field, you can customize this template.
If you want a different behavior for the rendering of ALL titles in the Form, see TitleFieldTemplate

tsx
import { ArrayFieldTitleTemplateProps, RJSFSchema, titleId } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

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

function ArrayFieldTitleTemplate(props: ArrayFieldTitleProps) {
  const { title, fieldPathId } = props;
  const id = titleId(fieldPathId);
  return <h1 id={id}>{title}</h1>;
}

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

You also can provide your own template to a uiSchema by specifying a ui:ArrayFieldDescriptionTemplate property with your Component :

tsx
import { UiSchema } from '@rjsf/utils';
import ArrayFieldDescriptionTemplate from './ArrayFieldDescriptionTemplate';

const uiSchema: UiSchema = {
  'ui:ArrayFieldDescriptionTemplate': ArrayFieldDescriptionTemplate,
};

or a string value from the Registry :

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

const uiSchema: UiSchema = {
  'ui:ArrayFieldDescriptionTemplate': 'CustomArrayFieldDescriptionTemplate',
};

The following props are passed to each ArrayFieldTitleTemplate:

  • title: The title of the array field being rendered.
  • fieldPathId: The FieldPathId of the field in the hierarchy.
  • schema: The schema object for this array field.
  • uiSchema: The uiSchema object for this array field.
  • required: A boolean value stating if the field is required
  • registry: The registry object.

BaseInputTemplate

The BaseInputTemplate is the template to use to render the basic component for a theme. It is used as the template for rendering many of the based widgets that differ by type and callbacks only.
For example, the TextWidget implementation in core is simply a wrapper around BaseInputTemplate that it gets from the registry.
Additionally, each theme implements its own version of BaseInputTemplate without needing to provide a different implementation of TextWidget.

If you desire a different implementation for the `` based widgets, you can customize this template.
For instance, say you have a CustomTextInput component that you want to integrate:

text
/* Detailed source-code truncated for AI context efficiency. */

Wrapping BaseInputTemplate to customize it

Sometimes you just need to pass some additional properties to the existing BaseInputTemplate.
The way to do this varies based upon whether you are using core or some other theme (such as mui):

tsx
import { BaseInputTemplateProps } from '@rjsf/utils';
import { getDefaultRegistry } from '@rjsf/core';
import { Templates } from '@rjsf/mui';

const {
  templates: { BaseInputTemplate },
} = getDefaultRegistry(); // To get templates from core
// const { BaseInputTemplate } = Templates; // To get templates from a theme do this

function MyBaseInputTemplate(props: BaseInputTemplateProps) {
  const customProps = {};
  // get your custom props from where you need to
  return <BaseInputTemplate {...props} {...customProps} />;
}

The following props are passed to the BaseInputTemplate:

  • 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 widget, if any;
  • required: The required status of this widget;
  • disabled: A boolean value stating if the widget is disabled;
  • hideError: A boolean value stating if the widget is hiding its errors.
  • readonly: A boolean value stating if the widget is read-only;
  • autofocus: A boolean value stating if the widget should autofocus;
  • label: The computed label for this widget, as a string
  • multiple: A boolean value stating if the widget can accept multiple values;
  • onChange: The value change event handler; call it with the new value every time it changes;
  • onChangeOverride: A BaseInputTemplate implements a default onChange handler that it passes to the HTML input component to handle the ChangeEvent. Sometimes a widget may need to handle the ChangeEvent using custom logic. If that is the case, that widget should provide its own handler via this prop;
  • onKeyChange: The key change event handler (only called for fields with additionalProperties and patternProperties); pass the new value every time it changes;
  • onBlur: The input blur event handler; call it with the widget id and value;
  • onFocus: The input focus event handler; call it with 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.
  • rawErrors: An array of strings listing all generated error messages from encountered errors for this widget.
  • registry: The registry object

CyclicSchemaExpandTemplate

The CyclicSchemaExpandTemplate is the template rendered by CyclicSchemaField when a circular $ref cycle is detected in the schema.
RJSF automatically detects when a $ref would recurse indefinitely (e.g. a schema whose property references its own root) and stops rendering at the cycle boundary.
At that point CyclicSchemaField renders this template, which shows a warning message and an expand button that the user can click to render one additional level of the recursive structure.

Each theme provides its own implementation.
You can replace the template globally via the templates prop on Form, or per-field via ui:CyclicSchemaExpandTemplate in the uiSchema.

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

// A schema that is self-referencing
const schema: RJSFSchema = {
  $schema: 'http://json-schema.org/draft-07/schema#',
  type: 'object',
  title: 'Node',
  properties: {
    value: { type: 'string' },
    child: { $ref: '#' },
  },
};

function CyclicSchemaExpandTemplate<T = any>(props: CyclicSchemaExpandProps<T>) {
  const { name, fieldPathId, onExpand } = props;
  const buttonId = `${fieldPathId.$id}-button`;
  return (
    <div className='cyclic-expand'>
      <span className='warning'>Circular reference detected for field &quot;{name}&quot;</span>
      <button id={buttonId} type='button' onClick={() => onExpand(fieldPathId.$id)}>
        Expand
      </button>
    </div>
  );
}

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

You can also provide a per-field template via uiSchema:

tsx
import { UiSchema } from '@rjsf/utils';
import CyclicSchemaExpandTemplate from './CyclicSchemaExpandTemplate';

const uiSchema: UiSchema = {
  'ui:CyclicSchemaExpandTemplate': CyclicSchemaExpandTemplate,
};

or a string value from the Registry:

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

const uiSchema: UiSchema = {
  'ui:CyclicSchemaExpandTemplate': 'CustomCyclicSchemaExpandTemplate',
};

The following props are passed to the CyclicSchemaExpandTemplate as defined by CyclicSchemaExpandProps in @rjsf/utils:

  • name: The unique name of the field at the cycle boundary, usually the property name within its parent object.
  • fieldPathId: The FieldPathId of the field in the hierarchy; use fieldPathId.$id to get the HTML id string.
  • onExpand: Callback to call when the user wants to render one additional level; receives the field's id string.
  • schema: The schema object for the field at the cycle boundary.
  • uiSchema: The uiSchema object for this field.
  • registry: The registry object.

DescriptionFieldTemplate

Each theme implements a DescriptionFieldTemplate used to render the description of a field.
If you want to customize how descriptions are rendered you can.

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

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

function DescriptionFieldTemplate(props: DescriptionFieldProps) {
  const { description, id } = props;
  return (
    <details id={id}>
      <summary>Description</summary>
      {description}
    </details>
  );
}

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

The following props are passed to the DescriptionFieldTemplate:

  • description: The description of the field being rendered.
  • id: The id of the field in the hierarchy.
  • schema: The schema object for the field.
  • uiSchema: The uiSchema object for the field.
  • registry: The registry object.

ErrorListTemplate

The ErrorListTemplate is the template that renders the all the errors associated with the fields in the Form, at the top.
Each theme implements a ErrorListTemplate used to render its errors using components for the theme's toolkit.
If you want to customize how all the errors are rendered you can.

tsx
import { ErrorListProps, RJSFValidationError, RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

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

function ErrorListTemplate(props: ErrorListProps) {
  const { errors } = props;
  return (
    <details id={id}>
      <summary>Errors</summary>
      <ul>
        {errors.map((error: RJSFValidationError, i: number) => {
          return (
            <li key={i} className='error'>
              {error.stack}
            </li>
          );
        })}
      </ul>
    </details>
  );
}

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

The following props are passed to the ErrorListTemplate:

  • schema: The schema that was passed to Form
  • uiSchema: The uiSchema that was passed to Form
  • errors: An array of all errors in this Form.
  • errorSchema: The ErrorSchema constructed by Form

FallbackFieldTemplate

The FallbackFieldTemplate is the template that renders opt-in fallback UI to control fields of unknown or unhandled types. Usage of this feature is controlled by the useFallbackUiForUnsupportedType Form prop.

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

const schema: RJSFSchema = {
  type: 'unknownType',
  title: 'My input',
};

function FallbackFieldTemplate(props: FallbackFieldTemplateProps) {
  const { typeSelector, schemaField } = props;
  return (
    <div className={'row'}>
      <div className={'col-xs-4'}>{typeSelector}</div>
      <div className={'col-xs-8'}>{schemaField}</div>
    </div>
  );
}

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

The following props are passed to the FallbackFieldTemplate:

  • schema: The schema for the field
  • uiSchema: The uiSchema for the field
  • registry: The Registry object
    1

FieldErrorTemplate

The FieldErrorTemplate is the template that renders all the errors associated a single field.
If you want to customize how the errors are rendered you can.

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

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

function FieldErrorTemplate(props: FieldErrorProps) {
  const { errors } = props;
  return (
    <details id={id}>
      <summary>Errors</summary>
      <ul>
        {errors.map((error: string, i: number) => {
          return (
            <li key={i} className='error'>
              {error.stack}
            </li>
          );
        })}
      </ul>
    </details>
  );
}

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

The following props are passed to the FieldErrorTemplate:

  • schema: The schema for the field
  • uiSchema: The uiSchema for the field
  • fieldPathId: The FieldPathId of the field in the hierarchy
  • errors: An array of all errors for this field
  • errorSchema: The ErrorSchema for this field
  • registry: The Registry object

FieldHelpTemplate

The FieldHelpTemplate is the template that renders the help associated a single field.
If you want to customize how the help is rendered you can.

tsx
import { FieldHelpProps, RJSFSchema, helpId } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

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

function FieldHelpTemplate(props: FieldHelpProps) {
  const { help, fieldPathId } = props;
  const id = helpId(fieldPathId);
  return <aside id={id}>{help}</aside>;
}

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

The following props are passed to the FieldHelpTemplate:

  • schema: The schema for the field
  • uiSchema: The uiSchema for the field
  • fieldPathId: The FieldPathId of the field in the hierarchy
  • help: The help information to be rendered
  • registry: The Registry object

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.

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

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

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

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

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

tsx
import { UiSchema } from '@rjsf/utils';
import CustomFieldTemplate from './CustomFieldTemplate';

const uiSchema: UiSchema = {
  'ui:FieldTemplate': CustomFieldTemplate,
};

or a string value from the Registry :

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

const uiSchema: 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.
  • style: An object containing the StyleHTMLAttributes defined in the 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 DescriptionFieldTemplate defined in the templates passed to the Form).
  • 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.
  • 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.
  • 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".

GridTemplate

The GridTemplate is the template that renders a theme dependent Grid for either a row or column.
While it has only two explicit properties, it extends the GenericObjectTemplate in order to support passing any of the properties associated with a Grid implementation for any theme.
If you want to customize how grids are rendered you can.

tsx
import { Grid2 } from '@mui/material';
import { GridTemplateProps } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';
import classNames from 'classnames';

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

function GridTemplate(props: FieldHelpProps) {
  const { children, column, className, ...rest } = props;
  return (
    <Grid2 item={column} {...rest} className={`${className} my-custom-grid-styling`}>
      {children}
    </Grid2>
  );
}

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

The following props are passed to the GridTemplate:

  • children: The contents of the grid template
  • column: Optional flag indicating whether the grid element represents a column, necessary for themes which have components for Rows vs Column

MultiSchemaFieldTemplate

Each theme implements a MultiSchemaFieldTemplate used to render the layout of a MultiSchemaField, i.e. a field described by a oneOf or anyOf schema.
The template typically renders a Widget used to select the schema to use, as well as a field for the selected schema.

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

const schema: RJSFSchema = {
  type: 'object',
  properties: {
    myField: {
      oneOf: [
        {
          type: 'string',
          title: 'String Field',
          description: 'A field that accepts a string',
        },
        {
          type: 'number',
          title: 'Number Field',
          description: 'A field that accepts a number',
        },
      ],
    },
  },
};

function MultiSchemaFieldTemplate(props: MultiSchemaFieldTemplateProps) {
  const { selector, optionSchemaField } = props;
  return (
    <div className='my-multi-schema-field-class'>
      {selector}
      <hr />
      {optionSchemaField}
    </div>
  );
}

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

The following props are passed to the MultiSchemaFieldTemplate:

  • selector: The rendered Widget used to select a multischema option.
  • optionSchemaField: The rendered SchemaField representing the selected option.
  • schema: The schema object for the field.
  • uiSchema: The uiSchema object for the field.
  • registry: The registry object.

ObjectFieldTemplate

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

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

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

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

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

tsx
import { UiSchema } from '@rjsf/utils';
import ObjectFieldTemplate from './ObjectFieldTemplate';

const uiSchema: UiSchema = {
  'ui:ObjectFieldTemplate': ObjectFieldTemplate,
};

or a string value from the Registry :

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

const uiSchema: UiSchema = {
  'ui:ObjectFieldTemplate': 'ObjectFieldTemplate',
};

Please see the customObject.tsx sample from the playground for a better example.

The following props are passed to each ObjectFieldTemplate as defined by the ObjectFieldTemplateProps in @rjsf/utils:

  • 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 object. Each of the properties represent a child with properties described below.
  • onAddProperty: () => void: Callback to use in order to add an new additionalProperty to the object field (to be used with additionalProperties and patternProperties)
  • readonly: A boolean value stating if the object is read-only.
  • required: A boolean value stating if the object is required.
  • hideError: A boolean value stating if the field is hiding its errors.
  • schema: The schema object for this object.
  • uiSchema: The uiSchema object for this object field.
  • fieldPathId: The FieldPathId of the field in the hierarchy
  • errorSchema: The optional validation errors in the form of an ErrorSchema
  • formData: The form data for the object.
  • 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 the FieldTemplate. To fully customize an object field template, you may need to specify both ui:FieldTemplate and ui:ObjectFieldTemplate.

OptionalDataControlsTemplate

Each theme implements a OptionalDataControlsTemplate used to render the Optional Data Controls when that feature has been enabled

text
/* Detailed source-code truncated for AI context efficiency. */

The following props are passed to each OptionalDataControlsTemplate as defined by the OptionalDataControlsTemplateProps in @rjsf/utils:

  • id: The generated id for this Optional Data Control instance.
  • label: The label to use for the Optional Data Control
  • onAddClick: Optional callback to call when clicking on the Optional Data Control to add data
  • onRemoveClick: Optional callback to call when clicking on the Optional Data Control to remove data
  • schema: The schema object for this object.
  • uiSchema: The uiSchema object for this object field.
  • registry: The registry object.

TitleFieldTemplate

Each theme implements a TitleFieldTemplate used to render the title of a field.
If you want to customize how titles are rendered you can.

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

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

function TitleFieldTemplate(props: TitleFieldProps) {
  const { id, required, title } = props;
  return (
    <header id={id}>
      {title}
      {required && <mark>*</mark>}
    </header>
  );
}

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

The following props are passed to each TitleFieldTemplate:

  • id: The id of the field in the hierarchy.
  • title: The title of the field being rendered.
  • schema: The schema object for the field.
  • uiSchema: The uiSchema object for the field.
  • required: A boolean value stating if the field is required
  • registry: The registry object.

UnsupportedFieldTemplate

The UnsupportedField component is used to render a field in the schema is one that is not supported by react-jsonschema-form.
If you want to customize how an unsupported field is rendered (perhaps for localization purposes) you can.

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

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

function UnsupportedFieldTemplate(props: UnsupportedFieldProps) {
  const { schema, reason } = props;
  return (
    <div>
      <FormattedMessage defaultMessage='Unsupported field schema, reason = {reason}' value={{ reason }} />
      <pre>{JSON.stringify(schema, null, 2)}</pre>
    </div>
  );
}

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

The following props are passed to each UnsupportedFieldTemplate:

  • schema: The schema object for this unsupported field.
  • fieldPathId: The FieldPathId of the field in the hierarchy
  • reason: The reason why the schema field has an unsupported type.
  • registry: The registry object.

WrapIfAdditionalTemplate

The WrapIfAdditionalTemplate is used by the FieldTemplate to conditionally render additional controls if additionalProperties or patternProperties are present in the schema.
You may customize WrapIfAdditionalTemplate if you wish to change the layout or behavior of user-controlled additionalProperties and patternProperties.

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

const schema: RJSFSchema = {
  type: 'object',
  additionalProperties: true,
};

function WrapIfAdditionalTemplate(props: WrapIfAdditionalTemplateProps) {
  const {
    id,
    label,
    onKeyRename,
    onKeyRenameBlur,
    onRemoveProperty,
    schema,
    children,
    uiSchema,
    registry,
    classNames,
    style,
  } = props;
  const { RemoveButton } = registry.templates.ButtonTemplates;
  const additional = ADDITIONAL_PROPERTY_FLAG in schema;

  if (!additional) {
    return <div>{children}</div>;
  }

  return (
    <div className={classNames} style={style}>
      <label label={keyLabel} id={`${id}-key`}>
        Custom Field Key
      </label>
      <input className='form-control' type='text' id={`${id}-key`} onBlur={onKeyRenameBlur} defaultValue={label} />
      <div>{children}</div>
      <RemoveButton onClick={onRemoveProperty} uiSchema={uiSchema} />
    </div>
  );
}

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

The following props are passed to the WrapIfAdditionalTemplate:

  • children: The children of the component, typically specified by the FieldTemplate.

  • 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.

  • style: An object containing the StyleHTMLAttributes defined in the uiSchema.

  • label: The computed label for this field, as a string.

  • 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.

  • schema: The schema object for this field.

  • uiSchema: The uiSchema object for this field.

  • onKeyRename: Callback used to handle the changing of an additional property key's name with the new value

  • onKeyRenameBlur: Callback used to handle the changing of an additional property key's name when the input is blurred. The event's target's value will be used as the new value. Its a wrapper callback around onKeyRename

  • onRemoveProperty: Callback used to handle the removal of the additionalProperty

ButtonTemplates

There are several buttons that are potentially rendered in the Form.
Each of these buttons have been customized in the themes, and can be customized by you as well.
All but one of these buttons (i.e. the SubmitButton) are rendered currently as icons with title text for a description.

Each button template (except for the SubmitButton) accepts, as props, the standard HTML button attributes along with the following:

  • iconType: An alternative specification for the type of the icon button.
  • icon: The name representation or actual react element implementation for the icon.
  • uiSchema: The uiSchema object for this field.
  • registry: The registry object.

AddButton

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

tsx
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 AddButton(props: IconButtonProps) {
  const { icon, iconType, ...btnProps } = props;
  return (
    <button {...btnProps}>
      {icon} <FormattedMessage defaultMessage='Add' />
    </button>
  );
}

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

MoveDownButton

The MoveDownButton is used to render a move down action on a Form for elements in an array.
You can customize the MoveDownButton to render something other than the icon button that is provided by a theme as follows:

tsx
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 MoveDownButton(props: IconButtonProps) {
  const { icon, iconType, ...btnProps } = props;
  return (
    <button {...btnProps}>
      {icon} <FormattedMessage defaultMessage='Move Down' />
    </button>
  );
}

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

MoveUpButton

The MoveUpButton is used to render a move up action on a Form for elements in an array.
You can customize the MoveUpButton to render something other than the icon button that is provided by a theme as follows:

tsx
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 or patternProperties 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:

tsx
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.

tsx
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:

  • uiSchema: The uiSchema object for this field, used to extract the UISchemaSubmitButtonOptions.
  • registry: The registry object.

Custom Templates

You can now add custom components to the registry and reference them in your uiSchema using string keys.

Adding Custom Templates to the Registry

tsx
import CustomArrayFieldTemplate from './CustomArrayFieldTemplate';
import { UiSchema } from '@rjsf/utils';

// Add the custom template to the registry
const registry = { templates: { CustomArrayFieldTemplate } };

// Use the custom template in the uiSchema
const uiSchema: UiSchema = { 'ui:ArrayFieldTemplate': 'CustomArrayFieldTemplate' };

Packages Docs Docs Advanced Customization Custom Themes (`packages/docs/docs/advanced-customization/custom-themes.md`)

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

tsx
import React, { Component } from 'react';
import validator from '@rjsf/validator-ajv8';
import { withTheme, ThemeProps } from '@rjsf/core';

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

const ThemedForm = withTheme(theme);

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

Theme object properties

The Theme object consists of the same properties as the rjsf Form component (such as widgets, fields and templates).
The themed-Form component merges together any theme-specific widgets, fields and templates with the default widgets, fields and templates.
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, 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:

tsx
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:

tsx
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.

tsx
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).


Packages Docs Docs Advanced Customization Custom Widgets Fields (`packages/docs/docs/advanced-customization/custom-widgets-fields.md`)

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 BooleanField
renders for boolean values. You can override any field and widget just by providing the customized fields/widgets in the
fields and widgets props:

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

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

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

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

const widgets: RegistryWidgetsType = {
  CheckboxWidget: CustomCheckbox,
};

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

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

tsx
import { RegistryFieldsType, RegistryWidgetsType } from '@rjsf/utils';
import { FormProps } from '@rjsf/core';

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

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

The default fields you can override are:

  • ArrayField
  • ArraySchemaField
  • BooleanField
  • DescriptionField
  • OneOfField
  • AnyOfField
  • LayoutGridField
  • LayoutMultiSchemaField
  • LayoutHeaderField
  • NullField
  • NumberField
  • ObjectField
  • SchemaField
  • StringField
  • TitleField
  • UnsupportedField
  • FallbackField
  • CyclicSchemaField

The default widgets you can override are:

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

Raising errors from within a custom widget or field

You can raise custom 'live validation' errors by overriding the onChange method to provide feedback while users are actively changing the form data.
If you do set errors this way, you must also clear them this way by passing undefined to the onChange() for the errorSchema parameter.

:::warning

While these errors are retained during validation, it is still preferred for you to use the customValidate Form prop mechanism instead.

:::

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

const schema: RJSFSchema = {
  type: 'text',
  default: 'hello',
};

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

const CustomTextWidget = function (props: WidgetProps) {
  const { id, value } = props;
  const raiseErrorOnChange = ({ target: { value } }: ChangeEvent<HTMLInputElement>) => {
    let raiseError: ErrorSchema | undefined;
    if (value !== 'test') {
      raiseError = {
        __errors: ['Value must be "test"'],
      };
    }
    props.onChange(value, [], raiseError, id);
  };

  return <input id={id} onChange={raiseErrorOnChange} value={value || ''} />;
};

const widgets: RegistryWidgetsType = {
  TextWidget: CustomTextWidget,
};

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

This creates a custom text widget that raises an error if the input value does not match 'test'.

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
tsx
import { RJSFSchema, UiSchema, WidgetProps } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

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

const uiSchema: UiSchema = {
  'ui:widget': (props: WidgetProps) => {
    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} validator={validator} />, document.getElementById('app'));

The following props are passed to custom widget components:

  • id: The generated id for this widget, used to provide unique names and ids for the HTML field elements rendered by widgets;
  • name: The unique name of the field, usually derived from the name of the property in the JSONSchema; Provided in support of custom widgets;
  • 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 widget, if any;
  • required: The required status of this widget;
  • disabled: A boolean value stating if the widget is disabled;
  • readonly: A boolean value stating if the widget is read-only;
  • autofocus: A boolean value stating if the widget should autofocus;
  • label: The computed label for this widget, as a string
  • hideLabel: A boolean value, if true, will cause the label to be hidden. This is useful for nested fields where you don't want to clutter the UI. Customized via label in the UiSchema;
  • multiple: A boolean value stating if the widget can accept multiple values;
  • 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 widget id and value;
  • onFocus: The input focus event handler; call it with 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.
  • 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:

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

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

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

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

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

render(
  <Form schema={schema} uiSchema={uiSchema} validator={validator} 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:

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

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

function MyCustomWidget(props: WidgetProps) {
  const { options } = props;
  const { color, backgroundColor } = options;
  return <input style={{ color, backgroundColor }} />;
}

MyCustomWidget.defaultProps = {
  options: {
    color: 'red',
  },
};

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

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

Note: This also applies to registered custom components.

Customizing widgets' text input

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

Wrapping an existing widget to customize it

Sometimes you just need to customize the properties that are passed to an existing widget.
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:

tsx
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:

tsx
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:

  • schema: The JSON subschema object for this field;
  • uiSchema: The uiSchema for this field;
  • idSchema: The FieldPathId of the field in the hierarchy
  • formData: The data for this field;
  • errorSchema: The tree of errors for this field and its children;
  • registry: A registry object (read next).
  • required: The required status of this field;
  • disabled: A boolean value stating if the field is disabled;
  • readonly: A boolean value stating if the field is read-only;
  • autofocus: A boolean value stating if the field should autofocus;
  • name: The unique name of the field, usually derived from the name of the property in the JSONSchema
  • rawErrors: `An array of strings listing all generated error messages from encountered errors for this field
  • onChange: The field change event handler; called with the updated field value, the optional change path for the value (defaults to an empty array), an optional ErrorSchema and the optional id of the field being changed
  • onBlur: The input blur event handler; call it with the field id and value;
  • onFocus: The input focus event handler; call it with the field id and value;

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.

  • fields: The set of all fields used by the Form. Includes fields from core, theme-specific fields and any custom registered fields;
  • widgets: The set of all widgets used by the Form. Includes widgets from core, theme-specific widgets and any custom registered widgets, if any;
  • templates: The set of templates used by the Form. Includes templates from core, theme-specific templates and any custom registered templates
  • rootSchema: The root schema, as passed to the Form, which can contain referenced definitions;
  • schemaUtils: The current implementation of the SchemaUtilsType (from @rjsf/utils) in use by the Form. Used to call any of the validation-schema-based utility functions.
  • translateString: The string translation function to use when displaying any of the RJSF strings in templates, fields or widgets
  • globalFormOptions: The global Form Options that are available for all templates, fields and widgets to access
  • globalUiOptions: The optional global UI Options that are available for all templates, fields and widgets to access

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:

tsx
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.

tsx
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:

tsx
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:

tsx
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, path: (number | string)[], es?: ErrorSchema<T>, id?: string) => {
      let data = newFormData;
      let error = es;
      if (checkBadData(newFormData)) {
        // Format the `error` and fix the `data` here
      }
      onChange(data, path, error, id);
    },
    [onChange],
  );
  return <ObjectField {...props} onChange={onChangeHandler} />;
}

Packages Docs Docs Advanced Customization Internals (`packages/docs/docs/advanced-customization/internals.md`)

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 @x0k/json-schema-merge 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.

A boolean property that is listed in its parent's required array and has no default of its own is populated with false. You can turn this off using the experimental requiredBooleanDefault flag, so that the property stays undefined until the user answers it.

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 (descendant) default taking precedence for any overlapping properties by default. You can change this behavior using the experimental nestedDefaultsPrecedence flag. 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

css
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.

tsx
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();

Update field value in form programmatically

You can use the reference to get your Form component and call the setFieldValue(fieldPath: string | FieldPathList, newValue?: T): void method to change the value of a field.
This method will dispatch the onChange event of the form.

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

const onChange = ({ formData }) => console.log('Data updated to: ', formData);
let yourForm;

const schema: RJSFSchema = {
  type: 'object',
  properties: {
    foo: {
      type: 'object',
      required: ['input'],
      properties: {
        input: {
          type: 'string',
        },
      },
    },
  },
  required: ['foo'],
};

const formRef = createRef<Form>();

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

formRef.current.setFieldValue('foo.input', 'value');
formRef.current.setFieldValue(['foo'], { input: 'newvalue' });
formRef.current.setFieldValue('', { foo: { input: 'another value' } });
formRef.current.setFieldValue([], { foo: { input: 'more values' } });

Packages Docs Docs Advanced Customization Typescript (`packages/docs/docs/advanced-customization/typescript.md`)

Typescript Support

RJSF fully supports Typescript.
The types and functions exported by @rjsf/utils are fully typed (as needed) using one or more of the following 3 optional generics:

  • T = any: This represents the type of the formData and defaults to any.
  • S extends StrictRJSFSchema = RJSFSchema: This represents the type of the schema and extends the StrictRJSFSchema type and defaults to the RJSFSchema type.
  • F extends FormContextType = any: This represents the type of the formContext, extends the FormContextType type and defaults to any.

Every other library in the @rjsf/* ecosystem use these same generics in their functions and React component definitions.
For instance, in the @rjsf/core library the definitions of the Form component and the withTheme() and getDefaultRegistry() functions are as follows:

ts
export default class Form<
  T = any,
  S extends StrictRJSFSchema = RJSFSchema,
  F extends FormContextType = any
> extends Component<FormProps<T, S, F>, FormState<T, S, F>> {
  // ... class implementation
}

export default function withTheme<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(
  themeProps: ThemeProps<T, S, F>
) {
  // ... function implementation
}

export default function getDefaultRegistry<
  T = any,
  S extends StrictRJSFSchema = RJSFSchema,
  F extends FormContextType = any
>(): Omit<Registry<T, S, F>, 'schemaUtils'> {
  // ... function implementation
}

Out of the box, the defaults for these generics will work for all use-cases.
Providing custom types for any of these generics may be useful for situations where the caller is working with typed formData, schema or formContext props, Typescript is complaining and type casting isn't allowed.

Overriding generics

T

The generic T is used to represent the type of the formData property passed into Form.
If you are working with a simple, unchanging JSON Schema and you have defined a type for the formData you are working with, you can override this generic as follows:

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

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

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

const formData: FormData = {};

const validator = customizeValidator<FormData>();

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

S

The generic S is used to represent the type of the schema property passed into Form.
If you are using something like the Ajv utility types for schemas typing system, you can override this generic as follows:

tsx
import { JSONSchemaType } from 'ajv';
import { RJSFSchema } from '@rjsf/utils';
import { customizeValidator } from '@rjsf/validator-ajv8';
import { Form } 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' },
  },
};

const validator = customizeValidator<any, MySchema>();

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

// Alternatively since you have the type, you could also use this
// const validator = customizeValidator<FormData, MySchema>();
// render((
//  <Form<FormData, MySchema> schema={schema} validator={validator} />
//), document.getElementById("app"));

NOTE: using this Ajv typing system has not been tested extensively with RJSF, so use carefully

F

The generic F is used to represent the type of the formContext property passed into Form.
If you have a type for this data, you can override this generic as follows:

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

interface FormContext {
  myCustomWidgetData: object;
}

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

const formContext: FormContext = {
  myCustomWidgetData: {
    enableCustomFeature: true,
  },
};

const validator = customizeValidator<any, RJSFSchema, FormContext>();

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

Overriding generics in core

As shown in previous examples, overriding the default Form from @rjsf/core is pretty straight forward.
Using the withTheme() function is just as easy:

tsx
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:

tsx
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:

tsx
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.


Packages Docs Docs Api Reference LayoutGridField (`packages/docs/docs/api-reference/LayoutGridField.md`)

LayoutGridField

The LayoutGridField will render a schema, uiSchema and formData combination out into a GridTemplate in the shape
described in the uiSchema. To define the grid to use to render the elements within a field in the schema, provide in
the uiSchema for that field the object contained under a ui:layoutGrid element. E.g. (as a JSON object):

json
{
  "field1" : {
    "ui:field": "LayoutGridField",
    "ui:layoutGrid": {
      "ui:row": { ... }
    }
  }
}

See the LayoutGridField usage for more detailed walk-through on how to use the component. This page is condensed
version of the uiSchema APIs for faster reference.

`ui:row`

The outermost level of a LayoutGridField is the ui:row that defines the nested rows, columns, and/or condition
elements (i.e. "grid elements") in the grid. This definition is either a simple "grid elements" OR an object with
native GridTemplate implementation-specific props and a children array of "grid elements". E.g. (as JSON objects):

Simple ui:row definition, without additional GridTemplate props:

json
{
  "ui:row": [
    { "ui:row"|"ui:col"|"ui:columns"|"ui:condition": ... },
    ...
  ]
}

Complex ui:row definition, with additional GridTemplate (this example uses @mui/material/Grid2 native props):

json
{
  "ui:row": {
    "spacing": 2,
    "size": {
      "md": 4
    },
    "alignContent": "flex-start",
    "className": "GridRow",
    "children": [
        {
          "ui:row"|"ui:col"|"ui:columns"|"ui:condition": ...
        },
        ...
      ]
    }
  }

NOTE: Special note about the native className prop values. All className values will automatically be looked up in
the formContext.lookupMap in case they have been defined using a CSS-in-JS approach. In other words, from the
example above, if the Form was constructed with a layoutGridLookupMap set to { GridRow: cssInJs.GridRowClass }
then when rendered, the native GridTemplate will get the className with the value from
cssInJs.GridRowClass. This automatic lookup will happen for any of the "grid elements" when rendering with
GridTemplate props. If multiple className values are present, for example:
{ className: 'GridRow GridColumn' }, the classNames are split apart, looked up individually, and joined
together to form one className with the values from cssInJs.GridRowClass and cssInJs.GridColumnClass. See the
example in the usage documentation.

`ui:col`

The ui:col grid element is used to specify the list of columns within a grid row. A ui:col element can take on
several forms:

  1. a simple list of dotted-path field names within the root field;
  2. a list of objects containing the dotted-path field name any other props that are gathered into ui:options for the field;
  3. a list with a one-off render functional component with or without a non-field name identifier and any other to-be-spread props; and
  4. an object with native GridTemplate implementation specific props and a children array with 1) or 2) or even a nested ui:row or a ui:condition containing a ui:row (although this should be used carefully). E.g. (as JSON objects):

Simple ui:col definition, without additional GridTemplate props and form 1 only children:

json
{
  "ui:col": ["innerField", "inner.grandChild", ...]
}

Complicated ui:col definition, without additional GridTemplate props and form 2 only children:

json
{
  "ui:col": [
    { "name": "innerField", "fullWidth": true },
    { "name": "inner.grandChild", "fullWidth": false },
    ...
  ]
}

More complicated ui:col definition, without additional GridTemplate props and form 2 children, one being a
one-off render functional component without a non-field name identifier

json
{
  "ui:col": [
    "innerField",
    {
      "render": "WizardNavButton",
      "isNext": true,
      "size": "large"
    }
  ]
}

Most complicated ui:col definition, additional GridTemplate props and form 1, 2 and 3 children (this example
uses @mui/material/Grid2 native props):

json
{
  "ui:col": {
    "size": { "md": 4 },
    "className": "GridColumn",
    "children": [
      "innerField",
      { "name": "inner.grandChild", "fullWidth": true },
      { "name": "customRender", "render": "CustomRender", "toSpread": "prop-value" },
      { "ui:row|ui:condition": ... },
      ...
    ]
  }
}

NOTE: If a name prop does not exist or its value does not match any field in a schema, then it is assumed to be a
custom render component. If the render prop does not exist, a null render will occur. If render is a
string, its value will be looked up in the formContext.lookupMap first before defaulting to a null render. If the
resulting looked up render is not a function (React components are functions), then it will be a null render.

`ui:columns`

The ui:columns grid element is syntactic sugar to specify a set of ui:col columns that all share the same set of
native GridTemplate props. In other words rather than writing the following configuration that renders a
<GridTemplate> element with 3 <GridTemplate column className="GridColumn col-md-4"> nodes and 2
<GridTemplate column className="col-md-6"> nodes within it (one for each of the fields contained in the children
list):

json
{
  "ui:row": {
    "children": [
      {
        "ui:col": {
          "className": "GridColumn col-md-4",
          "children": ["innerField"]
        }
      },
      {
        "ui:col": {
          "className": "GridColumn col-md-4",
          "children": ["inner.grandChild"]
        }
      },
      {
        "ui:col": {
          "className": "GridColumn col-md-4",
          "children": [{ "name": "inner.grandChild2" }]
        }
      },
      {
        "ui:col": {
          "className": "col-md-6",
          "children": ["innerField2"]
        }
      },
      {
        "ui:col": {
          "className": "col-md-6",
          "children": ["inner.grandChild3"]
        }
      }
    ]
  }
}

One can write this instead:

json
{
  "ui:row": {
    "children": [
      {
        "ui:columns": {
          "className": "GridColumn col-md-4",
          "children": ["innerField", "inner.grandChild", { "name": "inner.grandChild2", "fullWidth": true }]
        }
      },
      {
        "ui:columns": {
          "className": "col-md-6",
          "children": ["innerField2", "inner.grandChild3"]
        }
      }
    ]
  }
}

NOTE: This syntax differs from "ui:col": { "className": "col-md-6", "children": ["innerField2", "inner.grandChild3"] } in that
the ui:col will render the two children fields inside a single <GridTemplate "className": "col-md-6",>
element.

`ui:condition`

The final grid element, ui:condition, allows for conditionally displaying "grid elements" within a row based on the
current value of a field as it relates to a (list of) hard-coded value(s). There are four elements that make up a
ui:condition:

  1. the dotted-path field name within the root field that makes up the left-side of the condition;
  2. the hard-coded value (single or list) that makes up the right-side of the condition;
  3. the operator that controls how the left and right sides of the condition are compared; and
  4. the children array that defines the "grid elements" to display if the condition passes.

A ui:condition uses one of three operators when deciding if a condition passes:

  1. The all operator will pass when the right-side and left-side contains all the same value(s);
  2. the some operator will pass when the right-side and left-side contain as least one value in common;
  3. the none operator will pass when the right-side and left-side do not contain any values in common. E.g. (as JSON objects):

Here is how to render an if-then-else for field2 which is an enum that has 3 known values and supports allowing
any other value:

json
{
  "ui:row": [
    {
      "ui:condition": {
        "field": "field2",
        "operator": "all",
        "value": "value1",
        "children": [
          { "ui:row": [...] }
        ],
      }
    },
    {
      "ui:condition": {
        "field": "field2",
        "operator": "some",
        "value": ["value2", "value3"],
        "children": [
          { "ui:row": [...] }
        ],
      }
    },
    {
      "ui:condition": {
        "field": "field2",
        "operator": "none",
        "value": ["value1", "value2", "value3"],
        "children": [
          { "ui:row": [...] }
        ]
      }
    }
  ]
}

Packages Docs Docs Api Reference Dynamic Ui Schema Examples (`packages/docs/docs/api-reference/dynamic-ui-schema-examples.md`)

Dynamic uiSchema Examples

Backward Compatibility Examples

Example 1: Traditional Static uiSchema (No Changes Required)

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

// This continues to work exactly as before
const uiSchema: UiSchema = {
  guests: {
    items: {
      name: { 'ui:placeholder': 'Enter guest name' },
      age: { 'ui:widget': 'updown' },
      relationship: { 'ui:widget': 'select' },
    },
  },
};

Example 2: Dynamic uiSchema with Function

text
/* Detailed source-code truncated for AI context efficiency. */

Example 3: Using Form Context

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

interface ParticipantData {
  name?: string;
  email?: string;
  workshop?: string;
}

interface MyFormContext extends FormContextType {
  eventType?: 'conference' | 'workshop' | 'webinar';
}

const uiSchema: UiSchema<any, any, MyFormContext> = {
  participants: {
    items: (itemData: ParticipantData | undefined, index: number, formContext?: MyFormContext): UiSchema => {
      // Access form-wide settings
      const isConference = formContext?.eventType === 'conference';

      return {
        name: { 'ui:placeholder': 'Participant name' },
        email: { 'ui:widget': 'email' },
        // Show workshop selection only for conference events
        workshop: isConference ? { 'ui:widget': 'select' } : { 'ui:widget': 'hidden' },
      };
    },
  },
};

Example 4: Falsy Return Values

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

interface ItemData {
  needsCustomUI?: boolean;
  field1?: string;
  field2?: string;
}

const uiSchema: UiSchema = {
  items: {
    items: (itemData: ItemData | undefined, index: number): UiSchema | null | undefined => {
      // Only apply custom UI to specific items
      if (itemData?.needsCustomUI) {
        return {
          field1: { 'ui:widget': 'textarea' },
          field2: { 'ui:help': 'This item needs special attention' },
        };
      }

      // Return null or undefined to use default UI rendering
      // This is useful for conditionally applying custom UI
      return null;
    },
  },
};

Example 5: Dynamic UI for Fixed Arrays

For fixed/tuple arrays (where schema.items is an array), the dynamic function can be applied to each position:

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

interface DetailsData {
  age?: number;
  role?: string;
}

const schema: RJSFSchema = {
  type: 'array',
  items: [
    { type: 'string', title: 'First Name' },
    { type: 'string', title: 'Last Name' },
    { type: 'object', title: 'Details', properties: { age: { type: 'number' }, role: { type: 'string' } } },
  ],
};

const uiSchema: UiSchema = {
  items: [
    { 'ui:placeholder': 'Enter first name' }, // Static UI for first item
    { 'ui:placeholder': 'Enter last name' }, // Static UI for second item
    // Dynamic UI for third item based on its data
    (itemData: DetailsData | undefined, index: number): UiSchema => {
      if (itemData?.role === 'admin') {
        return {
          age: { 'ui:widget': 'hidden' },
          role: { 'ui:help': 'Admin role selected' },
        };
      }
      return {
        age: { 'ui:widget': 'updown' },
        role: { 'ui:widget': 'select' },
      };
    },
  ],
};

Schema Example

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

const schema: RJSFSchema = {
  type: 'object',
  properties: {
    guests: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          name: { type: 'string', title: 'Name' },
          age: { type: 'number', title: 'Age' },
          relationship: {
            type: 'string',
            title: 'Relationship',
            enum: ['adult', 'child', 'senior'],
          },
          guardianName: { type: 'string', title: 'Guardian Name' },
          mealPreference: {
            type: 'string',
            title: 'Meal Preference',
            enum: ['vegetarian', 'vegan', 'standard', 'gluten-free'],
          },
        },
        required: ['name', 'relationship'],
      },
    },
  },
};

Key Benefits

  1. Backward Compatible: Existing forms with object-based uiSchema.items continue to work without any changes
  2. Progressive Enhancement: Developers can opt-in to dynamic behavior when needed
  3. Flexible: Access to item data, index, and form context enables complex UI logic
  4. Safe: Built-in error handling prevents the entire form from crashing if your function throws an error. When an error occurs for a specific item, it will be caught and logged to the developer console, and the UI for that item will fall back to the default rendering. This ensures the rest of the form remains functional while making debugging easier.
  5. On-Demand Execution: The function is executed on-demand during the render cycle. However, as it runs for each array item, performance should be carefully managed for large lists (see Performance Considerations below).

Key Behaviors

  • Falsy Returns: If your function returns a falsy value (e.g., null or undefined), the UI for that specific item will fall back to its default rendering. This allows you to conditionally apply custom UI only when needed.
  • Error Handling: If your function throws an error, it will be caught and logged to the console. The form will continue to work, using default UI for the affected item.
  • New Items: When a new item is added to the array, itemData will be undefined or contain default values from the schema. Always use optional chaining (?.) to safely access properties.

Performance Considerations

When using dynamic uiSchema.items functions, keep in mind:

  • The function is executed on every render for each array item
  • For large arrays, this can impact performance if the function performs expensive operations
  • Best practices:
    • Keep the function logic lightweight and fast
    • Avoid heavy computations or external API calls within the function
    • Consider memoizing results if the same inputs produce the same outputs
    • For complex logic, pre-compute values and store them in formContext or component state

Example of a performance-optimized approach:

typescript
import React, { PropsWithChildren, useMemo } from 'react';
import Form from '@rjsf/core';
import { RJSFSchema, UiSchema, FormContextType, IChangeEvent } from '@rjsf/utils';

interface ItemData {
  type?: string;
  field?: any;
}

interface ExpensiveDataConfig {
  widget: string;
}

interface MyFormProps {
  schema: RJSFSchema;
  formData?: any;
}

// In your React component that renders the form:
function MyFormComponent({ schema, formData }: PropsWithChildren<MyFormProps>) {
  // Pre-compute expensive data once, and only re-compute if dependencies change
  const expensiveData = useMemo<Record<string, ExpensiveDataConfig>>(() => computeExpensiveData(), [/* dependencies */]);

  const defaultConfig: ExpensiveDataConfig = { widget: 'text' };

  // Define the uiSchema inside the component so it can access the memoized data
  const uiSchema: UiSchema = {
    myArrayField: { // Target your specific array field
      items: (itemData: ItemData | undefined, index: number, formContext?: FormContextType): UiSchema => {
        // Use the pre-computed data - this is very fast
        const config = expensiveData[itemData?.type || ''] || defaultConfig;

        return {
          field: { 'ui:widget': config.widget }
        };
      }
    }
  };

  return <Form schema={schema} uiSchema={uiSchema} formData={formData} />;
}

// Placeholder for the expensive computation function
declare function computeExpensiveData(): Record<string, ExpensiveDataConfig>;

Packages Docs Docs Api Reference Form Props (`packages/docs/docs/api-reference/form-props.md`)


title:
Props

<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.

autoComplete

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

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. If no children are provided, by default a Submit button will be rendered.

For other ways to modify the default Submit button, see both the Submit Button Options and the SubmitButton Template documentation.

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

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

render(
  <Form schema={schema} validator={validator}>
    <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).

customValidate

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

experimental_componentUpdateStrategy

Experimental feature to specify an alternative component update strategy that accepts one of the following value:
React's default Component rendering strategy is to re-render on every state change, see shouldComponentUpdate docs.
PureComponent's strategy uses shallow equality. One can also always update (not recommended for performance reasons, but can be useful for testing)

Option Description
customDeep Legacy behavior - uses RJSF's deepEquals function
shallow shallow equality
always component always rerenders

experimental_defaultFormStateBehavior

Experimental features to specify different form state behavior.
Currently, this only affects the handling of optional array fields where minItems is set and handling of setting defaults based on the value of emptyObjectFields.

Warning: This API is experimental and unstable, therefore breaking changes may be shipped in minor or patch releases. If you want to use this feature, we recommend pinning exact versions of @rjsf/\* packages in your package.json file or be ready to update your use of it when necessary.

The following subsections represent the different keys in this object, with the tables explaining the values and their meanings.

arrayMinItems

This optional subsection is an object with two optional fields, populate and mergeExtraDefaults.
When not specified, it defaults to { populate: 'all', mergeExtraDefaults: false }.

arrayMinItems.populate

Optional enumerated flag controlling how array minItems are populated, defaulting to all:

Flag Value Description
all Legacy behavior - populate minItems entries with default values initially and include empty array when no values have been defined.
requiredOnly Ignore minItems on a field when calculating defaults unless the field is required.
never Ignore minItems on a field when calculating defaults for required and non-required. Value will set only if defined default and from formData

arrayMinItems.computeSkipPopulate

The signature and documentation for this property is as follow:

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

A function that determines whether to skip populating the array with default values based on the provided validator, schema, and root schema.
If the function returns true, the array will not be populated with default values.
If the function returns false, the array will be populated with default values according to the populate option.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that is used to detect valid schema conditions
  • schema: S - The schema for which resolving a condition is desired
  • [rootSchema]: S - The root schema that will be forwarded to all the APIs

Returns

  • boolean: A boolean indicating whether to skip populating the array with default values.

Example

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

const schema: RJSFSchema = {
  type: 'object',
  properties: {
    stringArray: {
      type: 'array',
      items: { type: 'string' },
      minItems: 1,
    },
    numberArray: {
      type: 'array',
      items: { type: 'number' },
      minItems: 1,
    },
  },
  required: ['stringArray', 'numberArray'],
};

const computeSkipPopulateNumberArrays = (validator, schema, rootSchema) =>
  // These conditions are needed to narrow down the type of the schema.items
  !Array.isArray(schema?.items) &&
  typeof schema?.items !== 'boolean' &&
  schema?.items?.type === 'number',

render(
  <Form
    schema={schema}
    validator={validator}
    experimental_defaultFormStateBehavior={{
      arrayMinItems: {
        computeSkipPopulate: computeSkipPopulateNumberArrays,
      },
    }}
  />,
  document.getElementById('app')
);

arrayMinItems.mergeExtraDefaults

Optional boolean flag, defaulting to false when not specified.
When formData is provided and does not contain minItems worth of data, this flag controls whether the extra data provided by the defaults is appended onto the existing formData items to ensure the minItems condition is met.
When false (legacy behavior), only the formData provided is merged into the default form state, even if there are fewer than the minItems.
When true, the defaults are appended onto the end of the formData until the minItems condition is met.

emptyObjectFields

Optional enumerated flag controlling how empty object fields are populated, defaulting to populateAllDefaults:

Flag Value Description
populateAllDefaults Legacy behavior - set default when there is a primitive value, an non-empty object field, or the field itself is required
populateRequiredDefaults Only sets default when a value is an object and its parent field is required, or it is a primitive value and it is required
skipDefaults Does not set defaults
skipEmptyDefaults Does not set an empty default. It will still apply the default value if a default property is defined in your schema
tsx
import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

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

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

allOf

Optional enumerated flag controlling how empty defaults are populated when allOf schemas are provided, defaulting to skipDefaults:

Flag Value Description
skipDefaults Skip parsing defaults from allOf schemas nested inside the schema defaults are computed from, with the exceptions below
populateDefaults Generate default values for properties in the allOf schema including if-then-else syntax

skipDefaults only skips the allOf schemas nested inside the schema that defaults are computed from, not that schema's own allOf.
Which schema that is depends on what the form is doing:

  • When the form computes defaults from the root schema, a root-level allOf provides its defaults with either value.
  • Some actions compute defaults from a subschema as if it were the root, such as adding an array item or optional data, or switching a oneOf or anyOf option, so that subschema's own allOf provides its defaults with either value. When switching options, though, the if of an if-then-else in the new option's allOf is checked against the data of the option being left, so under skipDefaults its then default is filled in only when that data matches the if.
  • The option picked on the initial render is not computed as if it were the root, even when its oneOf or anyOf is in the root schema, so under skipDefaults its allOf is left out until the user switches away from that option and back.

The branch of an if-then-else is picked from the form data, not from the computed defaults, except in a dependencies entry, as the last item below says:

  • When the if lists a property in required and only a default provides that property, the then default is left out until the form data holds the value, for instance on the initial render.
  • Without required, a missing property still satisfies the if's properties, so such an if passes with no data, and its then default is filled in even when the if does not match the defaulted value.
  • With one allOf entry per enum value and no form data, the default allOf merger merges the then defaults of all the entries, and the first entry that defaults a property wins. An experimental_customMergeAllOf that throws on the conflicting defaults drops the whole allOf instead.

An allOf in an object property or in an array's items is skipped as a whole, plain property defaults included, so it usually needs populateDefaults to provide its defaults.
This is specific to allOf:

  • An if-then-else placed directly in a nested object schema is resolved with either value, unless emptyObjectFields is skipEmptyDefaults. For example, under skipDefaults, items: { type: 'object', if, then } fills in the then default, while items: { type: 'object', allOf: [{ if, then }] } does not.
  • Adding a direct if to that items schema resolves its whole allOf too, unless emptyObjectFields is skipEmptyDefaults.
  • With an experimental_customMergeAllOf built on a deep merger, such as createDeepAllOfMerge from @x0k/json-schema-merge given a shallow merge built with that library's createMerger and createShallowAllOfMerge, merging an allOf also turns a property's allOf: [{ if, then }] into a direct if-then-else, so that property's then default is filled in under skipDefaults, unless emptyObjectFields is skipEmptyDefaults. That happens wherever an allOf is merged: the root's own allOf, or the allOf of an object or items schema that also has a direct if, but not a nested allOf on its own.
  • A dependencies entry in a nested object schema is resolved once its property has a value, its allOf and if-then-else included, even when emptyObjectFields is skipEmptyDefaults. A default counts as that value, and the entry's if is checked against it, so an if that lists the property in required passes with no form data, while one that does not match the default fails. For example, under skipDefaults, items: { type: 'object', properties: { animal: { default: 'Cat' } }, dependencies: { animal: { allOf: [{ if, then }] } } } fills in the then default. A root dependencies entry counts a default only while the form data is empty: once the form data holds any value, the entry is applied only when the form data holds its property.
tsx
import { Form } from '@rjsf/core';
import { RJSFSchema } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';

const schema: RJSFSchema = {
  title: 'Example',
  type: 'object',
  properties: {
    animalInfo: {
      properties: {
        animal: {
          type: 'string',
          default: 'Cat',
          enum: ['Cat', 'Fish'],
        },
      },
      allOf: [
        {
          if: {
            properties: {
              animal: {
                const: 'Cat',
              },
            },
          },
          then: {
            properties: {
              food: {
                type: 'string',
                default: 'meat',
                enum: ['meat', 'grass', 'fish'],
              },
            },
            required: ['food'],
          },
        },
      ],
    },
  },
};

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

constAsDefaults

Optional enumerated flag controlling how const values are merged into the form data as defaults when dealing with undefined values, defaulting to always.
The defaulting behavior for this flag will always be controlled by the emptyObjectField flag value.
For instance, if populateRequiredDefaults is set and the const value is not required, it will not be set.

Flag Value Description
always A const value will always be merged into the form as a default. If there is are const values in a oneOf (for instance to create an enumeration with title different from the values), the first const value will be defaulted
skipOneOf If const is in a oneOf it will NOT pick the first value as a default
never A const value will never be used as a default

mergeDefaultsIntoFormData

Optional enumerated flag controlling how the defaults are merged into the form data when dealing with undefined values, defaulting to useFormDataIfPresent.

NOTE: If there is a default for a field and the formData is unspecified, the default ALWAYS merges.

Flag Value Description
useFormDataIfPresent Legacy behavior - Do not merge defaults if there is a value for a field in formData even if that value is explicitly set to undefined
useDefaultIfFormDataUndefined If the value of a field within the formData is undefined, then use the default value instead

nestedDefaultsPrecedence

Optional enumerated flag controlling how defaults defined on multiple levels are merged together for overlapping properties, defaulting to descendantWins.

Flag Value Description
descendantWins The innermost (descendant) default value definition takes precedence over its ancestor's defaults
ancestorWins The outermost (ancestor) default value definition takes precedence over any descendant's defaults

Example

In the following example, the animal property is a descendant of the root schema and both define a default value for animal. By default, the animal's default value Cat would take precedence over its ancestor's Fish. However, since nestedDefaultsPrecedence is set to ancestorWins, the root schema's default value takes precedence and animal is set to Fish by default.

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

const schema: RJSFSchema = {
  type: 'object',
  default: {
    animal: 'Fish',
  },
  properties: {
    animal: {
      type: 'string',
      default: 'Cat',
      enum: ['Cat', 'Fish'],
    },
  },
};

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

requiredBooleanDefault

Optional enumerated flag controlling whether a boolean listed in its parent's required array, with no default of its own, is populated with false, defaulting to populateFalse.
An explicit schema default, a parent default and an existing formData value always take precedence; this flag only decides what happens when none of them provides a value.

Flag Value Description
populateFalse A required boolean with no default is set to false
skip No value is synthesized; the property stays undefined until the user answers it, so required remains a validation concern

Example

In the following example, agree is required but has no default. By default it would start as false, and the form would report { agree: false } through onChange on mount. With requiredBooleanDefault set to skip, formData stays {} until the user answers, and validation reports agree as missing until then. This is the behavior to choose when a boolean question is rendered with an explicit "unanswered" state, for example a - - - / Yes / No select, rather than a checkbox.

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

const schema: RJSFSchema = {
  type: 'object',
  properties: {
    agree: {
      type: 'boolean',
      title: 'Do you agree?',
    },
  },
  required: ['agree'],
};

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

experimental_customMergeAllOf

The experimental_customMergeAllOf function allows you to provide a custom implementation for merging allOf schemas. This can be particularly useful in case the where the default merge library (@x0k/json-schema-merge) doesn't satisfy your functional or performance requirements.

By providing your own implementation, you can potentially achieve significant performance improvements. For instance, if your use case only requires a subset of JSON Schema features, you can implement a faster, more tailored merging strategy.

If you're looking for alternative allOf merging implementations, you might consider allof-merge.

Warning: This is an experimental feature. Only use this if you fully understand the implications of custom allOf merging and are prepared to handle potential edge cases. Incorrect implementations may lead to unexpected behavior or validation errors.

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

const customMergeAllOf = (schema: RJSFSchema): RJSFSchema => {
  // Your custom implementation here
};

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

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.

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

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

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

If you just want to disable some 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.

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

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

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

If you just want to make some 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.
By default, these are non-blocking errors, meaning that you can still submit the form when these are the only errors displayed to the user.
See Validation for more information.

extraErrorsBlockSubmit

If set to true, causes the extraErrors to become blocking when the form is submitted.

fields

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

focusOnFirstError

If set to true, then the first field with an error will receive the focus when the form is submitted with errors.

You can also provide a custom callback function to handle what happens when this function is called.

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

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

const focusOnError = (error: RJSFValidationError) => {
  console.log('I need to handle focusing this error');
};

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

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.

See AntD Customization for formContext customizations for the antd theme.
See Semantic UI Customization for formContext customizations for the semantic-ui theme.

formData

The data for the form, used to load a "controlled" form with its current data. If you want an "uncontrolled" form with initial data, then use initialFormData instead.

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).

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

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

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

This will render instead of

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 _).

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

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

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

This will render instead of when rendering first.

initialFormData

The initial data for the form, used to fill an "uncontrolled" form with existing data on the initial render and when reset() is called programmatically.

nameGenerator

The nameGenerator prop allows you to customize how HTML name attributes are generated for form fields. This is essential when submitting form data to backend frameworks that expect specific naming conventions for structured data.

Default behavior: When no nameGenerator is provided, the name attribute will equal the id attribute (e.g., root_tasks_0_title).

RJSF provides two built-in generators:

bracketNameGenerator - Generates bracket notation for PHP/Rails (e.g., root[tasks][0][title]). Automatically appends [] for multi-value fields like checkboxes.

dotNotationNameGenerator - Generates dot notation for other frameworks (e.g., root.tasks.0.title).

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

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

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

You can also create a custom generator by implementing the NameGeneratorFunction type, which receives path (array of path segments), idPrefix (typically 'root'), and optional isMultiValue (boolean for multi-value fields).

liveOmit

Flag that describes when live omit will be performed. Live omit happens only when omitExtraData is also set to
to true and the form's data is updated by the user.

If no value (or false) is provided, then live omit will not happen. If true or onChange is provided for
the flag, then live omit will be performed after processing of all pending changes has completed. If onBlur
is provided, then live omit will be performed when a field that was updated is blurred (as a performance
optimization).

NOTE: The boolean options for this flag is deprecated and will be removed in a future major release

liveValidate

Flag that describes when live validation will be performed. Live validation means that the form will perform
validation and show any validation errors whenever the form data is updated, rather than just on submit.

If no value (or false) is provided, then live validation will not happen. If true or onChange is provided for
the flag, then live validation will be performed after processing of all pending changes has completed. If onBlur
is provided, then live validation will be performed when a field that was updated is blurred (as a performance
optimization).

NOTE: The boolean options for this flag is deprecated and will be removed in a future major release

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 by default.

noValidate

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

NOTE: In a future major release, this flag may be deleted replaced by making validator prop optional

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 first argument as onSubmit any time a value is updated in the form.
It will also receive, as the second argument, the id of the field which experienced the change.
Generally, this will be the id of the field for which input data is modified.
In the case of adding/removing of new fields in arrays or objects with additionalProperties or patternProperties and the rearranging of items in arrays, the id will be that of the array or object itself, rather than the item/field being added, removed or moved.

onError

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

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

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

render(<Form schema={schema} validator={validator} 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:

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

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

render(<Form schema={schema} validator={validator} 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.

removeEmptyOptionalObjects

Deprecated: This prop no longer has any effect and will be removed in a future release. The behavior of pruning optional empty objects is now built into omitExtraData — enable that prop instead.

When a JSON Schema has a required field inside an optional object, any user interaction with that optional object "activates" it. Even if the user clears all the fields within that object, the empty object property (e.g., { test: {} } or { test: { field1: "" } }) remains in the formData. Because the object contains required fields that are now empty, the form becomes unsubmittable.

Previously, setting removeEmptyOptionalObjects to true caused the form to recursively prune these optional empty objects from the formData during onChange, onBlur, and onSubmit. This pruning is now performed automatically by omitExtraData.

schema

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

showErrorList

When this prop is set to top or bottom, a list of errors (or the custom error list defined in the ErrorList) will also show at the bottom or top of the form. When set to false, only inline input validation errors will be shown. Set to top 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.

tsx
<Form
  tagName="div"
  ...
/>

You can also provide a class/function component.

tsx
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.

templates

Dictionary of registered templates in the form. See Custom Templates for more information.

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.

translateString

Optional string translation function, if provided, allows users to change the translation of the RJSF internal strings.
Some strings contain replaceable parameter values as indicated by %1, %2, etc.
The number after the % indicates the order of the parameter.
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:

ts
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.

useFallbackUiForUnsupportedType

If set to true, when an unsupported schema type is encountered, the form will render a fallback UI instead of displaying an error. The fallback UI will display a widget that allows the user to select a JSON Schema primitive type, and a field containing the form data that matches the selected type. Set to false by default.

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.


Packages Docs Docs Api Reference UiSchema (`packages/docs/docs/api-reference/uiSchema.md`)

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 almost 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:

json
{
  "ui:title": "Title",
  "ui:description": "Description",
  "ui:classNames": "my-class",
  "ui:submitButtonOptions": {
    "props": {
      "disabled": false,
      "className": "btn btn-info"
    },
    "norender": false,
    "submitText": "Submit"
  }
}
json
{
  "ui:options": {
    "title": "Title",
    "description": "Description",
    "classNames": "my-class",
    "submitButtonOptions": {
      "props": {
        "disabled": false,
        "className": "btn btn-info"
      },
      "norender": false,
      "submitText": "Submit"
    }
  }
}

For a full list of what is supported in the uiSchema see the UiSchema type in @rjsf/utils/types.ts.
Be sure to pay attention to the hierarchical intersection to these other types: UIOptionsBaseType and TemplatesType.

Exceptions to the equivalence

There are 4 properties that exist in a UiSchema that will not be found in an inner ui:options object.

`ui:globalOptions`

The set of globally relevant UiSchema options that are read from the root-level UiSchema and stored in the registry for use everywhere.

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

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

`ui:definitions`

The ui:definitions property allows you to define reusable UI customizations for schema $ref references. This is particularly useful for:

  • Recursive schemas - Define uiSchema once for a self-referencing schema node
  • Reused definitions - Apply consistent UI to schemas used in multiple places
  • oneOf/anyOf branches - Provide different uiSchema for branches that reference different definitions

The keys in ui:definitions must match the exact $ref path used in the schema (e.g., #/definitions/address or #/$defs/node).

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

const schema: RJSFSchema = {
  definitions: {
    address: {
      type: 'object',
      properties: {
        street_address: { type: 'string' },
        city: { type: 'string' },
      },
    },
    node: {
      type: 'object',
      properties: {
        name: { type: 'string' },
        children: {
          type: 'array',
          items: { $ref: '#/definitions/node' }, // Recursive reference
        },
      },
    },
  },
  type: 'object',
  properties: {
    billing_address: { $ref: '#/definitions/address' },
    shipping_address: { $ref: '#/definitions/address' },
    tree: { $ref: '#/definitions/node' },
  },
};

const uiSchema: UiSchema = {
  'ui:definitions': {
    '#/definitions/address': {
      street_address: { 'ui:placeholder': 'Street and number' },
      city: { 'ui:placeholder': 'City name' },
    },
    '#/definitions/node': {
      name: { 'ui:placeholder': 'Enter node name' },
      children: { 'ui:options': { orderable: false } },
    },
  },
  // Local overrides take precedence over ui:definitions
  shipping_address: {
    street_address: { 'ui:placeholder': 'Shipping street (overrides definition)' },
  },
};

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

Local Overrides

You can override specific properties from ui:definitions by providing values at the field path. Local values are merged with definitions, with local values taking precedence.

oneOf/anyOf with Same Property Names

When using oneOf or anyOf with branches that have properties with the same name, each branch's $ref maps to its own entry in ui:definitions, ensuring correct UI is applied:

tsx
const schema: RJSFSchema = {
  definitions: {
    person: { type: 'object', properties: { name: { type: 'string' } } },
    company: { type: 'object', properties: { name: { type: 'string' } } },
  },
  type: 'object',
  properties: {
    contact: {
      oneOf: [
        { title: 'Person', $ref: '#/definitions/person' },
        { title: 'Company', $ref: '#/definitions/company' },
      ],
    },
  },
};

const uiSchema: UiSchema = {
  'ui:definitions': {
    '#/definitions/person': {
      name: { 'ui:placeholder': 'Full name (e.g., John Doe)' },
    },
    '#/definitions/company': {
      name: { 'ui:placeholder': 'Company name (e.g., Acme Inc.)' },
    },
  },
};

`ui:rootFieldId` (deprecated)

DEPRECATED: Use Form.idPrefix instead, will be removed in a future major version

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:

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

const uiSchema: UiSchema = {
  'ui:rootFieldId': 'myform',
};

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

`ui:field`

The ui:field property overrides the Field implementation used for rendering any field in the form's hierarchy.
Specify either the name of a field that is used to look up an implementation from the fields list or an actual one-off Field component implementation itself.

See Custom Widgets and Fields for more information about how to use this property.

`ui:fieldReplacesAnyOrOneOf`

By default, any field that is rendered for an anyOf/oneOf schema will be wrapped inside the AnyOfField or OneOfField component.
This default behavior may be undesirable if your custom field already handles behavior related to choosing one or more subschemas contained in the anyOf/oneOf schema.
By providing a true value for this flag in association with a custom ui:field, the wrapped components will be omitted, so just one instance of the custom field will be rendered.
If the flag is omitted or set to false, your custom field will be wrapped by AnyOfField/OneOfField.

`ui:options`

The ui:options property cannot be nested inside itself and thus is the last exception.

`ui:XXX` or `ui:options.XXX`

All the properties that follow can be specified in the uiSchema in either of the two equivalent ways.

NOTE: The properties specific to array items can be found here. For advanced dynamic UI schema capabilities for array items, see the Dynamic UI Schema Examples.

widget

The ui:widget property overrides the Widget implementation used for rendering any field in the form's hierarchy.
Specify either the name of a widget that is used to look up an implementation from the widgets list or an actual one-off Widget component implementation itself.

See Custom Widgets and Fields for more information about how to use this property.

classNames

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

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

const uiSchema = {
  title: {
    'ui:classNames': 'task-title foo-bar',
  },
};

Will result in:

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

style

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

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

const uiSchema = {
  title: {
    'ui:style': { color: 'red' },
  },
};

Will result in:

html
<div class="field field-string task-title" style={{ color: "red" }}>
  <label>
    <span>Title*</span>
    <input value="My task" required="" type="text">
  </label>
</div>

allowClearTextInputs

The optional ui:allowClearTextInputs uiSchema directive enables a clear/reset button for text-based input widgets.
When set to true, a clear button will be displayed when the input field has a value and is not readonly or disabled.
When omitted, no clear button will be displayed for text input fields.

When clicked, the property value will be set to the ui:emptyValue, if defined.

tsx
import { RJSFSchema, UiSchema } from '@rjsf/utils';
const schema: RJSFSchema = { type: 'string' };
const uiSchema: UiSchema = {
  'ui:allowClearTextInputs': true,
};

It can also be enabled globally by setting the allowClearTextInputs option to true in the ui:globalOptions
uiSchema directive.

tsx
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:globalOptions': {
    allowClearTextInputs: true,
  },
};

autocomplete

If you want to mark a text input, select or textarea input to use the HTML autocomplete feature, set the ui:autocomplete uiSchema directive to a valid HTML autocomplete value.

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

const schema: RJSFSchema = { type: 'string' };
const uiSchema: UiSchema = {
  'ui:widget': 'textarea',
  'ui:autocomplete': 'on',
};

autocapitalize

To control automatic capitalization on virtual keyboards for a text input, set the ui:autocapitalize uiSchema
directive to a valid HTML autocapitalize value.

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

const schema: RJSFSchema = { type: 'string' };
const uiSchema: UiSchema = {
  'ui:autocapitalize': 'words',
};

autofocus

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

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

const schema: RJSFSchema = { type: 'string' };
const uiSchema: 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:

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

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

deprecatedHandling

The ui:deprecatedHandling uiSchema directive controls how a field marked as deprecated in the JSON Schema is rendered.

Accepts one of three values:

  • 'label' (default): The field is rendered normally with "(deprecated)" appended to its label.
  • 'disable': The field is rendered but all its child widgets are disabled.
  • 'hide': The field is completely hidden from the form.
tsx
import { RJSFSchema, UiSchema } from '@rjsf/utils';

const schema: RJSFSchema = {
  type: 'object',
  properties: {
    legacyField: { type: 'string', deprecated: true },
  },
};

const uiSchema: UiSchema = {
  legacyField: {
    'ui:options': {
      deprecatedHandling: 'disable',
    },
  },
};

It can also be set globally by specifying the deprecatedHandling option in the ui:globalOptions uiSchema directive, which applies the chosen behavior to every deprecated field in the form.

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

const schema: RJSFSchema = {
  type: 'object',
  properties: {
    legacyField: { type: 'string', deprecated: true },
    anotherOldField: { type: 'number', deprecated: true },
  },
};

const uiSchema: UiSchema = {
  'ui:globalOptions': {
    deprecatedHandling: 'hide',
  },
};

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

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.

enableMarkdownInDescription

The ui:enableMarkdownInDescription uiSchema directive enables the support of Markdown syntax within the description of
a field.

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

const schema: RJSFSchema = { type: 'string', description: '**bolded** text in the description' };
const uiSchema: UiSchema = {
  'ui:enableMarkdownInDescription': true,
};
render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

It can also be enabled globally by setting the enableMarkdownInDescription option to true in the ui:globalOptions
uiSchema directive.

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

const schema: RJSFSchema = { type: 'string', description: '**bolded** text in the description' };
const uiSchema: UiSchema = {
  'ui:globalOptions': {
    enableMarkdownInDescription: true,
  },
};

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

enableMarkdownInHelp

The ui:enableMarkdownInHelp uiSchema directive enables the support of Markdown syntax within the help displayed for
a field.

tsx
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:enableMarkdownInHelp': true,
  'ui:help': '**bolded** text in the help',
};
render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, document.getElementById('app'));

It can also be enabled globally by setting the enableMarkdownInHelp option to true in the ui:globalOptions
uiSchema directive.

tsx
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:globalOptions': {
    enableMarkdownInHelp: true,
  },
  'ui:help': '**bolded** text in the help',
};

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

enableOptionalDataFieldForType

The ui:enableOptionalDataFieldForType uiSchema directive enables support for displaying the Optional Data Controls feature.
The intention of this feature is to allow developers to provide a condensed UI for users who don't care to enter an optional list of array items or set of optional object fields (see examples below).

This directive takes, as its value, an array in one of four forms:

  1. [] - Disables the feature at a global or field level
  2. ['array'] - Enables the feature only for optional arrays at a global or field level
  3. ['object'] - Enables the feature only for optional object at a global or field level
  4. ['array', 'object']- Enables the feature for both optional object and arrays at a global or field level

It can be specified in either the ui:globalOptions to turn the feature on for everything or in a specific field's uiSchema
To work properly this option must be coupled with the emptyObjectFields experimental feature on Form using the populateRequiredDefaults or skipDefaults options.

When enabled for either (or both) the array or object types, any optional object or array field which has an "undefined" value in formData will NOT render any of the container's UI elements.
Instead the object/array container's field title will have an "Add optional data" icon button that, when clicked will cause an empty container data element to be added to formData.

When enabled for either (or both) the array or object types, any optional object or array field which has an "defined" value in formData will render all of the container's UI elements as normal AND the object/array container's field title will have a "Remove optional data" icon button that, when clicked will set the data for field in the formData to "undefined".

Here is an example of what the UI will look like when enabled using the following Form configuration:

tsx
const schema: RJSFSchema = {
  title: 'test',
  properties: {
    nestedObjectOptional: {
      type: 'object',
      properties: {
        test: {
          type: 'string',
        },
      },
    },
    nestedArrayOptional: {
      type: 'array',
      items: {
        type: 'string',
      },
    },
  },
};
const uiSchema = {
  'ui:globalOptions': {
    enableOptionalDataFieldForType: ['object', 'array'],
  },
};
const experimental_defaultFormStateBehavior = {
  // Set the emptyObjectFields to only populate required defaults to highlight the code working
  emptyObjectFields: 'populateRequiredDefaults',
};

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

Add Optional Data Controls

Remove Optional Data Controls

emptyValue

The ui:emptyValue uiSchema directive provides the value to store when the input for a field is emptied, whether by typing or by clicking the ui:allowClearTextInputs clear button. It defaults to undefined, which omits the field from the form data entirely.

enumDisabled

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

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

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

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

enumNames

Allows a user to provide labels for enum values in the schema. Can be an array (matched by index) or a map (matched by value).

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

const schema: RJSFSchema = {
  type: 'number',
  enum: [1, 2, 3],
};

// Array form (matched by index)
const uiSchemaArray: UiSchema = {
  'ui:enumNames': ['one', 'two', 'three'],
};

// Map form (matched by value)
const uiSchemaMap: UiSchema = {
  'ui:enumNames': { 1: 'one', 2: 'two', 3: 'three' },
};

enumOrder

Controls the display order of enum options. Use '*' to represent remaining values in their original schema order. Unlisted values not covered by '*' are dropped.

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

const schema: RJSFSchema = {
  type: 'string',
  enum: ['apple', 'banana', 'cherry', 'date'],
};

const uiSchema: UiSchema = {
  'ui:enumOrder': ['cherry', '*', 'apple'],
};

filePreview

The FileWidget can be configured to show a preview of an image or a download link for non-images using this flag.

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

const schema: RJSFSchema = {
  type: 'string',
  format: 'data-url',
};
const uiSchema: UiSchema = {
  'ui:options': {
    filePreview: true,
  },
};

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:

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

const schema: RJSFSchema = { type: 'string' };
const uiSchema: 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.

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

const schema: RJSFSchema = { type: 'string' };
const uiSchema: UiSchema = {
  'ui:options': {
    inputType: 'tel',
  },
};

label

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

tsx
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:options': {
    label: false,
  },
};

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

They can also be omitted globally by setting the label option to false in the ui:globalOptions uiSchema directive.

tsx
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:globalOptions': {
    label: false,
  },
};

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

optionValueFormat

Controls how enum-backed widgets (select, radio, checkboxes) encode option values in their DOM value attributes. Accepts 'indexed' (default) or 'realValue'.

  • 'indexed': options are encoded as their array index (e.g. value="0", value="1"). This is the historical behavior and keeps non-primitive enum values (objects, arrays) addressable without stringifying them.
  • 'realValue': primitive option values are stringified directly (e.g. value="admin", value="42", value="true"). This enables native HTML form submission and browser autocomplete since the submitted value matches the enum value. Non-primitive values (objects, arrays) still fall back to their index because String(obj) would produce "[object Object]".

The form data passed to onChange is always the typed enum value; this option only affects the DOM-level encoding. Can be specified in ui:globalOptions to apply to all enum-backed fields, or per-field in ui:options.

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

const schema: RJSFSchema = {
  type: 'object',
  properties: {
    role: { type: 'string', enum: ['admin', 'editor', 'viewer'] },
  },
};

// Form-wide
const uiSchema: UiSchema = {
  'ui:globalOptions': {
    optionValueFormat: 'realValue',
  },
};

// Or per-field
const fieldUiSchema: UiSchema = {
  role: {
    'ui:options': {
      optionValueFormat: 'realValue',
    },
  },
};

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, 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:

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

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

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, 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.

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

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

render(<Form schema={schema} uiSchema={uiSchema} validator={validator} />, 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.

rows

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

tsx
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:options': {
    widget: 'textarea',
    rows: 15,
  },
};

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

title

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

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

const schema: RJSFSchema = { type: 'string' };
const uiSchema: 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.

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

const uiSchema: UiSchema = {
  'ui:submitButtonOptions': {
    props: {
      disabled: false,
      className: 'btn btn-info',
    },
    norender: false,
    submitText: 'Submit',
  },
};

`duplicateKeySuffixSeparator` option

When using additionalProperties, key collision is prevented by appending a unique integer suffix to the duplicate key.
For example, when you add a key named myKey to a form where myKey is already defined, then your new key will become myKey-1.
You can use ui:duplicateKeySuffixSeparator to override the default separator, "-" with a string of your choice on a per-field basis.

You can also set this in the ui:globalOptions to have the same separator used everywhere.

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

const uiSchema = {
  'ui:globalOptions': {
    duplicateKeySuffixSeparator: '_',
  },
};

Using uiSchema with oneOf, anyOf

anyOf

The uiSchema will work with elements inside an anyOf as long as the uiSchema defines the anyOf key at the same level as the anyOf within the schema.
Because the anyOf 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 anyOf list you would do the following:

ts
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:

ts
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


Packages Docs Docs Api Reference Utility Functions (`packages/docs/docs/api-reference/utility-functions.md`)

RJSF utility functions, constants and types

In version 5, the utility functions from @rjsf/core/utils were refactored into their own library called @rjsf/utils.
These utility functions are separated into two distinct groups.
The first, larger, group are the functions that do NOT require a ValidatorType interface be provided as one of their parameters.
The second, smaller, group are the functions that DO require a ValidatorType interface be provided as a parameter.
There is also a helper function used to create a SchemaUtilsType implementation from a ValidatorType implementation and rootSchema object.

Constants

The @rjsf/utils package exports a set of constants that represent all the keys into various elements of a RJSFSchema or UiSchema that are used by the various utility functions.
In addition to those keys, there is the special ADDITIONAL_PROPERTY_FLAG flag that is added to a schema under certain conditions by the retrieveSchema() utility.

These constants can be found on GitHub here.

Types

Additionally, the Typescript types used by the utility functions represent nearly all the types used by RJSF.
Those types are exported for use by @rjsf/core and all the themes, as well as any customizations you may build.

These types can be found on GitHub here.

ObjectPath — Used by the path utilities (getByPath, setByPath, hasByPath, unsetByPath) to address a value inside a plain object. It is string | number | FieldPathList. A bare string is always a single literal key: 'a.b' means the key 'a.b', never the nested path a → b. To walk a dotted path string, split it explicitly with toPath() first, or pass a FieldPathList ((string | number)[]) of segments. Reads and existence checks resolve own properties only, so inherited members never appear as form data.

SchemaFieldPath — Used when navigating a JSON Schema subtree (for example with getFromSchema and findFieldInSchema on SchemaUtilsType, documented under Validator-based utility functions). It is string | FieldPathList: either a dotted path or an array of segments with the same rules as FieldPathList ((string | number)[]). A numeric segment denotes an array index or an object key that is numeric. Navigation skips only undefined or empty-string segments, so segment 0 is always honored (this avoids the bug from treating 0 as a falsy path unit).

Enums

There are enumerations in @rjsf/utils that are exported for use by @rjsf/core and all the themes, as well as any customizations you may build.

These enums can be found on GitHub here.

Non-Validator utility functions

allowAdditionalItems()

Checks the schema to see if it is allowing additional items, by verifying that schema.additionalItems is an object.
The user is warned in the console if schema.additionalItems has the value true.

Parameters

  • schema: S - The schema object to check

Returns

  • boolean: True if additional items is allowed, otherwise false

ariaDescribedByIds()

Return a list of element ids that contain additional information about the field that can be used to as the aria description of the field.

Parameters

  • id: FieldPathId | string - Either simple string id or an FieldPathId from which to extract it
  • [includeExamples=false]: boolean - Optional flag, if true, will add the examplesId into the list

Returns

  • string: The string containing the list of ids for use in an aria-describedBy attribute

asNumber()

Attempts to convert the string into a number. If an empty string is provided, then undefined is returned.
If a null is provided, it is returned.
If the string ends in a . then the string is returned because the user may be in the middle of typing a float number.
If a number ends in a pattern like .0, .20, .030, string is returned because the user may be typing number that will end in a non-zero digit.
Otherwise, the string is wrapped by Number() and if that result is not NaN, that number will be returned, otherwise the string value will be.

Parameters

  • value: string | null - The string or null value to convert to a number

Returns

  • undefined | null | string | number: The value converted to a number when appropriate, otherwise the value

bracketNameGenerator()

Generates bracketed names for form fields.

Parameters

  • path: FieldPathList - The path of field path units to use when generating the name
  • idPrefix: string - The prefix to use at the start of the generated name
  • [isMultiValue]: boolean | undefined - Optional flag, if true, will append [] to the end of the name for multi-value fields (e.g., checkboxes, multi-select)

Returns

  • string: The generated bracketed name (e.g., root[tasks][0][title], or root[hobbies][] for multi-value fields)

buttonId()

Return a consistent id for the btn button element

Parameters

  • id: FieldPathId | string - The id of the parent component for the option
  • btn: 'add' | 'copy' | 'moveDown' | 'moveUp' | 'remove' - The button type for which to generate the id

Returns

  • string: The consistent id for the button from the given id and btn type

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

Checks whether the field described by schema, having the uiSchema and formData supports expanding.
The UI for the field can expand if it has additional properties, is not forced as non-expandable by the uiSchema and the formData object doesn't already have schema.maxProperties elements.

Parameters

  • schema: S - The schema for the field that is being checked
  • [uiSchema={}]: UiSchema<T, S, F> - The uiSchema for the field
  • [formData]: T | undefined - The formData for the field

Returns

  • boolean: True if the schema element has additionalProperties or patternProperties keywords, is expandable, and not at the maxProperties limit

createErrorHandler<T = any>()

Given a formData object, recursively creates a FormValidation error handling structure around it

Parameters

  • formData: T - The form data around which the error handler is created

Returns

  • FormValidation<T>: A FormValidation object based on the formData structure

dataURItoBlob()

Given the FileReader.readAsDataURL() based dataURI extracts that data into an actual Blob along with the name
of that Blob if provided in the URL. If no name is provided, then the name falls back to unknown.

Parameters

  • dataURI: string - The DataUrl potentially containing name and raw data to be converted to a Blob

Returns

  • { blob: Blob, name: string }: An object containing a Blob and its name, extracted from the URI

dateRangeOptions<S extends StrictRJSFSchema = RJSFSchema>()

Returns a list of options for a date range between start and stop.
If the start date is greater than the end date, then the date range is reversed.
If start and stop are negative numbers (or zero), then they will be treated as relative to the current year.

Parameters

  • start: number - The starting point of the date range
  • stop: number - The ending point of the date range

Returns

  • EnumOptionsType<S>[]: The list of EnumOptionsType for the date range between start and stop

Throws

  • Error when start and stop aren't both %lt;= 0 or > 0

deepEquals()

Implements a deep equals that treats all functions as equivalent and tracks circular references, so self-referential inputs do not recurse infinitely.

Parameters

  • a: any - The first element to compare
  • b: any - The second element to compare

Returns

  • boolean: True if the a and b are deeply equal, false otherwise

descriptionId()

Return a consistent id for the field description element.

Parameters

  • id: FieldPathId | string - Either simple string id or an FieldPathId from which to extract it

Returns

  • string: The consistent id for the field description element from the given id

dotNotationNameGenerator()

Generates dot-notation names for form fields. Multi-value fields are handled the same as single-value fields in dot notation.

Parameters

  • path: FieldPathList - The path of field path units to use when generating the name
  • idPrefix: string - The prefix to use at the start of the generated name
  • [_isMultiValue]: boolean | undefined - Optional flag (unused in dot notation)

Returns

  • string: The generated dot-notation name (e.g., root.tasks.0.title)

englishStringTranslator()

Translates a TranslatableString value stringToTranslate into english.
When a params array is provided, each value in the array is used to replace any of the replaceable parameters in the stringToTranslate using the %1, %2, etc. replacement specifiers.

Parameters

stringToTranslate: TranslatableString - The TranslatableString value to convert to english
[params]: string[] - The optional list of replaceable parameter values to substitute to the english string

Returns

  • string: The stringToTranslate itself with any replaceable parameter values substituted

enumOptionsDeselectValue<S extends StrictRJSFSchema = RJSFSchema>()

Removes the enum option value at the valueIndex from the currently selected (list of) value(s).
If selected is a list, then that list is updated to remove the enum option value with the valueIndex in allEnumOptions.
If it is a single value, then if the enum option value with the valueIndex in allEnumOptions matches selected, undefined is returned, otherwise the selected value is returned.

Parameters

  • valueIndex: string | number - The index of the value to be removed from the selected list or single value
  • [selected]: EnumOptionsType<S>["value"] | EnumOptionsType<S>["value"][] | undefined - The current (list of) selected value(s)
  • [allEnumOptions=[]]: EnumOptionsType<S>[] - The list of all the known enumOptions

Returns

  • EnumOptionsType<S>["value"][]: The updated selected list with the value removed from it

enumOptionSelectedValue<S extends StrictRJSFSchema = RJSFSchema>()

Computes the value to pass to a select element's value attribute.
When format is 'realValue', converts form data values to strings.
When format is 'indexed' (the default), resolves to index-based values via enumOptionsIndexForValue.
Returns emptyValue when the current value is empty.

Parameters

  • value: any - The current form data value
  • enumOptions: EnumOptionsType<S>[] | undefined - The available enum options
  • multiple: boolean - Whether the select allows multiple selections
  • [format='indexed']: OptionValueFormat - How option values are encoded on the DOM
  • emptyValue: any - The value to return when the selection is empty

Returns

  • any: The value to use for the select element's value attribute

enumOptionsIndexForValue<S extends StrictRJSFSchema = RJSFSchema>()

Returns the index(es) of the options in allEnumOptions whose value(s) match the ones in value.
All the enumOptions are filtered based on whether they are a "selected" value and the index of each selected one is then stored in an array.
If multiple is true, that array is returned, otherwise the first element in the array is returned.

Parameters

  • value: EnumOptionsType<S>["value"] | EnumOptionsType<S>["value"][] - The single value or list of values for which indexes are desired
  • [allEnumOptions=[]]: EnumOptionsType<S>[] - The list of all the known enumOptions
  • [multiple=false]: boolean - Optional flag, if true will return a list of index, otherwise a single one

Returns

  • string | string[] | undefined: A single string index for the first value in allEnumOptions, if not multiple. Otherwise, the list of indexes for (each of) the value(s) in value.

enumOptionsIsSelected<S extends StrictRJSFSchema = RJSFSchema>()

Determines whether the given value is (one of) the selected value(s).

Parameters

  • value: EnumOptionsType<S>["value"] - The value being checked to see if it is selected
  • selected: EnumOptionsType<S>["value"] | EnumOptionsType<S>["value"][] - The current selected value or list of values
  • [allEnumOptions=[]]: EnumOptionsType<S>[] - The list of all the known enumOptions

Returns

  • boolean: true if the value is one of the selected ones, false otherwise

enumOptionsSelectValue<S extends StrictRJSFSchema = RJSFSchema>()

Add the value to the list of selected values in the proper order as defined by allEnumOptions.

Parameters

  • valueIndex: string | number - The index of the value that should be selected
  • selected: EnumOptionsType<S>["value"][] - The current list of selected values
  • [allEnumOptions=[]]: EnumOptionsType<S>[] - The list of all the known enumOptions

Returns

  • EnumOptionsType<S>["value"][]: The updated list of selected enum values with value added to it in the proper location

enumOptionsValueForIndex<S extends StrictRJSFSchema = RJSFSchema>()

Returns the value(s) from allEnumOptions at the index(es) provided by valueIndex.
If valueIndex is not an array AND the index is not valid for allEnumOptions, emptyValue is returned.
If valueIndex is an array, AND it contains an invalid index, the returned array will have the resulting undefined values filtered out, leaving only valid values or in the worst case, an empty array.

Parameters

  • valueIndex: string | number | Array<string | number> - The index(es) of the value(s) that should be returned
  • [allEnumOptions=[]]: EnumOptionsType<S>[] - The list of all the known enumOptions
  • [emptyValue]: EnumOptionsType<S>["value"] | undefined - The value to return when the non-array valueIndex does not refer to a real option

Returns

  • EnumOptionsType<S>["value"] | EnumOptionsType<S>["value"][] | undefined: The single or list of values specified by the single or list of indexes if they are valid. Otherwise, emptyValue or an empty list.

enumOptionValueDecoder<S extends StrictRJSFSchema = RJSFSchema>()

Decodes a string from a DOM value attribute back to a typed enum value.
When format is 'realValue', does a reverse lookup: finds the enum option whose String(value) matches the input string and returns the original typed value.
For object/array values that were encoded as indices, falls back to index resolution.
When format is 'indexed' (the default), uses index-based resolution via enumOptionsValueForIndex.

Parameters

  • value: string | string[] - The string value(s) from the DOM
  • enumOptions: EnumOptionsType<S>[] | undefined - The available enum options
  • [format='indexed']: OptionValueFormat - How the values were encoded on the DOM
  • emptyValue: unknown - The value to return for empty/missing selections

Returns

  • unknown: The original typed enum value(s)

enumOptionValueEncoder()

Encodes an enum option value into a string for a DOM value attribute.
When format is 'realValue', primitive values are converted via String().
Non-primitive values (objects, arrays) fall back to the index since String() would produce "[object Object]".
When format is 'indexed' (the default), returns the index as a string.

Parameters

  • value: unknown - The typed enum value
  • index: number - The option's position in the enumOptions array
  • [format='indexed']: OptionValueFormat - How to encode the value for the DOM attribute

Returns

  • string: The string to use as the DOM value attribute

logUnsupportedDefaultForEnum<S extends StrictRJSFSchema = RJSFSchema>()

Logs a warning when a single-select enum widget has a schema default that is not one of its enum options.
Multi-select widgets are ignored because they do not use the same single-value default handling.

Parameters

  • id: string - The field id used in the warning message
  • schema: S - The schema whose default value is checked
  • [enumOptions]: EnumOptionsType<S>[] - The enum options available to the widget
  • [multiple=false]: boolean - Whether the widget allows multiple selections

errorId()

Return a consistent id for the field error element.

Parameters

  • id: FieldPathId | string - Either simple string id or an FieldPathId from which to extract it

Returns

  • string: The consistent id for the field error element from the given id

examplesId()

Return a consistent id for the field examples element.

Parameters

  • id: FieldPathId | string - Either simple string id or an FieldPathId from which to extract it

Returns

  • string: The consistent id for the field examples element from the given id

findSchemaDefinition<S extends StrictRJSFSchema = RJSFSchema>()

Given the name of a $ref from within a schema, using the rootSchema, look up and return the sub-schema using the path provided by that reference.
If # is not the first character of the reference, or the path does not exist in the schema, then throw an Error.
Otherwise, return the sub-schema. Also deals with nested $refs in the sub-schema.

Parameters

  • $ref: string - The ref string for which the schema definition is desired
  • [rootSchema={}]: S - The root schema in which to search for the definition

Returns

  • S: The sub-schema within the rootSchema which matches the $ref if it exists

Throws

  • Error indicating that no schema for that reference exists

getByPath<R = unknown>()

Gets the value at path of obj, returning defaultValue when the resolved value is undefined.
A bare string path is a single literal key, not a dotted path; use toPath() to split a dotted path string into segments first.
Every segment must be an own property, matching hasByPath(), so the two can be used as a guard/read pair.
Inherited members are never resolved: getByPath({}, 'toString') returns defaultValue rather than Function.prototype.toString. For the plain form data and schemas RJSF navigates, an inherited member is never data, and the own-property rule also makes prototype internals such as __proto__ unreachable unless they are genuine own data keys.

An empty segment list resolves to nothing, so defaultValue is returned rather than obj itself; this matches hasByPath(), which is false for an empty path.

The value at a runtime-computed path cannot be known statically, so R is the caller's declaration of the expected type (like Map.get()); it defaults to unknown, which forces narrowing when no type is given.

Parameters

  • obj: unknown - The object to query
  • path: ObjectPath - The single key or list of path segments at which to get the value
  • [defaultValue]: R - The value returned when the resolved value is undefined

Returns

  • R: The resolved value, otherwise defaultValue

Example

typescript
getByPath({ a: { b: 1 } }, ['a', 'b']); // 1
getByPath({ 'a.b': 1 }, 'a.b'); // 1, a bare string is one literal key
getByPath({ a: { b: 1 } }, toPath('a.b')); // 1
getByPath({ a: {} }, ['a', 'missing'], 'fallback'); // 'fallback'
getByPath({}, 'toString', 'fallback'); // 'fallback', inherited members are not read
getByPath({ a: 1 }, [], 'fallback'); // 'fallback', an empty path resolves to nothing

getChangedFields(a: unknown, b: unknown, deep?: boolean)

Compares two objects and returns the names of the fields that have changed.
This function iterates over each field of object a, using _.isEqual to compare the field value with the corresponding field value in object b.
If the values are different, the field name will be included in the returned array.

When deep is true, a field holding a nested object or a same-length array is descended into and the dotted path of the deepest field that changed is returned instead of the name of the top-level field holding it.
A key that contains a . or a [ is descended into like any other: the path it produces cannot be told apart from a path through nested keys, and neither can the entry an ErrorSchema keeps for it, since toErrorSchema() spells such a name out as a path in the same way.

Parameters

  • a: unknown - The first object, representing the original data to compare.
  • b: unknown - The second object, representing the updated data to compare.
  • [deep=false]: boolean - Optional flag that, when true, returns the dotted path of the deepest field that changed.

Returns

  • string[] : An array of field names that have changed.

Example

typescript
const a = { name: 'John', age: 30 };
const b = { name: 'John', age: 31 };
const changedFields = getChangedFields(a, b);
console.log(changedFields); // Output: ['age']

Example (deep)

typescript
const a = { items: [{ qux: '', corge: '' }] };
const b = { items: [{ qux: 'a', corge: '' }] };
console.log(getChangedFields(a, b)); // Output: ['items']
console.log(getChangedFields(a, b, true)); // Output: ['items.0.qux']

getDecimalSeparator(languages?: string | string[])

Determines the locale-specific decimal separator.
It uses the provided locale or the first locale in navigator.languages (if available) and falls back to "en".

Parameters

  • languages?: string | string[] - Optional array of locales or a single locale string.

Returns

  • string : The decimal separator character (typically '.' or ',').

Example

typescript
const separator = getDecimalSeparator('fr');
console.log(separator); // Output: ','

getDiscriminatorFieldFromSchema<S extends StrictRJSFSchema = RJSFSchema>()

Returns the discriminator.propertyName when defined in the schema if it is a string. A warning is generated when it is not a string.
Returns undefined when a valid discriminator is not present.

Parameters

  • schema: S - The schema from which the discriminator is potentially obtained

Returns

  • string | undefined: The discriminator.propertyName if it exists in the schema, otherwise undefined

getDateElementProps()

Given date & time information with optional yearRange & format, returns props for DateElement

Parameters

  • date: DateObject - Object containing date with optional time information
  • time: boolean - Determines whether to include time or not
  • [yearRange=[1900, new Date().getFullYear() + 2]]: [number, number] - Controls the list of years to be displayed
  • [format='YMD']: DateElementFormat - Controls the order in which day, month and year input element will be displayed

Returns

  • Array of props for DateElement

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

Using the schema, defaultType and options, extract out the props for the `` element that make sense.

Parameters

  • schema: S - The schema for the field provided by the widget
  • [defaultType]: string | undefined - The default type, if any, for the field provided by the widget
  • [options={}]: UIOptionsType<T, S, F> - The UI Options for the field provided by the widget
  • [autoDefaultStepAny=true]: boolean - Determines whether to auto-default step=any when the type is number and no step

Returns

  • InputPropsType: The extracted InputPropsType object

getOptionMatchingSimpleDiscriminator()

Compares the value of discriminatorField within formData against the value of discriminatorField within schema for each option. Returns index of first option whose discriminator matches formData. Returns undefined if there is no match.

This function does not work with discriminators of "type": "object" and "type": "array"

Parameters

  • [formData]: T | undefined - The current formData, if any, used to figure out a match
  • options: S[] - The list of options to find a matching options from
  • [discriminatorField]: string | undefined - The optional name of the field within the options object whose value is used to determine which option is selected

Returns

  • number | undefined: index of the matched option

getOptionValueFormat()

Resolves the effective optionValueFormat for enum-backed widgets.
Provides a single source of truth for the default DOM encoding format ('indexed') used by SelectWidget, RadioWidget, and CheckboxesWidget.
Widgets should call this helper once and pass the result to enumOptionValueEncoder, enumOptionValueDecoder, and enumOptionSelectedValue rather than reading options.optionValueFormat directly.

Parameters

  • [options]: { optionValueFormat?: OptionValueFormat } | undefined - The widget options (typically from the options prop, already resolved from ui:options and ui:globalOptions)

Returns

  • OptionValueFormat: The resolved OptionValueFormat, defaulting to 'indexed' when not set

getPropertySchema<S extends StrictRJSFSchema = RJSFSchema>()

Returns the sub-schema declared for property in the properties of schema, falling back to an empty schema when the schema has no such property.
Callers treat the properties of a schema as schemas of the same type S, which the JSONSchema7 typing of properties cannot express, so this function owns that single assertion rather than repeating it at every lookup.

Parameters

  • schema: S | undefined - The schema, if any, from which to read the property sub-schema
  • property: string - The name of the property whose sub-schema is desired

Returns

  • S: The sub-schema for property, or an empty schema when it is not declared

getSchemaType()

Gets the type of a given schema.
If the type is not explicitly defined, then an attempt is made to infer it from other elements of the schema as follows:

  • schema.const: Returns the guessType() of that value
  • schema.enum: Returns string
  • schema.properties: Returns object
  • schema.additionalProperties: Returns object
  • schema.patternProperties: Returns object
  • type is an array with a length of 2 and one type is 'null': Returns the other type

Parameters

  • schema: S - The schema for which to get the type

Returns

  • string | string[] | undefined: The type of the schema

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

Extracts any ui:submitButtonOptions from the uiSchema and merges them onto the DEFAULT_OPTIONS

Parameters

  • [uiSchema={}]: UiSchema<T, S, F> - the UI Schema from which to extract submit button props

Returns

  • UISchemaSubmitButtonOptions: The merging of the DEFAULT_OPTIONS with any custom ones

getTemplate<Name extends keyof TemplatesType<T, S, F>, T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>()

Returns the template with the given name from either the uiSchema if it is defined or from the registry
otherwise. NOTE, since ButtonTemplates are not overridden in uiSchema only those in the registry are returned.

Parameters

  • name: Name - The name of the template to fetch, restricted to the keys of TemplatesType
  • registry: Registry<T, S, F> - The Registry from which to read the template
  • [uiOptions={}]: UIOptionsType<T, S, F> - The UIOptionsType from which to read an alternate template

Returns

  • TemplatesType<T, S, F>[Name] - The template from either the uiSchema or registry for the name

getTestIds()

Returns an object of test IDs that can only be used in test mode.
If the function is called in a test environment (NODE_ENV === 'test', this is set by jest) then a Proxy object will be returned.
If a key within the returned object is accessed, if the value already exists the object will return that value, otherwise it will create that key
with a generated uuid value and return the generated ID.
If it is called outside of a test environment, the function will return an empty object, therefore returning undefined for any property within the object and excluding the prop from the rendered output of the component in which it is used.
To use this helper, you will want to generate a separate object for each component to avoid potential overlapping of ID names.
You will also want to export the object for use in tests, because the keys will be generated in the component file, and used in the test file.
Within the component file, add: export const TEST_IDS = getTestIds();
Then pass TEST_IDS.examplePropertyName as the value of the test ID attribute of the intended component.
This will allow you to use TEST_IDS.examplePropertyName within your tests, while keeping the test IDs out of your rendered output.

Returns

  • TestIdShape: An object that auto-generates test ids upon request the first time and then returns the same value on subsequent calls

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

Get all passed options from ui:options, and ui:<optionName>, returning them in an object with the ui: stripped off.
Any globalOptions will always be returned, unless they are overridden by options in the uiSchema.

Parameters

  • [uiSchema={}]: UiSchema<T, S, F> - The UI Schema from which to get any ui:xxx options
  • [globalOptions={}]: GlobalUISchemaOptions - The optional Global UI Schema from which to get any fallback xxx options

Returns

  • UIOptionsType<T, S, F> An object containing all of the ui:xxx options with the ui: stripped off along with all globalOptions

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

Given a schema representing a field to render and either the name or actual Widget implementation, returns the
React component that is used to render the widget. If the widget is already a React component, then it is wrapped
with a MergedWidget. Otherwise an attempt is made to look up the widget inside of the registeredWidgets map based
on the schema type and widget name. If no widget component can be found an Error is thrown.

Parameters

  • schema: S - The schema for the field
  • widget: Widget<T, S, F> | string - Either the name of the widget OR a Widget implementation to use
  • [registeredWidgets={}]: RegistryWidgetsType<T, S, F> - A registry of widget name to Widget implementation

Returns

  • Widget<T, S, F>: The Widget component to use

Throws

  • An error if there is no Widget component that can be returned

hasByPath()

Determines whether obj has an own property at path.
A bare string path is a single literal key, not a dotted path; use toPath() to split a dotted path string into segments first.
Every segment is checked with Object.hasOwn(), so inherited properties report false — hasByPath({}, 'toString') is false. getByPath() applies the same own-property rule, so the two can be used as a guard/read pair.

Parameters

  • obj: unknown - The object to query
  • path: ObjectPath - The single key or list of path segments to check for

Returns

  • boolean: True if the own property exists at path, otherwise false

Example

typescript
hasByPath({ a: { b: undefined } }, ['a', 'b']); // true, the key exists
hasByPath({ a: { b: 1 } }, 'a.b'); // false, there is no key named 'a.b'
hasByPath({}, 'toString'); // false, inherited properties are not own properties

hashObject()

Stringifies an object and returns the hash of the resulting string.
Sorts object fields in consistent order before stringify to prevent different hash ids for the same object.

Parameters

  • object: object - The object for which the hash is desired

Returns

  • string: The string obtained from the hash of the stringified object

hashString()

Hashes a string using the algorithm based on Java's hashing function.

Parameters

  • string: string - The string for which to get the hash

Returns

  • string: The resulting hash of the string in hex format

guessType()

Given a specific value attempts to guess the type of a schema element. In the case where we have to implicitly
create a schema, it is useful to know what type to use based on the data we are defining.

Parameters

  • value: any - The value from which to guess the type

Returns

  • string: The best guess for the object type

hashForSchema<S extends StrictRJSFSchema = RJSFSchema>()

Stringifies the schema and returns the hash of the resulting string.

Parameters

  • schema: S - The schema for which the hash is desired

Returns

  • string: The string obtained from the hash of the stringified schema

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

Detects whether the widget exists for the schema with the associated registryWidgets and returns true if it does, or false if it doesn't.

Parameters

  • schema: S - The schema for the field
  • widget: Widget<T, S, F> | string - Either the name of the widget OR a Widget implementation to use
  • [registeredWidgets={}]: RegistryWidgetsType<T, S, F> - A registry of widget name to Widget implementation

Returns

  • boolean: True if the widget exists, false otherwise

helpId()

Return a consistent id for the field help element.

Parameters

  • id: FieldPathId | string - Either simple string id or an FieldPathId from which to extract it

Returns

  • string: The consistent id for the field help element from the given id

isConstant<S extends StrictRJSFSchema = RJSFSchema>()

This function checks if the given schema matches a single constant value.
This happens when either the schema has an enum array with a single value or there is a const defined.

Parameters

  • schema: S - The schema for a field

Returns

  • boolean: True if the schema has a single constant value, false otherwise

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

Checks to see if the uiSchema contains the widget field and that the widget is not hidden

Parameters

  • uiSchema: UiSchema<T, S, F> - The UI Schema from which to detect if it is customized

Returns

  • boolean: True if the uiSchema describes a custom widget, false otherwise

isFixedItems<S extends StrictRJSFSchema = RJSFSchema>()

Detects whether the given schema contains fixed items.
This is the case when schema.items is a non-empty array that only contains objects.

Parameters

  • schema: S - The schema in which to check for fixed items

Returns

  • boolean: True if there are fixed items in the schema, false otherwise

isFormDataAvailable<T = any>()

Determines whether the given formData represents valid form data, such as a primitive type, an array, or a non-empty object.

Parameters

  • formData: T - The data to check

Returns

  • boolean: True if formData is not undefined, null, a primitive type or an array or an empty object

isObject()

Determines whether a thing is an object for the purposes of RSJF.
In this case, thing is an object if it has the type object but is NOT null, an array or a File.

Parameters

  • thing: any - The thing to check to see whether it is an object

Returns

  • boolean: True if it is a non-null, non-array, non-File object

isPlainObject()

Determines whether thing is a plain object, i.e. one created by the Object constructor or with a null prototype.
Unlike isObject(), class instances such as Error are not plain objects, which matters when recursively walking a structure whose nested values are expected to be plain data.

Parameters

  • thing: unknown - The thing to check to see whether it is a plain object

Returns

  • boolean: True if it is a plain object, otherwise false. When true, thing is narrowed to Record<string, unknown>

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

Helper to check whether a JSON schema object is the root schema. The schema is a root schema with root properties
key or a root $ref key. If the schemaToCompare has a root oneOf property, the function will
return false. Else if schemaToCompare and rootSchema are the same object or equal, the function will return
true. Else if the rootSchema has a $ref, it will be resolved using schemaUtils.resolveSchema utility. If the
resolved schema matches the schemaToCompare the function will return true. Otherwise, it will return false.

Parameters

  • registry: Registry<T, S, F> - The Registry used to get the rootSchema and schemaUtils
  • schemaToCompare: S - The JSON schema object to check. If schemaToCompare is an root schema, the function will return true.

Returns

  • boolean: True if the uiSchema describes a custom widget, false otherwise

isValueEmpty()

Returns true when a form value is considered empty: null, undefined, or '' (empty string), an empty array ([]), or a plain object whose every own value is itself empty (checked recursively). Scalar values such as 0 and false are not considered empty.

Parameters

  • value: unknown - The value to check

Returns

  • boolean: True if the value is considered empty, false otherwise

labelValue()

Helper function that will return the value to use for a widget label based on hideLabel.
The fallback is used as the return value from the function when hideLabel is true.
Due to the implementation of theme components, it may be necessary to return something other than undefined to cause the theme component to not render a label.
Some themes require may false and others may require an empty string.

Parameters

  • [label]: string | ReactElement | undefined - The label string or component to render when not hidden

  • [hideLabel]: boolean| undefined - Flag, if true, will cause the label to be hidden

  • [fallback]: undefined | false | '' - One of 3 values, undefined (the default), false or an empty string

  • Returns

  • string | boolean | undefined: fallback if hideLabel is true, otherwise label

localToUTC()

Converts a local Date string into a UTC date string

Parameters

  • dateString: string - The string representation of a date as accepted by the Date() constructor

Returns

  • string | undefined: A UTC date string if dateString is truthy, otherwise undefined

lookupFromFormContext<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any, R = unknown>()

Given a React JSON Schema Form registry or formContext object, return the value associated with toLookup.
This might be contained within the lookup map in the formContext.
If no such value exists, return the fallback value.

Parameters

  • regOrFc: Registry<T, S, F> | Registry<T, S, F>['formContext'] - The @rjsf registry or form context in which the lookup will occur
  • toLookup: string - The name of the field in the lookup map in the form context to get the value for
  • [fallback]: R - The fallback value to use if the form context does not contain a value for toLookup

Returns

  • R: The value associated with toLookup in the form context or fallback

mergeDefaultsWithFormData<T = any>()

Merges the defaults object of type T into the formData of type T

When merging defaults and form data, we want to merge in this specific way:

  • objects are deeply merged
  • arrays are merged in such a way that:
    • when the array is set in form data, only array entries set in form data are deeply merged; additional entries from the defaults are ignored unless mergeExtraArrayDefaults is true, in which case the extras are appended onto the end of the form data
    • when the array is not set in form data, the default is copied over
  • scalars are overwritten/set by form data

Parameters

  • [defaults]: T | undefined - The defaults to merge
  • [formData]: T | undefined - The form data into which the defaults will be merged
  • [mergeExtraArrayDefaults=false]: boolean - If true, any additional default array entries are appended onto the formData
  • [defaultSupercedesUndefined=false]: boolean - If true, an explicit undefined value will be overwritten by the default value

Returns

  • T | undefined: The resulting merged form data with defaults

mergeObjects()

Recursively merge deeply nested objects.

Parameters

  • obj1: GenericObjectType - The first object to merge
  • obj2: GenericObjectType - The second object to merge
  • [concatArrays=false]: boolean | "preventDuplicates" - Optional flag that, when true, will cause arrays to be concatenated. Use "preventDuplicates" to merge arrays in a manner that prevents any duplicate entries from being merged.

Returns

@returns - A new object that is the merge of the two given objects

mergeSchemas()

Recursively merge deeply nested schemas.
The difference between mergeSchemas and mergeObjects is that mergeSchemas only concats arrays for values under the 'required' keyword, and when it does, it doesn't include duplicate values. NOTE: Uses shallow comparison for the duplicate checking.

Parameters

  • obj1: GenericObjectType - The first object to merge
  • obj2: GenericObjectType - The second object to merge

Returns

  • GenericObjectType: The merged schema object

optionalControlsId()

Return a consistent id for the optional data controls element

Parameters

  • id: string - The id of the parent component for the option
  • element: 'Add' | 'Msg' | 'Remove' - The element type for which to generate the id

Returns

  • string: The consistent id for the optional data controls element from the given id and element type

optionId()

Return a consistent id for the optionIndexs of a Radio or Checkboxes widget

Parameters

  • id: string - The id of the parent component for the option
  • optionIndex: number - The index of the option for which the id is desired

Returns

  • string: An id for the option index based on the parent id

noop()

A function that does nothing and returns undefined, useful as a placeholder for an optional callback or as the implementation of a mocked function.

Returns

  • void

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

Gets the list of options from the schema. If the schema has an enum list, then those enum values are returned.
The labels for the options will be extracted from ui:enumNames in the uiSchema if provided, otherwise the label will be the same as the value. If ui:enumOrder is provided, the options will be reordered accordingly.

If the schema has a oneOf or anyOf, then the value is the list of either:

  • The const values from the schema if present
  • If the schema has a discriminator and the label using either the schema.title or the value. If a uiSchema is
    provided, and it has the ui:enumNames matched with enum or it has an associated oneOf or anyOf with a list of
    objects containing ui:title then the UI schema values will replace the values from the schema.

Parameters

  • schema: S - The schema from which to extract the options list
  • [uiSchema]: UiSchema<T, S, F> - The optional uiSchema from which to get alternate labels for the options

Returns

  • { schema?: S, label: string, value: any }: The list of options from the schema

orderProperties()

Given a list of properties and an order list, returns a list that contains the properties ordered correctly.
If order is not an array, then the untouched properties list is returned.
Otherwise properties is ordered per the order list.
If order contains a '_' then any properties that are not mentioned explicity in order will be places in the location of the _.

Parameters

  • properties: string[] - The list of property keys to be ordered
  • order: string[] - An array of property keys to be ordered first, with an optional '*' property

Returns

  • string[]: A list with the properties ordered

Throws

  • Error when the properties cannot be ordered correctly

pad()

Returns a string representation of the num that is padded with leading "0"s if necessary

Parameters

  • num: number - The number to pad
  • width: number - The width of the string at which no lead padding is necessary

Returns

  • string: The number converted to a string with leading zero padding if the number of digits is less than width

parseDateString()

Parses the dateString into a DateObject, including the time information when includeTime is true

Parameters

  • dateString: string - The date string to parse into a DateObject
  • [includeTime=true]: boolean - Optional flag, if false, will not include the time data into the object

Returns

  • DateObject: The date string converted to a DateObject

Throws

  • Error when the date cannot be parsed from the string

rangeSpec<S extends StrictRJSFSchema = RJSFSchema>()

Extracts the range spec information { step?: number, min?: number, max?: number } that can be spread onto an HTML input from the range analog in the schema { multipleOf?: number, minimum?: number, maximum?: number }.

Parameters

  • schema: S - The schema from which to extract the range spec

Returns

  • RangeSpecType: A range specification from the schema

replaceStringParameters()

Potentially substitutes all replaceable parameters with the associated value(s) from the params if available.
When a params array is provided, each value in the array is used to replace any of the replaceable parameters in the inputString using the %1, %2, etc. replacement specifiers.

Parameters

  • inputString: string - The string which will be potentially updated with replacement parameters
  • [params]: string[] - The optional list of replaceable parameter values to substitute into the english string

Returns

  • string: The updated string with any replacement specifiers replaced

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

Computes the widget name a field falls back to when no ui:widget is specified, along with the enumOptions (if any) that back a select-like fallback.
The default is select when schema has enumerable options, the schema's format when a widget is registered for it, or text otherwise.

Parameters

  • schema: S - The schema for the field
  • uiSchema: UiSchema<T, S, F> | undefined - The uiSchema for the field
  • schemaUtils: SchemaUtilsType<T, S, F> - The SchemaUtilsType used to detect whether schema has enumerable options
  • [registeredWidgets={}]: RegistryWidgetsType<T, S, F> - A registry of widget name to Widget implementation

Returns

  • { defaultWidget: string, enumOptions: EnumOptionsType<S>[] | undefined }: The default widget name and the enumOptions, if any, computed along the way

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

Resolves the uiSchema for a given schema, considering ui:definitions stored in the registry.
Called at runtime for each field. When the schema contains a $ref, looks up the corresponding uiSchema definition from registry.uiSchemaDefinitions and merges it with local overrides.
For schemas with oneOf/anyOf branches, also populates uiSchema[keyword][i] for branches whose $ref matches a definition, so MultiSchemaField can read dropdown option titles.

Resolution order (later sources override earlier):

  1. ui:definitions[$ref] - base definition from registry
  2. localUiSchema - local overrides at current path

Parameters

  • schema: S - The JSON schema (may contain $ref or RJSF_REF_KEY)
  • localUiSchema: UiSchema<T, S, F> | undefined - The uiSchema at the current path (local overrides)
  • registry: Registry<T, S, F> - The registry containing uiSchemaDefinitions

Returns

  • UiSchema<T, S, F>: The resolved uiSchema with definitions merged in

schemaHasNestedConditional<S extends StrictRJSFSchema = RJSFSchema>()

Recursively checks whether the given raw schema contains a dependencies or if keyword anywhere below its top level, e.g. inside a nested object's properties, a $ref, an array's tuple items, or a patternProperties entry.
retrieveSchema() only resolves the dependencies/if declared directly on the schema it is given, so a root-level retrieved schema never reflects a conditional branch switch that happens deeper in the tree.
Form uses this to detect when a comparison of root-level retrieved schemas can't be trusted to decide whether sanitization is needed.

Parameters

  • schema: S | boolean | undefined - The raw schema node to search
  • rootSchema: S - The root schema, used to resolve any $refs encountered while searching
  • atRoot: boolean = true - Whether schema is the root of the search, whose own dependencies/if don't count
  • seenRefs: string[] = [] - The $refs already resolved along this branch of the search, to guard against cycles

Returns

  • boolean: True if a dependencies or if keyword exists below the root of the schema

schemaRequiresTrueValue<S extends StrictRJSFSchema = RJSFSchema>()

Check to see if a schema specifies that a value must be true. This happens when:

  • schema.const is truthy
  • schema.enum == [true]
  • schema.anyOf or schema.oneOf has a single value which recursively returns true
  • schema.allOf has at least one value which recursively returns true

Parameters

  • schema: S - The schema to check

Returns

  • boolean: True if the schema specifies a value that must be true, false otherwise

setByPath<O>()

Sets value at path of obj, mutating and returning obj.
A bare string path is a single literal key, not a dotted path; use toPath() to split a dotted path string into segments first.
Missing intermediate containers are created: arrays when the next segment is a valid array index, plain objects otherwise, or always plain objects when createIntermediateObjects is true.
A path containing a __proto__ segment is refused and obj is returned unmodified, preventing prototype pollution. constructor and prototype are legal JSON Schema property names and are written normally: intermediate containers are read as own properties only, so ['constructor', 'prototype', 'x'] shadows constructor with a fresh object instead of reaching Object.prototype.

Parameters

  • obj: O - The object to modify
  • path: ObjectPath - The single key or list of path segments at which to set the value
  • value: unknown - The value to set
  • [createIntermediateObjects=false]: boolean - When true, always create plain objects for missing intermediate containers, even for numeric path segments

Returns

  • O: The mutated obj

Example

typescript
setByPath({}, ['a', 'b'], 1); // { a: { b: 1 } }
setByPath({}, ['a', 0], 1); // { a: [1] }, a numeric next segment creates an array
setByPath({}, ['a', 0], 1, true); // { a: { 0: 1 } }, createIntermediateObjects forces an object
setByPath({}, 'a.b', 1); // { 'a.b': 1 }, a bare string is one literal key

shallowEquals()

Implements a shallow equals comparison that uses Object.is() for comparing values.
This function compares objects by checking if all keys and their values are equal using Object.is().

Parameters

  • a: any - The first element to compare
  • b: any - The second element to compare

Returns

  • boolean: True if the a and b are shallow equal, false otherwise

shouldRender()

Determines whether the given component should be rerendered by comparing its current set of props and state against the next set.
If either of those two sets are not the same, then the component should be rerendered.

Parameters

  • component: React.Component - A React component being checked
  • nextProps: any - The next set of props against which to check
  • nextState: any - The next set of state against which to check

Returns

  • True if boolean: the component should be re-rendered, false otherwise

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

Determines whether the field information from the combination of schema and required along with the
enableOptionalDataFieldForType settings from the global UI options in the registry all indicate that this field
should be rendered with the Optional Data Controls UI.

Parameters

  • registry: Registry<T, S, F> - The registry object
  • schema: S - The schema for the field
  • required - Flag indicating whether the field is required
  • [uiSchema]: UiSchema<T, S, F> - The optional uiSchema for the field

Returns

  • boolean: True if the field should be rendered with the optional field UI, otherwise false

sortedJSONStringify()

Stringifies an object, sorts object fields in consistent order before stringifying it.

Parameters

  • object: object - The object for which the sorted stringify is desired

Returns

  • string: The stringified object with keys sorted in a consistent order

titleId()

Return a consistent id for the field title element.

Parameters

  • id: FieldPathId | string - Either simple string id or an FieldPathId from which to extract it

Returns

  • string: The consistent id for the field title element from the given id

toConstant<S extends StrictRJSFSchema = RJSFSchema>()

Returns the constant value from the schema when it is either a single value enum or has a const key.
Otherwise, throws an error.

Parameters

  • schema: S - The schema from which to obtain the constant value

Returns

  • string | number | boolean: The constant value for the schema

Throws

  • Error when the schema does not have a constant value

toDateString()

Returns a UTC date string for the given dateObject.
If time is false, then the time portion of the string is removed.

Parameters

  • dateObject: DateObject - The DateObject to convert to a date string
  • [time=true]: boolean - Optional flag used to remove the time portion of the date string if false

Returns

  • string: The UTC date string

toErrorList<T = any>()

Converts an errorSchema into a list of RJSFValidationErrors

Parameters

  • errorSchema: ErrorSchema<T> - The ErrorSchema instance to convert
  • [fieldPath=[]]: string[] | undefined - The current field path, defaults to [] if not specified

Returns

  • RJSFValidationErrors[]: The list of RJSFValidationErrors extracted from the errorSchema

toErrorSchema<T = any>()

Transforms a RJSF validation errors list into an ErrorSchema

ts
const changesThis = [
  { property: '.level1.level2[2].level3', message: 'err a', stack: '.level1.level2[2].level3 err a' },
  { property: '.level1.level2[2].level3', message: 'err b', stack: '.level1.level2[2].level3 err b' },
  { property: '.level1.level2[4].level3', message: 'err b', stack: '.level1.level2[4].level3 err b' },
];
const intoThis = {
  level1: {
    level2: {
      2: { level3: { errors: ['err a', 'err b'] } },
      4: { level3: { errors: ['err b'] } },
    },
  },
};

Parameters

  • errors: RJSFValidationError[] - The list of RJSFValidationError objects

Returns

  • ErrorSchema<T>: The ErrorSchema built from the list of RJSFValidationErrors

toFieldPathId()

Constructs the FieldPathId for fieldPath. If parentPathId is provided, the fieldPath is appended to the end
of the parent path. Then the ID_KEY of the resulting FieldPathId is constructed from the idPrefix and
idSeparator contained within the globalFormOptions. If fieldPath is passed as an empty string, it will simply
generate the path from the parentPath (if provided) and the idPrefix and idSeparator

Parameters

  • fieldPath: string | number - The property name or array index of the current field element
  • globalFormOptions: GlobalFormOptions - The GlobalFormOptions used to get the idPrefix and idSeparator
  • [parentPath]: FieldPathId | FieldPathList | undefined - The optional FieldPathId or FieldPathList of the parent element for this field element

Returns

  • FieldPathId: The FieldPathId for the given fieldPath and the optional parentPathId

toPath()

Converts a dotted path string, such as the property of a validation error, into its list of path segments.
Array indexes may be written bracketed ('a[0].b') or dotted ('a.0.b'), and empty segments — from a leading ., a trailing . or a .. run — are dropped.
Only the grammar RJSF itself produces is supported: dots and brackets are always separators, so quoted keys are not recognized and keys containing dots must be addressed with a segment list instead of a string.

Parameters

  • path: string - The string path to convert, such as '.level1.level2[2].level3'

Returns

  • string[]: The list of path segments, such as ['level1', 'level2', '2', 'level3']

Example

typescript
toPath('.level1.level2[2].level3'); // ['level1', 'level2', '2', 'level3']
toPath('a.0.b'); // ['a', '0', 'b']
getByPath(formData, toPath(error.property)); // the usual pairing with the path utilities

unsetByPath()

Removes the own property at path of obj, mutating obj.
A bare string path is a single literal key, not a dotted path; use toPath() to split a dotted path string into segments first.

Parameters

  • obj: unknown - The object to modify
  • path: ObjectPath - The single key or list of path segments at which to remove the property

Returns

  • boolean: True if the property was removed or did not exist, otherwise false. A non-configurable property returns false rather than throwing in strict mode

Example

typescript
const obj = { a: { b: 1 } };
unsetByPath(obj, ['a', 'b']); // true, obj is now { a: {} }
unsetByPath(obj, ['a', 'missing']); // true, nothing to remove

unwrapErrorHandler<T = any>()

Unwraps the errorHandler structure into the associated ErrorSchema, stripping the addError() functions from it

Parameters

  • errorHandler: FormValidation<T> - The FormValidation error handling structure

Returns

  • ErrorSchema<T>: The ErrorSchema resulting from the stripping of the addError() function

useAltDateWidgetProps<T = unknown, S extends StrictRJSFSchema = RJSFSchema,F extends FormContextType = any>`()

Hook which encapsulates the logic needed to render an AltDateWidget with optional time elements. It contains
the state of the current date(/time) selections in the widget. It returns a UseAltDateWidgetResult object
that contains the elements: DateElementProp[] and three callbacks needed to change one of the rendered elements,
and to handle the clicking of the clear and setNow buttons.

Parameters

  • props: WidgetProps<T, S, F> - The WidgetProps for the AltDateWidget

Returns

  • UseAltDateWidgetResult: The UseAltDateWidgetResult to be used within a AltDateWidget implementation

useDeepCompareMemo<T = unknown>()

Hook that stores and returns a T. If newValue is the same as the stored one, then the stored one is returned to
avoid having a component rerender due it being a different object. Otherwise, the newValue is stored and returned.

Parameters

  • newValue: T - The potential new T value

Returns

  • T: The latest stored T value

useFileWidgetProps()

Hook which encapsulates the logic needed to read and convert a value of File or File[] into the
filesInfo: FileInfoType[] and the two callback implementations needed to change the list or to remove a
File from the list. To be used by theme specific FileWidget implementations.

Parameters

  • value: string | string[] | undefined | null - The current value of the FileWidget
  • onChange: (value: string | null | (string | null)[]) => void - The onChange handler for the FileWidget
  • [multiple=false] - Flag indicating whether the control supports multiple selections

Returns

  • UseFileWidgetPropsResult: The UseFileWidgetPropsResult to be used within a FileWidget implementation

utcToLocal()

Converts a UTC date string into a local Date format

Parameters

  • jsonDate: string - A UTC date string

Returns

  • string: An empty string when jsonDate is falsey, otherwise a date string in local format

validationDataMerge<T = any>()

Merges the errors in additionalErrorSchema into the existing validationData by combining the hierarchies in the two ErrorSchemas and then appending the error list from the additionalErrorSchema obtained by calling toErrorList() on the errors in the validationData.
If no additionalErrorSchema is passed, then validationData is returned.

Parameters

  • validationData: ValidationData<T> - The current ValidationData into which to merge the additional errors
  • [additionalErrorSchema]: ErrorSchema<T> | undefined - The optional additional set of errors in an ErrorSchema
  • [preventDuplicates=false]: boolean - Optional flag, if true, will call mergeObjects() with preventDuplicates

Returns

  • ValidationData<T>: The validationData with the additional errors from additionalErrorSchema merged into it, if provided.

withIdRefPrefix<S extends StrictRJSFSchema = RJSFSchema>()

Recursively prefixes all $refs in a schema with the value of the ROOT_SCHEMA_PREFIX constant.
This is used in isValid to make references to the rootSchema

Parameters

  • schemaNode: S - The object node to which a ROOT_SCHEMA_PREFIX is added when a $ref is part of it

Returns

  • S: A copy of the schemaNode with updated $refs

Validator-based utility functions

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

Finds the field at the given path within the root or a nested schema node, following oneOf / anyOf using formData where needed. If nothing matches the path, { field: undefined, isRequired: undefined } is returned. When a leaf is found, the result includes whether that leaf is required under its parent.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be forwarded to all the APIs
  • rootSchema: S - The root schema that will be forwarded to all the APIs
  • schema: S - The node within the JSON schema in which to search
  • path: SchemaFieldPath - Dotted path or segment list to the desired field; see SchemaFieldPath
  • [formData={}]: T - The form data that is used to determine which anyOf/oneOf option to descend
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • FoundFieldType<S>: An object that contains the field and its required state. If no field can be found then { field: undefined, isRequired: undefined } is returned.

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

Finds the option inside the schema['any/oneOf'] list which has the properties[selectorField].default or properties[selectorField].const that matches the formData[selectorField] value.
For the purposes of this function, selectorField is either schema.discriminator.propertyName or fallbackField.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be forwarded to all the APIs
  • rootSchema: S | undefined - The root schema that will be forwarded to all the APIs
  • schema: S - The schema element in which to search for the selected anyOf/oneOf option
  • fallbackField: string - The field to use as a backup selector field if the schema does not have a required field
  • xxx: 'anyOf' | 'oneOf' - Either anyOf or oneOf, defines which value is being sought
  • [formData={}]: T - The form data that is used to determine which anyOf/oneOf option to descend
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • S | undefined: The anyOf/oneOf option that matches the selector field in the schema or undefined if nothing is selected

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

Returns the superset of formData that includes the given set updated to include any missing fields that have computed to have defaults provided in the schema.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • theSchema: S - The schema for which the default state is desired
  • [formData]: T | undefined - The current formData, if any, onto which to provide any missing defaults
  • [rootSchema]: S | undefined - The root schema, used to primarily to look up $refs
  • [includeUndefinedValues=false]: boolean | "excludeObjectChildren" - Optional flag, if true, cause undefined values to be added as defaults. If "excludeObjectChildren", cause undefined values for this object and pass includeUndefinedValues as false when computing defaults for any nested object properties.
  • [experimental_defaultFormStateBehavior]: Experimental_DefaultFormStateBehavior - See Form documentation for the experimental_defaultFormStateBehavior prop
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop
  • [initialDefaultsGenerated]: boolean - Optional flag, indicates whether or not initial defaults have been generated

Returns

  • T: The resulting formData with all the defaults provided

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

Determines whether the combination of schema and uiSchema properties indicates that the label for the schema should be displayed in a UI.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • schema: S - The schema for which the display label flag is desired
  • [uiSchema={}]: UiSchema<T, S, F> - The UI schema from which to derive potentially displayable information
  • [rootSchema]: S | undefined - The root schema, used to primarily to look up $refs
  • [globalOptions={}]: GlobalUISchemaOptions - The optional Global UI Schema from which to get any fallback xxx options

Returns

  • boolean: True if the label should be displayed or false if it should not

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

Determines which of the given options provided most closely matches the formData.
Returns the index of the option that is valid and is the closest match, or 0 if there is no match.

The closest match is determined using the number of matching properties, and more heavily favors options with matching readOnly, default, or const values.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • rootSchema: S - The root schema, used to primarily to look up $refs
  • [formData]: T | undefined - The current formData, if any, used to figure out a match
  • options: S[] - The list of options to find a matching options from
  • [selectedOption=-1]: number - The index of the currently selected option, defaulted to -1 if not specified
  • [discriminatorField]: string | undefined - The optional name of the field within the options object whose value is used to determine which option is selected
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • number: The index of the option that is the closest match to the formData or the selectedOption if no match

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

Determines whether the combination of schema and uiSchema properties indicates that the label for the schema should be displayed in a UI.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • schema: S - The schema for which the display label flag is desired
  • [uiSchema={}]: UiSchema<T, S, F> - The UI schema from which to derive potentially displayable information
  • [rootSchema]: S | undefined - The root schema, used to primarily to look up $refs
  • [globalOptions={}]: GlobalUISchemaOptions - The optional Global UI Schema from which to get any fallback xxx options
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • boolean: True if the label should be displayed or false if it should not

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

Reads the value at path within a schema, additionally retrieving $refs as needed to resolve schemas containing potentially nested $refs.
The path accepts a SchemaFieldPath (dotted string or FieldPathList-style segment array).

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be forwarded to all the APIs
  • rootSchema: S - The root schema that will be forwarded to all the APIs
  • schema: S - The current node within the JSON schema recursion
  • path: SchemaFieldPath - Dotted path or segment list to the desired field; see SchemaFieldPath
  • defaultValue: T | S - The value to return if a value is not found for the pathList path
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • T | S: The inner schema from the schema for the given path or the defaultValue if not found

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

Given the formData and list of options, attempts to find the index of the first option that matches the data.
Always returns the first option if there is nothing that matches.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • [formData]: T | undefined - The current formData, if any, used to figure out a match
  • options: S[] - The list of options to find a matching options from
  • rootSchema: S - The root schema, used to primarily to look up $refs
  • [discriminatorField]: string | undefined - The optional name of the field within the options object whose value is used to determine which option is selected

Returns

  • number: The index of the first matched option or 0 if none is available

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

Checks to see if the schema combination represents a multi-select

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • schema: S - The schema for which check for a multi-select flag is desired
  • [rootSchema]: S | undefined - The root schema, used to primarily to look up $refs
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • boolean: True if schema contains a multi-select, otherwise false

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

Checks to see if the schema combination represents a select

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • theSchema: S - The schema for which check for a select flag is desired
  • [rootSchema]: S | undefined - The root schema, used to primarily to look up $refs
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • boolean: True if schema contains a select, otherwise false

relaxOptionsForScoring<S extends StrictRJSFSchema = RJSFSchema>()

Normalises a list of oneOf/anyOf options for use in option-scoring only (not for filtering).
Boolean schemas are converted to their object equivalents (true → {}, false → {not:{}}).
When resolveRefs is true, each object option is first passed through resolveAllReferences so that $ref-based options expose their additionalProperties constraint before relaxation.
Any option whose additionalProperties is false is widened to true so that getClosestMatchingOption / validator.isValid() does not produce false negatives when the form data contains keys not listed in properties.

Parameters

  • options: Array<S | boolean> - The raw oneOf/anyOf array, which may contain boolean schemas
  • [resolveRefs=false]: boolean - When true, resolve $refs in each option before relaxing; pass rootSchema as well. Set false (default) when refs are already resolved at the call site
  • [rootSchema]: S | undefined - Required when resolveRefs is true; the root schema used to look up $refs

Returns

  • S[]: A new array of plain schema objects with additionalProperties relaxed where needed

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

NOTE: This function is deprecated and will be removed in a future release. The equivalent pruning behavior is now built into omitExtraData — use that instead.

Recursively removes optional objects from the formData that are empty (i.e., all their fields are undefined, null, empty strings, or themselves empty optional objects).
This solves the problem where interacting with fields inside an optional object "activates" it permanently, making the form unsubmittable when the optional object has required inner fields.
An object property is considered "optional" when it is NOT listed in its parent schema's required array.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • schema: S - The JSON schema describing the formData
  • [rootSchema]: S | undefined - The root schema, used primarily to look up $refs
  • [formData]: T | undefined - The current form data to prune

Returns

  • T | undefined: A new copy of formData with empty optional objects removed, or undefined if the entire formData was pruned

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

Retrieves an expanded schema that has had all of its conditions, additional properties, references and dependencies
resolved and merged into the schema given a validator, rootSchema and rawFormData that is used to do the
potentially recursive resolution.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be forwarded to all the APIs
  • schema: S - The schema for which retrieving a schema is desired
  • [rootSchema={}]: S - The root schema that will be forwarded to all the APIs
  • [rawFormData]: T | undefined - The current formData, if any, to assist retrieving a schema
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • RJSFSchema: The schema having its conditions, additional properties, references and dependencies resolved

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

Takes a schema and formData and returns a copy of the formData with any fields not defined in the schema removed.
This is useful for ensuring that only data that is relevant to the schema is preserved.
Objects with additionalProperties keyword set to true will not have their extra fields removed.

ts
const schema = {
  type: 'object',
  properties: {
    child1: {
      type: 'object',
      properties: {
        name: { type: 'string' },
      },
    },
    child2: {
      type: 'object',
      properties: {
        name: { type: 'string' },
      },
      additionalProperties: true,
    },
  },
};

const formData = {
  child1: {
    name: 'John Doe',
    extraField: 'This should be removed',
  },
  child2: {
    name: 'Jane Doe',
    extraField: 'This should NOT be removed',
  },
};

const filteredFormData = omitExtraData(validator, schema, schema, formData);
console.log(filteredFormData);
/*
{
  child1: {
    name: "John Doe",
  },
  child2: {
    name: "Jane Doe",
    extraField: "This should NOT be removed",
  },
}
*/

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • schema: S - The schema to use for filtering the formData
  • [rootSchema]: S | undefined - The root schema, used to primarily to look up $refs
  • [formData]: T | undefined - The formData to filter

Returns

  • T: The new form data, with any fields not defined in the schema removed

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

Sanitize the data associated with the oldSchema so it is considered appropriate for the newSchema.
If the new schema does not contain any properties, then undefined is returned to clear all the form data.
Due to the nature of schemas, this sanitization happens recursively for nested objects of data.
Also, any properties in the old schema that are non-existent in the new schema are set to undefined.

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • rootSchema: S - The root JSON schema of the entire form
  • [newSchema]: S | undefined - The new schema for which the data is being sanitized
  • [oldSchema]: S | undefined - The old schema from which the data originated
  • [data={}]: any - The form data associated with the schema, defaulting to an empty object when undefined
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • T: The new form data, with all the fields uniquely associated with the old schema set to undefined. Will return undefined if the new schema is not an object containing properties.

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

NOTE: This function is deprecated and will be removed as an exported @rjsf/utils function in a future release.

Generates an PathSchema object for the schema, recursively

Parameters

  • validator: ValidatorType<T, S, F> - An implementation of the ValidatorType interface that will be used when necessary
  • schema: S - The schema for which the PathSchema is desired
  • [name='']: string - The base name for the schema
  • [rootSchema]: S | undefined - The root schema, used to primarily to look up $refs
  • [formData]: T | undefined - The current formData, if any, to assist retrieving a schema
  • [experimental_customMergeAllOf]: Experimental_CustomMergeAllOf<S> - See Form documentation for the experimental_customMergeAllOf prop

Returns

  • PathSchema<T> - The PathSchema object for the schema

Schema utils creation function

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

Creates a SchemaUtilsType interface that is based around the given validator and rootSchema parameters.
The resulting interface implementation will forward the validator and rootSchema to all the wrapped APIs.

Parameters

  • validator: ValidatorType<T, S, F> - an implementation of the ValidatorType interface that will be forwarded to all the APIs
  • rootSchema: S - The root schema that will be forwarded to all the APIs

Returns

  • SchemaUtilsType<T, S, F> - An implementation of a SchemaUtilsType interface

ErrorSchema builder class

ErrorSchemaBuilder<T = any>(initialSchema?: ErrorSchema<T>) constructor

The ErrorSchemaBuilder&lt;T> is used to build an ErrorSchema&lt;T> since the definition of the ErrorSchema type is designed for reading information rather than writing it.
Use this class to add, replace or clear errors in an error schema by using either dotted path or an array of path names.
Once you are done building the ErrorSchema, you can get the result and/or reset all the errors back to an initial set and start again.

Parameters

  • [initialSchema]: ErrorSchema<T> | undefined - The optional set of initial errors, that will be cloned into the class

Returns

  • ErrorSchemaBuilder<T> - The instance of the ErrorSchemaBuilder class

ErrorSchema getter function

Returns the ErrorSchema that has been updated by the methods of the ErrorSchemaBuilder

Usage:

ts
import { ErrorSchemaBuilder, ErrorSchema } from "@rjsf/utils";

const builder = new ErrorSchemaBuilder();

// Do some work using the builder
...

const errorSchema: ErrorSchema = builder.ErrorSchema;

resetAllErrors()

Resets all errors in the ErrorSchemaBuilder back to the initialSchema if provided, otherwise an empty set.

Parameters

  • [initialSchema]: ErrorSchema<T> | undefined - The optional set of initial errors, that will be cloned into the class

Returns

  • ErrorSchemaBuilder<T> - The instance of the ErrorSchemaBuilder class

addErrors()

Adds the errorOrList to the list of errors in the ErrorSchema at either the root level or the location within the schema described by the pathOfError.
The path is either a dotted string, with optional bracketed array indexes such as 'level1.level2[2]', or a list of segments; see toPath() for the grammar a string path accepts.

Parameters

  • errorOrList: string | string[] - The error or list of errors to add into the ErrorSchema
  • [pathOfError]: string | (string | number)[] | undefined - The optional path into the ErrorSchema at which to add the error(s)

Returns

  • ErrorSchemaBuilder<T> - The instance of the ErrorSchemaBuilder class

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.
The path is either a dotted string, with optional bracketed array indexes such as 'level1.level2[2]', or a list of segments; see toPath() for the grammar a string path accepts.

Parameters

  • errorOrList: string | string[] - The error or list of errors to add into the ErrorSchema
  • [pathOfError]: string | (string | number)[] | undefined - The optional path into the ErrorSchema at which to add the error(s)

Returns

  • ErrorSchemaBuilder<T> - The instance of the ErrorSchemaBuilder class

clearErrors()

Clears the error(s) in the ErrorSchema at either the root level or the location within the schema described by the pathOfError.
The path is either a dotted string, with optional bracketed array indexes such as 'level1.level2[2]', or a list of segments; see toPath() for the grammar a string path accepts.

Parameters

  • [pathOfError]: string | (string | number)[] | undefined - The optional path into the ErrorSchema at which to add the error(s)

Returns

  • ErrorSchemaBuilder<T> - The instance of the ErrorSchemaBuilder class

Packages Docs Docs Api Reference Validator Ajv8 (`packages/docs/docs/api-reference/validator-ajv8.md`)

@rjsf/validator-ajv8 APIs

In RJSF version 6, the original, embedded AJV 6 validator implementation from earlier versions was removed in favor of the @rjsf/validator-ajv8 package.
@rjsf/validator-ajv8 uses the AJV 8 package, including adding support for using precompiled validators.
Below are the exported API functions that are provided by this package.
See the Validation documentation for examples of using these APIs.

Types

There are a few Typescript types that are exported by @rjsf/validator-ajv8 in support of the APIs.

These types can be found on GitHub here.

APIs

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

Creates and returns a customized implementation of the ValidatorType with the given customization options if provided.
If a localizer is provided, it is used to translate the messages generated by the underlying AJV validation.

Parameters

  • [options={}]: CustomValidatorOptionsType - The optional map of CustomValidatorOptionsType options that are used to create the ValidatorType instance. Supported options:
    • additionalMetaSchemas: Additional meta schemas the validator can access
    • customFormats: Additional custom format validators
    • ajvOptionsOverrides: Config overrides passed to the AJV constructor
    • ajvFormatOptions: Options for ajv-formats; pass false to disable format support entirely
    • AjvClass: The AJV class to construct (e.g. Ajv2019, Ajv2020)
    • extenderFn: A function called to extend the AJV instance (e.g. ajvErrors())
    • suppressDuplicateFiltering: Controls filtering of duplicate anyOf/oneOf errors using the SuppressDuplicateFilteringType type. 'none' (default) filters duplicates for both; 'anyOf' suppresses filtering for anyOf (oneOf duplicates still filtered); 'oneOf' suppresses filtering for oneOf (anyOf duplicates still filtered); 'all' disables all duplicate filtering.
  • [localizer]: Localizer | undefined - If provided, is used to localize a list of Ajv ErrorObjects after running the form validation using AJV

Returns

  • AJV8Validator<T, S, F>: The custom validator implementation resulting from the set of parameters provided

compileSchemaValidators<S extends StrictRJSFSchema = RJSFSchema>()

The function used to compile a schema into an output file in the form that allows it to be used as a precompiled validator.
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

  • schema: S - The schema to be compiled into a set of precompiled validators functions
  • output: string - The name of the file into which the precompiled validator functions will be generated
  • [options={}]: CustomValidatorOptionsType - The set of CustomValidatorOptionsType information used to alter the AJV validator used for compiling the schema. They are the same options that are passed to the customizeValidator() function in order to modify the behavior of the regular AJV-based validator.

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

  • validateFns: ValidatorFunctions - The map of the validation functions that are created by the compileSchemaValidators() function
  • rootSchema: S - The root schema that was used with the compileSchemaValidators() function
  • [localizer]: Localizer | undefined - If provided, is used to localize a list of Ajv ErrorObjects after running the form validation using AJV
  • [suppressDuplicateFiltering]: SuppressDuplicateFilteringType | undefined - Controls filtering of duplicate anyOf/oneOf errors. See customizeValidator() for full description of each value.

Returns

  • ValidatorType<T, S, F>: The precompiled validator implementation resulting from the set of parameters provided

Packages Docs Docs Api Reference Validator Ata (`packages/docs/docs/api-reference/validator-ata.md`)

@rjsf/validator-ata APIs

@rjsf/validator-ata is an alternative to @rjsf/validator-ajv8, backed by ata-validator instead of AJV.
The public surface mirrors the AJV package, so swapping the import is enough for the form to keep working: customizeValidator(), ValidatorType<T, S, F>, custom formats, transformErrors, customValidate, and suppressDuplicateFiltering all behave the same.

See the Validation documentation for examples of using these APIs.

Differences from `@rjsf/validator-ajv8`

  • AJV-only options (AjvClass, ajvFormatOptions, ajvOptionsOverrides) are not accepted. The closest equivalent is ataOptionsOverrides, which is spread on top of the default ata-validator options.
  • The ata-validator format set is always installed, so there is no opt-in flag for formats.
  • ata-validator's error params are frozen, so the pre-quote pass that validator-ajv8 runs for ajv-i18n is unnecessary. Localizers that mutate message in place still work as-is.
  • Precompiled validators (compileSchemaValidators / createPrecompiledValidator) are supported. ata-validator's bundleStandalone output is adapted into the validator function map the precompiled consumer expects. Error output matches the non-precompiled validator, including per-field errors for schema-valued additionalProperties (with ata-validator >= 0.17.4); an invalid anyOf reports a single error on the field, the same as the runtime path. One constraint carries over from the standalone (AOT) path: custom formats must be a RegExp or pre-anchored string pattern, since a function checker cannot be serialized into the bundle and is rejected at compile time.

Types

There are a few TypeScript types that are exported by @rjsf/validator-ata in support of the APIs. These types can be found on GitHub here.

APIs

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

Creates and returns a customized implementation of the ValidatorType with the given customization options if provided.
If a localizer is provided, it is used to translate the messages generated by the underlying ata-validator validation.

Parameters

  • [options={}]: CustomValidatorOptionsType - The optional map of CustomValidatorOptionsType options that are used to create the ValidatorType instance. Supported options:
    • additionalMetaSchemas: Additional schemas registered for cross-schema $ref resolution
    • customFormats: Custom format checkers; values can be functions, RegExps, or pre-anchored regex source strings
    • ataOptionsOverrides: Overrides spread on top of the default ata-validator options (e.g. coerceTypes, removeAdditional, verbose, abortEarly)
    • extenderFn: A function called against the constructed Validator instance for additional setup; returning a different instance is supported
    • suppressDuplicateFiltering: Controls filtering of duplicate anyOf/oneOf errors using the SuppressDuplicateFilteringType type. 'none' (default) filters duplicates for both; 'anyOf' suppresses filtering for anyOf (oneOf duplicates still filtered); 'oneOf' suppresses filtering for oneOf (anyOf duplicates still filtered); 'all' disables all duplicate filtering.
  • [localizer]: Localizer | undefined - If provided, is used to localize a list of ata-validator ValidationErrors after running the form validation

Returns

  • ValidatorType<T, S, F>: The custom validator implementation resulting from the set of parameters provided

compileSchemaValidators<S extends StrictRJSFSchema = RJSFSchema>()

Compiles a schema into an output file that can be loaded later as a precompiled validator.
The main reasons for using a precompiled validator are reducing code size, improving startup time by skipping schema compilation, and avoiding dynamic code generation when a browser's Content Security Policy forbids it.
Under the hood this calls ata-validator's bundleStandalone and wraps the result in the map the precompiled consumer expects.

NOTE: Custom formats passed through options.customFormats must be a RegExp or a pre-anchored string pattern. A function checker cannot be serialized into the standalone bundle and is rejected at compile time.

Parameters

  • schema: S - The schema to be compiled into a set of precompiled validator functions
  • output: string - The name of the file into which the precompiled validator functions are generated
  • [options={}]: CustomValidatorOptionsType - The CustomValidatorOptionsType options accepted by customizeValidator(), with limits: extenderFn, extra schemas without an $id and the ataOptionsOverrides keys coerceTypes, removeAdditional and keywords cannot be carried into the generated file and are ignored with a warning, the generated file never fills in default values, and suppressDuplicateFiltering belongs to createPrecompiledValidator(). See the precompiled section of usage/validation.md

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 ata-validator validation.

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

Parameters

  • validateFns: ValidatorFunctions - The map of the validation functions that are created by the compileSchemaValidators() function
  • rootSchema: S - The root schema that was used with the compileSchemaValidators() function
  • [localizer]: Localizer | undefined - If provided, is used to localize the list of ata-validator ValidationErrors after running the form validation
  • [suppressDuplicateFiltering]: SuppressDuplicateFilteringType | undefined - Controls filtering of duplicate anyOf/oneOf errors. See customizeValidator() for the full description of each value.

Returns

  • ValidatorType<T, S, F>: The precompiled validator implementation resulting from the set of parameters provided

Packages Docs Docs Api Reference Validator Cfworker (`packages/docs/docs/api-reference/validator-cfworker.md`)

@rjsf/validator-cfworker APIs

@rjsf/validator-cfworker is an additional, eval-free validator option for CSP-constrained applications. It is backed by @cfworker/json-schema, interprets schemas without eval or new Function, and defaults to JSON Schema draft 2020-12.

It is not an AJV replacement. See the package README for the unsupported-keyword matrix and current upstream-state notes.

Differences from `@rjsf/validator-ajv8`

  • AJV-only options and extensions such as AjvClass, $data, discriminator, and ajv-errors's errorMessage are not supported.
  • $dynamicRef and $dynamicAnchor are not currently supported by the underlying engine.
  • Error messages differ from AJV, and there is no ajv-i18n localizer equivalent. Use transformErrors to customize messages.
  • Precompiled-validator mode is not part of this initial package.
  • The wrapper normalizes undefined form-data values before validation and caches validators by schema id to make repeated RJSF isValid() calls safe.

Types

The package exports CustomValidatorOptionsType, CFWorkerValidationError, CFWorkerFormatChecker, and SuppressDuplicateFilteringType from src/types.ts.

APIs

`customizeValidator()`

Creates a ValidatorType<T, S, F> backed by @cfworker/json-schema.

Parameters

  • options.additionalMetaSchemas: additional schemas registered for cross-schema $ref resolution
  • options.customFormats: format checkers expressed as functions, regular expressions, or regular-expression source strings
  • options.draft: '4', '7', '2019-09', or '2020-12'; defaults to '2020-12'
  • options.extenderFn: hook called with every newly constructed engine validator
  • options.shortCircuit: stop at the first error; defaults to false
  • options.suppressDuplicateFiltering: 'none', 'anyOf', 'oneOf', or 'all'

Returns

  • ValidatorType<T, S, F>: the customized validator implementation
ts
import { customizeValidator } from '@rjsf/validator-cfworker';

const validator = customizeValidator({
  draft: '2020-12',
  customFormats: { slug: /^[a-z0-9-]+$/ },
});

Packages Docs Docs Json Schema Arrays (`packages/docs/docs/json-schema/arrays.md`)

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:

tsx
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:

tsx
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:

tsx
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'));

NOTE: The items property in uiSchema can also accept a function for dynamic UI schema generation based on array item data. See Dynamic UI Schema Examples for advanced use cases.

The `additionalItems` keyword

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

tsx
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:

tsx
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:

tsx
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:

tsx
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:

tsx
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:

tsx
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:

tsx
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:

tsx
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:

tsx
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:

tsx
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'));

Packages Docs Docs Json Schema Definitions (`packages/docs/docs/json-schema/definitions.md`)

Schema definitions and references

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

tsx
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.

uiSchema for Schema Definitions

To customize the UI for schemas referenced via $ref, use the ui:definitions property in your uiSchema. This works for both reused and recursive schemas.

See ui:definitions for full details and more examples.

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

const schema: RJSFSchema = {
  definitions: {
    node: {
      type: 'object',
      properties: {
        name: { type: 'string' },
        children: {
          type: 'array',
          items: { $ref: '#/definitions/node' },
        },
      },
    },
  },
  type: 'object',
  properties: {
    tree: { $ref: '#/definitions/node' },
  },
};

const uiSchema: UiSchema = {
  'ui:definitions': {
    '#/definitions/node': {
      name: { 'ui:placeholder': 'Node name' },
    },
  },
};

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

Packages Docs Docs Json Schema Dependencies (`packages/docs/docs/json-schema/dependencies.md`)

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.

tsx
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.

tsx
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

tsx
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.

tsx
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.


Packages Docs Docs Json Schema Objects (`packages/docs/docs/json-schema/objects.md`)

Objects

Object properties

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

tsx
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:

tsx
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:

tsx
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:

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

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

Additional and pattern properties

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

tsx
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.

The patternProperties keyword allows the user to add properties with names that match one or more of the specified regular expressions

tsx
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',
    },
  },
  patternProperties: {
    '^foo+$': {
      type: 'number',
      enum: [1, 2, 3],
    },
  },
};

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

Also in this case, an add button for new properties is shown by default.

`expandable` option

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

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

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

Packages Docs Docs Json Schema Oneof (`packages/docs/docs/json-schema/oneof.md`)

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

tsx
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

tsx
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 @x0k/json-schema-merge 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"}:

tsx
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'));

Packages Docs Docs Json Schema Single (`packages/docs/docs/json-schema/single.md`)

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:

tsx
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.

tsx
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'));

Deprecated fields

The JSON Schema deprecated keyword can be used to indicate that a field is no longer supported.

The deprecated keyword is a JSON Schema Draft 2019-09 feature. You may need to configure your schema validator to properly recognize it. See the Validation documentation for more details.

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

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

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

By default, RJSF will append (deprecated) to the field label. You can customize this behavior using the deprecatedHandling option in the uiSchema. See deprecatedHandling for more details.

Enumerated values

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

tsx
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.

tsx
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'));
tsx
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'));

If you use enum in your JSON Schema, you may instead specify ui:enumNames in your uiSchema, which RJSF can use to label an enumeration. ui:enumNames can be an array (matched by index) or a map (matched by value):

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

const schema: RJSFSchema = {
  type: 'number',
  enum: [1, 2, 3],
};

// Array form (matched by index)
const uiSchema: UiSchema = {
  'ui:enumNames': ['one', 'two', 'three'],
};

// Map form (matched by value)
const uiSchema: UiSchema = {
  'ui:enumNames': { 1: 'one', 2: 'two', 3: 'three' },
};

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

Ordering `enum` fields

To control the display order of enum options, use ui:enumOrder. Use '*' to represent all remaining values in their original schema order. Unlisted values not covered by '*' are dropped.

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

const schema: RJSFSchema = {
  type: 'string',
  enum: ['apple', 'banana', 'cherry', 'date'],
};

const uiSchema: UiSchema = {
  'ui:enumOrder': ['cherry', '*', 'apple'],
};

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.

tsx
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.

tsx
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'));

Packages Docs Docs Migration Guides V2.X Upgrade Guide (`packages/docs/docs/migration-guides/v2.x upgrade guide.md`)

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)

Packages Docs Docs Migration Guides V3.X Upgrade Guide (`packages/docs/docs/migration-guides/v3.x upgrade guide.md`)

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.


Packages Docs Docs Migration Guides V4.X Upgrade Guide (`packages/docs/docs/migration-guides/v4.x upgrade guide.md`)

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


Packages Docs Docs Migration Guides V5.X Upgrade Guide (`packages/docs/docs/migration-guides/v5.x upgrade guide.md`)

5.x Upgrade Guide

Breaking changes

There were several significant breaking changes in RJSF version 5 that were necessary in order to support the following new features:

  • Schema validation was decoupled from @rjsf/core to resolve issue #2693. Additionally, in order to break a circular dependency in the validation refactor, the @rjsf/core/utils.js file was split out into its own @rjsf/utils package as was suggested in #1655.
  • The theme for Material UI version 5 (i.e. @rjsf/mui) was split out of the theme for version 4 (i.e. @rjsf/material-ui) to resolve the following issues: #2762, #2858, #2905, #2945
  • As part of the fix for #2526 all the existing templates in the previous version were moved into a new templates dictionary, similar to how widgets and fields work. This templates dictionary was added to the Registry and also the Form props, replacing the ArrayFieldTemplate, FieldTemplate, ObjectFieldTemplate and ErrorList props. In addition, several of the fields and widgets based components were moved into the templates dictionary as they were more like templates than true Fields or Widgets. Also fixes #2945
  • Fixed anyOf and oneOf getting incorrect, potentially duplicate ids when combined with array #2197
  • CheckboxesWidget, RadioWidget and SelectWidget in all themes now use indexes into enumOptions[] rather than option.value to allow for objects in enumOptions - #1494

Node support

Version 5 is dropping official support for Node 12 as it is no longer a maintained version.
Please use Node 18 when making any changes to package.json and package-lock.json files.
All PR and branch builds are running against Node 14, 16 and 18.

React version

RJSF is no longer actively supporting React version < 16.14.x.
React 17 is officially supported on all the themes where the underlying theme library also supports React 17.

Unfortunately, there is required work pending to properly support React 18, so use it at your own risk.

New packages

There are four new packages added in RJSF version 5:

  • @rjsf/utils: All of the utility functions previously imported from @rjsf/core/utils as well as the Typescript types for RJSF version 5.
    • The following new utility functions were added: ariaDescribedByIds(), createSchemaUtils(), descriptionId(), enumOptionsDeselectValue(), enumOptionsIndexForValue(), enumOptionsIsSelected(), enumOptionsSelectValue(), enumOptionsValueForIndex(), errorId(), examplesId(), getClosestMatchingOption(), getFirstMatchingOption(), getInputProps(), helpId(), mergeValidationData(), optionId(), sanitizeDataForNewSchema() and titleId()
  • @rjsf/validator-ajv6: The ajv-v6-based validator refactored out of @rjsf/[email protected], that implements the ValidatorType interface defined in @rjsf/utils.
  • @rjsf/validator-ajv8: The ajv-v8-based validator that is an upgrade of the @rjsf/validator-ajv6, that implements the ValidatorType interface defined in @rjsf/utils. See the ajv 6 to 8 migration guide for more information.
  • @rjsf/mui: Previously @rjsf/material-ui/v5, now provided as its own theme.

`id` BREAKING CHANGES

In many of the themes the ids for the Title, Description and Examples blocks were update to all have a consistent value of xxx__title, xxx__description and xxx__examples, respectively, where xxx is the id of the field.
In addition, some of the ids for various input values were updated to be consistent across themes or to fix small bugs.
For instance, the values for radio buttons in the RadioWidget and checkboxes in the CheckboxesWidget are of the form xxx-${option.value}, where xxx is the id of the field.

`enumOptions[]` widgets BREAKING CHANGES

Schemas may have enumOptions[] where values are objects rather than primitive types. Examples of such schemas have been added to the playground. These schemas did not work in RJSF prior to v5.
In every theme, the enumOptions[] rendering widgets CheckboxesWidget, RadioWidget and SelectWidget previously used the enumOptions[].value to as the value used for the underlying checkbox, radio and select.option elements.
Now, these CheckboxesWidget, RadioWidget and SelectWidget components use the index of the enumOptions[] in the list as the value for the underlying elements.
If you need to build a custom widget for this kind of enumOptions, there are a set of enumOptionsXXX functions in @rjsf/utils to support your implementation.

`@rjsf/core` BREAKING CHANGES

Types

In version 4, RJSF exported all its types directly from @rjsf/core.
In version 5, only the types for the Form component and the withTheme() HOC are exported directly from @rjsf/core.
All the rest of the types for RJSF are now exported from the new @rjsf/utils package.

NOTE: The types in @rjsf/utils have been improved significantly from those in version 4 and as a result may require you to fix your Typescript typings and add some casts.

Some of the most notable changes are:

  • RJSFSchema has replaced the use of JSON7Schema for future compatibility reasons.

    • Currently RJSFSchema is simply an alias to JSON7Schema so this change is purely a naming one.
    • It is highly recommended to update your use of JSON7Schema with RJSFSchema so that when the RJSF begins supporting a newer JSON Schema version out-of-the-box, your code won't be affected.
  • RJSFSchemaDefinition has replaced the use of JSONSchema7Definition for the same reasons.

  • The use of the generic T (defaulting to any) for the formData type has been expanded to cover all type hierarchies that use formData.

  • StrictRJSFSchema and RJSFSchema have replaced the use of JSON7Schema for future compatibility reasons.

    • RJSFSchema is StrictRJSFSchema joined with the GenericObjectType (i.e. { [key: string]: any }) to allow for additional syntax related to newer draft versions
    • All definitions of schema and rootSchema elements have been replaced with a generic that is defined as S extends StrictRJSFSchema = RJSFSchema
    • It is highly recommended to update your use of JSON7Schema with RJSFSchema since that is the default for the new generic used for schema and rootSchema
  • A new generic F (extending FormContextType defaulting to any) was added for the formContext type, and all types in the hierarchy that use formContext have had that generic added to them.

  • The new CustomValidator, ErrorTransformer, ValidationData, ValidatorType and SchemaUtilsType types were added to support the decoupling of the validation implementation.

  • The new TemplatesType, ArrayFieldDescriptionProps, ArrayFieldTitleProps, UnsupportedFieldProps, IconButtonProps, SubmitButtonProps and UIOptionsBaseType were added to support the consolidation (and expansion) of templates in the Registry and Form.

  • BREAKING CHANGE The DescriptionField and TitleField props were removed from the ArrayFieldTemplateProps and ObjectFieldTemplateProps as they can now be derived from the templates or uiSchema via the new getTemplate() utility function.

  • BREAKING CHANGE The fields prop was removed from the FieldTemplateProps as you can simply use registry.fields instead.

  • BREAKING CHANGE The showErrorList prop was changed to accept false, "top" or "bottom". true is no longer a valid value. The default value is "top", which has identical behavior to the default value/true in v4.
    You can view all these types on GitHub.

Form props

In version 5, the Form component's two optional props additionalMetaSchemas and customFormats were replaced with the new, required validator prop, in order to support the decoupling of the validation implementation.
This new validator prop is expected to be an implementation of the ValidatorType interface.
The new @rjsf/validator-ajv6 package contains the refactored implementation of the version 4 validator; It was provided for backwards compatibility with RJSF v4, and it is deprecated.
The new @rjsf/validator-ajv8 package contains the refactored implementation of the version 4 validator, that has been converted to use the Ajv 8 validator and has more capabilities than the Ajv 6 one. See the Ajv migration guide for more information.

There are two ways to use this new package to provide a validator for a Form.
First, you can simply import the default validator from the package and pass it to a Form.

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

// Your schema
const schema: RJSFSchema = { ... };

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

Second, if you were actually providing one (or both) of the removed optional props to your Form, you can continue using them by creating a customized validator.

tsx
import { RJSFSchema } from "@rjsf/utils";
import Form from "@rjsf/core";
import { customizeValidator, CustomValidatorOptionsType } from "@rjsf/validator-ajv8";

// Your schema, additionalMetaSchemas and/or customFormats
const schema: RJSFSchema = { ... };
const additionalMetaSchemas: CustomValidatorOptionsType['additionalMetaSchemas'] = [{ ... }];
const customFormats: CustomValidatorOptionsType['customFormats'] = { ... };

const validator = customizeValidator({ additionalMetaSchemas, customFormats });

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

`formElement` converted to RefObject

The formElement variable that stored the ref to the inner <form /> was converted from a simple variable assigned via a callback ref (ala React < 16.3) to a React.RefObject created using the React.createRef() API.
As a result, if you were using the formElement ref, you will need to update it to use formElement.current:

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

// Your schema
const schema: RJSFSchema = { ... };

const formRef = React.createRef();

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

...
// Previously, to reset the form one would have called:
//   formRef.current.formElement.reset();
// Now one calls:
formRef.current.formElement.current.reset();

`validate` prop renamed

Additionally, in version 5, the validate prop on Form was renamed to customValidate to avoid confusion with the new validator prop.

`fields` prop changes

In previous versions, it was possible to provide an override to the DescriptionField, TitleField and/or UnsupportedField components by providing a custom implementation in the fields prop on the Form.
Since these components do not actually support the FieldProps interface, they were moved into the templates dictionary instead.
If you were previously overriding any (or all) of these components, you can override them now via the templates prop on Form instead:

tsx
import { DescriptionFieldProps, RJSFSchema, TitleFieldProps } from "@rjsf/utils";
import Form from "@rjsf/core";
import validator from "@rjsf/validator-ajv8";

// Your schema
const schema: RJSFSchema = { ... };

// Your custom fields
const CustomDescriptionField = (props: DescriptionFieldProps) => { ... };
const CustomTitleField = (props: TitleFieldProps) => { ... };
const CustomUnsupportedField = (props: ObjectFieldTemplateProps) => { ...
};

const templates: Partial<TemplatesType> = {
  DescriptionFieldTemplate: CustomDescriptionField,
  TitleFieldTemplate: CustomTitleField,
  UnsupportedFieldTemplate: CustomUnsupportedField,
};

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

new `templates` prop

Additionally, in version 5, the ArrayFieldTemplate, FieldTemplate, ObjectFieldTemplate and ErrorList props were replaced with the templates prop as part of the TemplatesType consolidation.
If you were previously overriding any (or all) of these templates, you can simply consolidate them into the new templates prop on Form instead:

tsx
import { ArrayFieldTemplateProps, ErrorListProps, FieldTemplateProps, ObjectFieldTemplateProps, RJSFSchema } from "@rjsf/utils";
import Form from "@rjsf/core";
import validator from "@rjsf/validator-ajv8";

// Your schema
const schema: RJSFSchema = { ... };

// Your custom templates
const CustomArrayFieldTemplate = (props: ArrayFieldTemplateProps) => { ... };
const CustomFieldTemplate = (props: FieldTemplateProps) => { ... };
const CustomObjectFieldTemplate = (props: ObjectFieldTemplateProps) => { ... };
const CustomErrorField = (props: ErrorListProps) => { ... };

const templates: Partial<TemplatesType> = {
  ArrayFieldTemplate: CustomArrayFieldTemplate,
  FieldTemplate: CustomFieldTemplate,
  ObjectFieldTemplate: CustomObjectFieldTemplate,
  ErrorFieldTemplate: CustomErrorField,
};

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

NOTE: In version 5, the ArrayField implementation was refactored to add 3 additional templates for presenting arrays along with the ArrayFieldTemplate.
If you were updating the ArrayFieldTemplate to modify just a subset of the UI, it may be easier for you to implement one of the other new templates instead.
See the Custom Templates documentation for more details.

`widgets` prop change

In the previous version, it was possible to provide an override to the SubmitButton component by providing a custom implementation in the widgets prop on the Form.
Since this component only requires a tiny fraction of the WidgetProps interface, it was moved into the templates.ButtonTemplates dictionary instead with its own, reduced set of props.
If you were previously overriding this component, you can override it now via the templates prop on Form instead:

tsx
import { RJSFSchema, SubmitButtonProps } from "@rjsf/utils";
import Form from "@rjsf/core";
import validator from "@rjsf/validator-ajv8";

// Your schema
const schema: RJSFSchema = { ... };

// Your custom button
const CustomSubmitButton = (props: SubmitButtonProps) => { ...
};

const templates: Partial<TemplatesType> = {
  ButtonTemplates: {
    SubmitButton: CustomSubmitButton,
  }
};

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

utils.js

In version 5, all the utility functions that were previously accessed via import { utils } from '@rjsf/core'; are now available via import utils from '@rjsf/utils';.
Because of the decoupling of validation from @rjsf/core there is a breaking change for all the validator-based utility functions, since they now require an additional ValidatorType parameter.
More over, one previously exported function resolveSchema() is no longer exposed in the @rjsf/utils, so use retrieveSchema() instead.
Finally, the function getMatchingOption() has been deprecated in favor of getFirstMatchingOption().

If you have built custom fields or widgets that utilized any of these breaking-change functions, don't worry, there is a quick and easy solution for you.
The registry has a breaking-change which removes the previously deprecated definitions property while adding the new schemaUtils property.
This new registry.schemaUtils property implements the SchemaUtilsType interface, which allows you to call a version of each of these breaking-change functions without the need for passing either a validator or rootSchema.
Because all fields and widgets are guaranteed to be passed the registry as a prop, if your custom field/widget happens to use either the registry.definitions object or a breaking-change validator-based utility function you make the following changes:

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

function YourField(props: FieldProps) {
  const { registry } = props;
// Change `registry.definitions` to `registry.rootSchema.definitions`
// const { definitions } = registry; <- version 4
  const { rootSchema } = registry;
  const { definitions } = rootSchema;
...
}
tsx
// Change breaking-change function to schemaUtils instead, otherwise import from @rjsf/utils
// import { utils } from '@rjsf/core'; <- version 4
// const { isMultiSelect, resolveSchema, getUiOptions } = utils; <- version 4
import { RJSFSchema, WidgetProps, getUiOptions } from '@rjsf/utils';

function YourWidget(props: WidgetProps) {
  const { registry, uiSchema } = props;
  const { schemaUtils } = registry;
// const matchingOption = getMatchingOption({}, options, rootSchema); <- version 4
// const isMultiSelect = isMultiSelect(schema, rootSchema); <- version 4
// const newSchema = resolveSchema(schema, formData, rootSchema); <- version 4
  const matchingOption = schemaUtils.getFirstMatchingOption({}, options);
  const isMultiSelect = schemaUtils.isMultiSelect(schema);
  const newSchema: RJSFSchema = schemaUtils.retrieveSchema(schema, formData);
  const options = getUiOptions(uiSchema);

...
}

validator.js

Because of the decoupling of validation from @rjsf/core this file was refactored into its own @rjsf/validator-ajv8 package.
During that refactor a few breaking changes were made to how it works related to custom validation and ErrorSchema conversion.

toErrorList param changed

In previous versions, the toErrorList() function used to take a fieldName string defaulted to root, and used it to format the stack message.
In version 5, fieldName was changed to fieldPath string array defaulted to an empty array, and is used to recursively add the field name to the errors as the property object along with the raw message.
The result is that if you had an ErrorSchema that looks like:

tsx
const errorSchema: ErrorSchema = {
  __errors: ['error message 1'],
  password: { __errors: 'passwords do not match' },
};

The returned result from calling toErrorList(errorSchema) has changed as follows:

tsx
// version 4 result
[{ stack: 'root: error message 1' }, { stack: 'password: passwords do not match' }][
  // version 5 result
  ({ property: '.', message: 'error message 1', stack: '. error message 1' },
  {
    property: '.password',
    message: 'passwords do not match',
    stack: '.password passwords do not match',
  })
];

Custom validation and extraErrors

In previous versions, when using a custom validator on the Form, any errors that were generated were inconsistently inserted into the validations errors list.
In addition, there was an issue where the non-stack AJV error information was lost when custom validation generated errors.
This issue has been fixed.
Also, when extraErrors were provided, they were being inconsistently inserted into the errors list and the non-stack AJV error information was lost.
In version 5, all of these errors will be consistently appended onto the end of the validation errors list, and the additional AJV error information is maintained.

In other words, if custom validation or extraErrors produced the following ErrorSchema:

tsx
{
  __errors: [ "Please correct your password"],
  password2: { __errors: "passwords do not match" }
}

And the AJV validation produced the following ErrorSchema:

tsx
{
  __errors: [
    {
      message: 'should NOT be shorter than 3 characters',
      name: 'minLength',
      params: { limit: 3 },
      property: '.password2',
      schemaPath: '#/properties/password2/minLength',
      stack: '.password2 should NOT be shorter than 3 characters',
    },
  ];
}

The resulting errors list has changed as follows:

tsx
// version 4
[
  { stack: 'root: Please correct your password' },
  { stack: 'password2: passwords do not match' },
  { stack: 'password2: should NOT be shorter than 3 characters' },
][
  // version 5
  ({
    message: 'should NOT be shorter than 3 characters',
    name: 'minLength',
    params: { limit: 3 },
    property: '.password2',
    schemaPath: '#/properties/password2/minLength',
    stack: '.password2 should NOT be shorter than 3 characters',
  },
  {
    property: '.',
    message: 'Please correct your password',
    stack: '. Please correct your password',
  },
  {
    property: '.',
    message: 'passwords do not match',
    stack: '.password2 passwords do not match',
  })
];

Generate correct ids when arrays are combined with `anyOf`/`oneOf`

In v4, with arrays inside anyOf or oneOf, the parent name was not used to generate ids.
For example, given a schema such as:

json
{
  "type": "object",
  "properties": {
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "anyOf": [
          {
            "properties": {
              "foo": {
                "type": "string"
              }
            }
          },
          {
            "properties": {
              "bar": {
                "type": "string"
              }
            }
          }
        ]
      }
    }
  }
}

We would get fields with id root_foo and root_bar.
As you can imagine, we could end up with duplicated ids if there's actually a foo or a bar in the root of the schema.

From v5, the child fields will correctly use the parent id when generating its own id, generating ids such as root_items_0_foo.

Deprecations added in v5

getMatchingOption()

The utility function getMatchingOption() was deprecated in favor of the more aptly named getFirstMatchingOption() which has the exact same implementation.

Non-standard `enumNames` property

enumNames is a non-standard JSON Schema field that was deprecated in version 5.
enumNames could be included in the schema to apply labels that differed from an enumeration value.
This behavior can still be accomplished with oneOf or anyOf containing const values, so enumNames support will be removed from a future major version of RJSF.
For more information, see #532.

uiSchema.classNames

In versions previous to 5, uiSchema.classNames was the only property that did not require the ui: prefix.
Additionally, it did not support being added into the ui:options object.
This was fixed in version 5 to be consistent with all the other properties in the uiSchema, so the uiSchema.classNames support may be removed from a future major version of RJSF.

If you are using classNames as follows, simply add the ui: prefix to it to remove the deprecation warning that will be displayed for each uiSchema.classNames you have:

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

// This uiSchema will log a deprecation warning to the console
const uiSchemaLog: UiSchema = {
  title: {
    classNames: 'myClass',
  },
};
// This uiSchema will not
const uiSchemaNoLog: UiSchema = {
  title: {
    'ui:classNames': 'myClass',
  },
};

`@rjsf/material-ui` BREAKING CHANGES

This theme was simplified back to working only with Material UI version 4 after an unsuccessful attempt to have it fully support both versions 4 and 5 simultaneously.
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:

text
{
  ...
  "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:

text
"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:

text
{
  ...
  "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:

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

Before

tsx
import Form5 from '@rjsf/material-ui';

or

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

or

tsx
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

tsx
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

tsx
import Form from '@rjsf/mui';

or

tsx
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);

Packages Docs Docs Migration Guides V6.X Upgrade Guide (`packages/docs/docs/migration-guides/v6.x upgrade guide.md`)

6.x Upgrade Guide

New packages

There are 5 new packages added in RJSF version 6:

  • @rjsf/daisyui: This is new theme based on the daisyui toolkit
  • @rjsf/mantine: This is new theme based on the mantine toolkit
  • @rjsf/primereact: This is a new theme based on the PrimeReact toolkit
  • @rjsf/react-bootstrap: This is rename of the bootstrap-4 theme with an upgrade to the latest version of react-bootstrap
  • @rjsf/shadcn: This is new theme based on the shadcn toolkit

New deprecations

UiSchema.rootFieldId

The ui:rootFieldId notation on UiSchema was deprecated in favor of Form.idPrefix.
This notation will be removed in a future major version release

@rjsf/semantic-ui

The semantic-ui theme is deprecated and will be removed in a future major version release unless sematic-ui-react version 3 is released with React 19 support.
Although that seems unlikely as no changes have been made to version 3 since December 2023.

Breaking changes

CJS build changes

Due to making all of the package.json files for the @rjsf/* libraries include "type": "module" to better support modern ESM builds, the generation of the Common JS distributions were updated to produce .cjs files rather than .js files.
Hopefully this will not cause any issues with existing uses of the libraries. If so, one may need to switch from doing an import of the CJS build to doing a require().

Theme removals

The following themes were removed due to duplication of a framework with a newer theme

bootstrap-4

The older bootstrap-4 theme has been removed in favor of the react-bootstrap theme

fluent-ui

The older fluent-ui theme has been removed in favor of the fluentui-rc theme

material-ui

The older material-ui theme has been removed in favor of the mui theme

validator-ajv6

This deprecated validator has been removed. Use the validator-ajv8.

Theme version support changes

@rjsf/antd

Version 6 is dropping official support for antd version 4. You must upgrade to version 5.

@rjsf/chakra-ui

Version 6 is dropping official support for @chakra-ui version 2. You must upgrade to version 3. We are also requiring
chakra-react-select version >=6 as a result.

@mui version 5 and 6

Version 6 is dropping official support for @mui/material and @mui/icons-material versions 5 and 6 due to the adoption
of breaking changes in version 7. You must upgrade to version 7.

@rjsf/semantic-ui

Version 6 is dropping official support for semantic-ui-react version 1. You must upgrade to version 2.

Node support

Version 6 is dropping official support for Node 14, 16, and 18 as they are no longer maintained versions.
Please use Node 22 when making any changes to package.json and package-lock.json files.
All PR and branch builds are running against Node 20 and 22.

React version

RJSF is no longer actively supporting React version < 18.x.
React 18 is officially supported on all the themes.

React 19 support is expected before the end of beta (although several developers have already upgraded with no problems).

Form POTENTIAL BREAKING CHANGES

The onChange() and onSubmit() callbacks were accidentally returning extra data along with what was listed in the IChangeEvent interface.
In v6, this was fixed so that only the data described by the IChangeEvent interface is returned.
If you were relying on that extra data in the callbacks, we are sorry for the inconvenience.

A bug was fixed such that live validation will no longer be triggered on the data provided during the initial rendering of the Form.
If you require that your initial data have errors shown, then you can programmatically validate it after the initial render.

IdSchema replacement BREAKING CHANGE

The recursive IdSchema type and all its usages was replaced with a much simpler FieldPathId type.
This was done to remove a performance headache associated with having to recursively generate the IdSchema for every change made to formData.
Moreover, after some evaluation, 99% of the use cases for the IdSchema were simply to get the id for a field.

FieldPathId is defined as:

typescript
/** The list of path elements that represents where in the schema a field is located. When the item in the field list is
 * a string, then it represents the name of the property within an object. When it is a number, then it represents the
 * index within an array.
 *
 * For example:
 * `[]` represents the root object of the schema
 * `['foo', 'bar']` represents the `bar` element contained within the `foo` element of the schema
 * `['baz', 1]` represents the second element in the list `baz` of the schema
 */
export type FieldPathList = (string | number)[];

/** Type describing an id and path used for a field */
export type FieldPathId = {
  /** The id for a field */
  $id: string;
  /** The path for a field */
  path: FieldPathList;
};

idSchema props

In addition, everywhere the idSchema: IdSchema<T> prop was part of a RJSF type, it was replaced with fieldPathId: FieldPathId.

The affected types are:

  • FieldErrorProps
  • FieldHelpProps
  • FieldProps
  • UnsupportedFieldProps
  • ArrayFieldTitleProps
  • ArrayFieldDescriptionProps
  • ArrayFieldItemButtonsTemplateProps
  • ArrayFieldTemplateProps
  • ObjectFieldTemplateProps

If you have built a custom component using one of those types that used idSchema: IdSchema, simply replace that type and property name with fieldPathId: FieldPathId.

For example, if you had a custom field:

tsx
import { FieldProps } from '@rjsf/utils';

// Version 5-based custom widget
function CustomField(props: FieldProps) {
  const {
    idSchema: { $id },
    formData,
    value,
  } = props;

  return <div id={$id}>// Your field implementation</div>;
}

// Version 6-based custom widget
function CustomField(props: FieldProps) {
  const {
    fieldPathId: { $id },
    formData,
    value,
  } = props;

  return <div id={$id}>// Your field implementation</div>;
}

toIdSchema() removed

Finally, the toIdSchema() utility function was deleted and replaced with a new toFieldPathId() function documented here

formContext BREAKING CHANGES

Removed the unnecessary formContext property from the following interfaces since it is readily available in the registry.
If you were using the formContext in your custom template, field or widget, simply get it from the registry instead.

Interfaces with formContext removed:

  • ErrorListProps - The properties that are passed to an ErrorListTemplate implementation
  • FieldProps - The properties that are passed to a Field implementation
  • FieldTemplateProps - The properties that are passed to a FieldTemplate implementation
  • ArrayFieldTemplateProps - The properties that are passed to an ArrayFieldTemplate implementation
  • WidgetProps - The properties that are passed to a Widget implementation

Fields BREAKING CHANGES

FieldProps.onChange

The onChange handling for fields has been changed to fix a serious bug related to nearly simultaneous updates losing data.
Previously in 5.x, data change handling worked by passing a complete newFormData object up to the Form from the underlying Fields.
In 6.x, data change handling now works by passing just the changed newValue for a Field and the path array of the Field within the formData, with the Form itself being responsible for injecting the changed data into the formData.

As a result, the FieldProps interface was updated with the following breaking change so that custom Field authors are forced to respond to this update:

typescript
// Version 5's `onChange` handler:

/** The field change event handler; called with the updated form data and an optional `ErrorSchema` */
onChange: (newFormData: T | undefined, es?: ErrorSchema<T>, id?: string) => any;

// Version 6's `onChange` handler:
/** The field change event handler; called with the updated field value, the optional change path for the value
 * (defaults to an empty array), an optional ErrorSchema and the optional id of the field being changed
 */
onChange: (newValue: T | undefined, path: FieldPathList, es?: ErrorSchema<T>, id?: string) => void;

In order to support letting the Form know what the path of the change was, a new path: FieldPathList parameter was injected into the handler before the es?: ErrorSchema<T> parameter.
If you have written a custom Field that implements merging the new value into the newFormData, now you just need to pass that value and provide the fieldPathId.path to the onChange function.

Here is an example of a custom Field that was updated due to this change:

text
/* Detailed source-code truncated for AI context efficiency. */

The same change also applies to the ErrorSchema object being passed to the Form.
Therefore, if your custom Field also updated the ErrorSchema to add a new error, now you just need to pass that error as well.
Finally, the errors are preserved across validations, so if you want to clear an error you passed via onChange, you will have to pass undefined

Here is an example of a custom Field that was updated due to this change:

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

const { StringField } = getDefaultRegistry().fields;

// Version 5-based custom field
function StringFieldError(props: FieldProps) {
  const onChange = (newFormData: any | undefined, es?: ErrorSchema, id?: string) => {
    let raiseError = es;
    if (newFormData === 'test') {
      raiseError = {
        ...es,
        __errors: ['Value cannot be "test"'],
      };
    }
    props.onChange(newFormData, raiseError, id);
  };
  return <StringField {...props} onChange={onChange} />;
}

// Version 6-based custom field
function StringFieldError(props: FieldProps) {
  const onChange = (newValue: any | undefined, path: FieldPathList, es?: ErrorSchema, id?: string) => {
    let raiseError = es;
    if (newValue === 'test') {
      raiseError = {
        __errors: ['Value cannot be "test"'],
      };
    }
    props.onChange(newValue, path, raiseError, id);
  };
  return <StringField {...props} onChange={onChange} />;
}

FieldProps.idPrefix and FieldProps.idSeparator refactor

The idPrefix and idSeparator props were refactored from the FieldProps interface to the new GlobalFormOptions interface,
If your custom implementation required either of those props, you can simply obtain them from the registry.globalFormOptions variable instead.

FieldTemplateProps and WrapIfAdditionalTemplateProps BREAKING CHANGES

During the conversion of ObjectField to a stateless functional component, the additionalProperties-based props in these two interfaces were simplified by replacing two callback-generators with memoized callbacks.

If you have your own implementation of the FieldTemplate and/or WrapIfAdditionalTemplate template(s), you will have to rename the props mentioned below with their replacements.

onKeyChange replacement

The onKeyChange: (value: string) => () => void callback-generator function was replaced with the following 2 memoized callbacks, (one is a helper callback, since most of the key renames were triggered off of an input blur):

typescript
/** Callback used to handle the changing of an additional property key's name with the new value
 */
onKeyRename: (newKey: string) => void;
/** Callback used to handle the changing of an additional property key's name when the input is blurred. The event's
 * target's value will be used as the new value. Its a wrapper callback around `onKeyRename`
 */
onKeyRenameBlur: (event: FocusEvent<HTMLInputElement>) => void;

onDropPropertyClick replacement

The onDropPropertyClick: (value: string) => () => void callback-generator function was replaced with the following memoized callback:

typescript
/** Callback used to handle the removal of the additionalProperty */
onRemoveProperty: () => void;

ObjectFieldTemplateProps BREAKING CHANGES

During the conversion of ObjectField to a stateless functional component, the additionalProperties-based prop in this interface was simplified by replacing a callback-generator with a memoized callback.

If you have your own implementation of the ObjectFieldTemplate template, you will have to rename the prop mentioned below with its replacement.

onAddClick replacement

The onAddClick: (schema: S) => () => void callback-generator function was replaced with the following memoized callback:

typescript
/** Callback to use in order to add an new additionalProperty to the object field  (to be used with
 * additionalProperties and patternProperties)
 */
onAddProperty: () => void;

Registry BREAKING CHANGES

A new required prop, globalFormOptions: GlobalFormOptions, was added to the Registry interface.
This could affect your tests if you have your own way of creating registry objects to test your custom widgets, fields and/or templates.
If you are creating Registry objects, you simply need to add an empty object to the globalFormOptions prop.
You may also, provide values for any of the optional props contained within the GlobalFormOptions type.

The definition of the GlobalFormOptions object is:

typescript
/** The set of options from the `Form` that will be available on the `Registry` for use in everywhere the `registry` is
 * available.
 */
export type GlobalFormOptions = {
  /** To avoid collisions with existing ids in the DOM, it is possible to change the prefix used for ids;
   * Default is `root`. This prop is passed to the `toFieldPathId()` function within the RJSF field implementations.
   */
  readonly idPrefix?: string;
  /** To avoid using a path separator that is present in field names, it is possible to change the separator used for
   * ids; Default is `_`. This prop is passed to the `toFieldPathId()` function within the RJSF field implementations.
   */
  readonly idSeparator?: string;
  /** The component update strategy used by the Form and its fields for performance optimization */
  readonly experimental_componentUpdateStrategy?: 'customDeep' | 'shallow' | 'always';
  /** Optional function to generate custom HTML name attributes for form elements. Receives the field path segments
   * and element type (object or array), and returns a custom name string. This allows backends like PHP/Rails
   * (`root[tasks][0][title]`) or Django (`root__tasks-0__title`) to receive form data in their expected format.
   */
  readonly nameGenerator?: NameGeneratorFunction;
};

To help support this change for test writers, a new getTestRegistry() function has been provided in @rjsf/core.

Templates BREAKING CHANGES

ArrayFieldTemplateItemType renamed

The type ArrayFieldTemplateItemType was renamed to ArrayFieldItemTemplateProps type, which matches the template properties naming pattern.

Also changed the key: string prop to itemKey: string to avoid a name collision with React

ArrayFieldItemTemplate BREAKING CHANGES

The ArrayFieldItemTemplateProps was refactored to extract the following props into out a new ArrayFieldItemButtonsTemplateProps:

  • canAdd: A boolean value stating whether new items can be added to the array.
  • hasCopy: A boolean value stating whether the array item can be copied.
  • 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.
  • onAddIndexClick: (index) => (event?) => void: Returns a function that adds a new item at index.
  • onCopyIndexClick: (index: number) => (event?: any) => void;: Returns a function that copies the item at index into the position at index + 1.
  • 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.

In addition to this refactor, the conversion of the ArrayField template to functional components caused the replacement of the 4 callback-generator functions with 5 memoizable functions.

onAddIndexClick replacement

The onAddIndexClick: (index) => (event?) => void callback-generator function was replaced with the following memoized callback:

typescript
/** Callback function that adds a new item below this item */
onAddItem: (event?: any) => void;

onCopyIndexClick replacement

The onCopyIndexClick: (index: number) => (event?: any) => void; callback-generator function was replaced with a simpler, memoized callback:

typescript
/** Callback function that copies this item below itself */
onCopyItem: (event?: any) => void;

onDropIndexClick replacement

The onDropIndexClick: (index) => (event?) => void callback-generator function was replaced with the following memoized callback:

typescript
/** Callback function that removes the item from the list */
onRemoveItem: (event?: any) => void;

onReorderClick replacement

The onReorderClick: (index, newIndex) => (event?) => void callback-generator function was replaced with the following 2 memoized callbacks:

typescript
/** Callback function that moves the item up one spot in the list */
onMoveUpItem: (event?: any) => void;
/** Callback function that moves the item down one spot in the list */
onMoveDownItem: (event?: any) => void;

A new buttonsProps prop was added of the type ArrayFieldItemButtonsTemplateProps

This new type was then used to create a new ArrayFieldItemButtonsTemplate in the Registry.templates.
See ArrayFieldItemButtonTemplate

If you have implemented your own ArrayFieldItemTemplate or ArrayField then you will have to account for these changes.

ArrayFieldTemplate BREAKING CHANGE

In order to support the conversion of ArrayField to functional components, the items property was changed from an
array of ArrayFieldItemTemplateProps information to an array of React elements. These elements are result of the ArrayField
actually rendering the ArrayFieldItemTemplate directly, rather than deferring it the ArrayFieldTemplate.

If you previously provided a custom ArrayFieldTemplate to do the full rendering of your arrays, now you will have to
separate the logic of generating the items into your own custom ArrayFieldItemTemplate. For example:

text
/* Detailed source-code truncated for AI context efficiency. */
text
/* Detailed source-code truncated for AI context efficiency. */

NOTE: the example above could also have implemented an ArrayFieldItemButtonsTemplate for the buttonProps related code.

Potential BREAKING CHANGE

This template was also updated to support the new Optional Data Controls feature by adding a new optionalDataControl prop to the ArrayFieldTemplateProps interface.

If you have your own implementation of ArrayFieldTemplate and want to support this new feature, please refer to any of the ArrayFieldTemplate implementation for whatever theme you are using and pick up the changes.

ArrayFieldTitleTemplate POTENTIAL BREAKING CHANGE

This template was updated to support the new Optional Data Controls feature by adding a new optionalDataControl prop to the ArrayFieldTitleProps interface.

If you have your own implementation of ArrayFieldTitleTemplate and want to support this new feature, please refer to the ArrayFieldTitleTemplate implementation for @rjsf/core or whatever theme you are using and pick up the changes.

GridTemplate

A new, theme-dependent template GridTemplate was added to support the new layout feature and must be provided if you are building your own registry.templates rather than overloading them via the templates props.

MultiSchemaFieldTemplate

This new template was created to extract styling applied to the MultiSchemaField component in the @rjsf/core package.

If you have styled your form using the following classNames and you do NOT use the @rjsf/core theme, you may need to adjust your styles, as they may have been removed from your theme: panel, panel-default, panel-body, form-group.

ObjectFieldTemplate POTENTIAL BREAKING CHANGE

This template was updated to support the new Optional Data Controls feature by adding a new optionalDataControl prop to the ObjectFieldTemplateProps interface.

If you have your own implementation of ObjectFieldTemplate and want to support this new feature, please refer to the ObjectFieldTemplate implementation for whatever theme you are using and pick up the changes.

OptionalDataControlsTemplate POTENTIAL BREAKING CHANGE

This new template was created to support the new Optional Data Controls feature.

If you are implementing your own theme you may need to add this new template if you anticipate supporting this new feature.

TitleFieldTemplate POTENTIAL BREAKING CHANGE

This template was updated to support the new Optional Data Controls feature by adding a new optionalDataControl prop to the TitleFieldProps interface.

If you have your own implementation of TitleFieldTemplate and want to support this new feature, please refer to the TitleFieldTemplate implementation for whatever theme you are using and pick up the changes.

SchemaField - Addition of FallbackField POTENTIAL BREAKING CHANGE

The SchemaField was updated to use the new FallbackField, which adds opt-in support to replace the UnsupportedField with an interactive UI instead of an error message.
If you have your own implementation of SchemaField and want to support this new feature, please refer to the SchemaField implementation in @rjsf/core and pick up the changes.

The UnsupportedField component is unaffected by these changes, and is still used by the new FallbackField.

SchemaUtilsType

Five new functions were added to this type, so if you have your own implementation of this type, you will need to add them to yours.
The following new functions match the 5 new validator-based utility API functions mentioned below:

  • findFieldInSchema(path: string | string[], schema: S, formData?: T): FoundFieldType<S>
  • findSelectedOptionInXxxOf(schema: S, fallbackField: string, xxx: 'anyOf' | oneOf, formData?: T): S | undefined;
  • getFromSchema(schema: S, path: string | string[], defaultValue: T): T;
  • getFromSchema(schema: S, path: string | string[], defaultValue: S): S;
  • getFromSchema(schema: S, path: string | string[], defaultValue: T | S): S | T;

In addition the toIdSchema() function was removed on this type in concert with the toIdSchema() function removal, so update your implementation to remove this as well.

Removed deprecations

The following deprecations were removed from the code base in v6

FormProps.acceptcharset

The acceptcharset prop on Form was removed. Use the acceptCharset prop instead. I.e.:

tsx
<Form acceptCharset='ISO-8859-1' />

getMatchingOption()

The getMatchingOption() function in @rjsf/utils was removed. Use the getFirstMatchingOption() function instead.
I.e.:

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

const schema: RJSFSchema = {
  // your schema goes here
};

const formData = {
  /* your form data goes here */
};
const options: RJSFSchema[] = [
  /* your options extracted from the schema go here */
];

const option = getFirstMatchingOption(validator, formData, options, schema);

SchemaUtilsType.getMatchingOption()

The getMatchingOption() function in the SchemaUtilsType was removed. Use the getFirstMatchingOption() funciton on
the type instead. I.e.:

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

const schema: RJSFSchema = {
  // your schema goes here
};

const formData = {
  /* your form data goes here */
};
const options: RJSFSchema[] = [
  /* your options extracted from the schema go here */
];
const schemaUtils = createSchemaUtils(validator, schema);

const option = schemaUtils.getFirstMatchingOption(formData, options);

mergeValidationData()

The mergeValidationData() function from @rjsf/utils was removed. Use the validationDataMerge() function instead.
I.e.:

ts
import { validationDataMerge, ValidationData, ErrorSchema } from '@rjsf/utils';

const validationData: ValidationData = {
  errors: [
    /* Your validation errors go here */
  ],
  errorSchema: {
    /* Your error schema goes here */
  },
};

const additionalErrorSchema: ErrorSchema = {
  /* Your additional error schema goes here */
};

const merged = validationDataMerge(validationData, additionalErrorSchema);

SchemaUtilsType.mergeValidationData()

The mergeValidationData() function in the SchemaUtilsType was removed. Use the standalone validationDataMerge()
function instead. I.e.:

ts
import { toErrorList } from '@rjsf/utils';

const validationData: ValidationData = {
  errors: [
    /* Your validation errors go here */
  ],
  errorSchema: {
    /* Your error schema goes here */
  },
};

const additionalErrorSchema: ErrorSchema = {
  /* Your additional error schema goes here */
};

const merged = validationDataMerge(validationData, additionalErrorSchema);

ValidatorType.toErrorList()

The toErrorList() function on the ValidatorType interface was removed. Use the standalone toErrorList() function
from @rjsf/utils instead. I.e.:

ts
import { validationDataMerge, ErrorSchema, RJSFValidationError, toErrorList } from '@rjsf/utils';

const errorSchema: ErrorSchema = {
  /* Your error schema goes here */
};

const validationErrors: RJSFValidationError[] = toErrorList(errorSchema);

RJSF_ADDITONAL_PROPERTIES_FLAG

The constant RJSF_ADDITONAL_PROPERTIES_FLAG was removed from @rjsf/utils. Use the RJSF_ADDITIONAL_PROPERTIES_FLAG
constant instead. I.e.:

ts
import { RJSF_ADDITIONAL_PROPERTIES_FLAG } from '@rjsf/utils';

UiSchema.classNames

The classNames notation on UiSchema was removed. Use the ui:classNames notation instead. I.e.:

json
{
  "someField": {
    "ui:classNames": "someCustomClass"
  }
}

schema.enumNames

The custom enumNames property support on a JSON Schema that RJSF invented has been removed. Please use the UiSchema
replacement, ui:enumNames instead. I.e.:

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

const schema: RJSFSchema = {
  type: 'object',
  properties: {
    attendance: {
      title: 'How did you attend the event?',
      enum: ['person', 'phone', 'video'],
    },
    rating: {
      title: 'How would you rate this event?',
      enum: ['0', '1', '2', '3', '4'],
    },
  },
};

const uiSchema: UiSchema = {
  attendance: {
    'ui:enumNames': ['I joined in person', 'I called in using the phone number', 'I joined using the video link'],
  },
  rating: {
    'ui:enumNames': ["I did't like it", 'It was meh', 'It was ok', 'I liked it', 'I loved it'],
  },
};

Use the ui:enumNames in the UiSchema instead.

Other BREAKING CHANGES

Primitive field handling in oneOf/anyOf schemas

A bug fix was implemented that changes how primitive fields (boolean, string, number, etc.) are handled when switching between oneOf/anyOf schema options with mergeDefaultsIntoFormData: "useDefaultIfFormDataUndefined".

Previous (buggy) behavior: Undefined primitive fields were incorrectly set to empty objects {} when switching between schema variants.

New (correct) behavior: Undefined primitive fields now remain undefined or receive proper default values according to their type when switching between schema variants.

This change fixes #4709 and was implemented in #4710.

Impact: If your application was incorrectly relying on undefined primitive fields becoming {} objects, you may need to update your form validation or data processing logic to handle proper primitive values or undefined instead.

Optional array defaulting (POTENTIAL)

A bug fix was implemented that changes how optional arrays are initialized during the formData defaulting phase.

Previous (buggy) behavior: Optional arrays were initialized to [].

New (correct) behavior: Optional arrays are no longer initialized.

Impact: If your application was incorrectly relying on optional arrays being initialized this way, you may need to update it to handle the corrected behavior.

SchemaField removed Bootstrap 3 classes

In fixing #2280, the following Bootstrap 3 classes
(form-group, has-error and has-danger error classes) were removed from the classNames prop passed down to the
FieldTemplate. They were instead moved into the core theme's WrapIfAdditionalTemplate to ensure that theme was
unchanged.

Additionally, the Bootstrap 3 classes panel, panel-default, panel-body, and form-group were removed from the
MultiSchemaField component in the @rjsf/core package, and moved into the core theme's MultiSchemaFieldTemplate
to ensure that the theme was unchanged.

As a result, the themes (other than core) will no longer render these classes.

If you use a non-core theme and were relying on them for in your application's styling or behavior (via css overrides
perhaps), then you can still use the non-Bootstrap 3 RJSF marker class (see below) or your specific theme's error classes.

Prefixed RJSF template and field marker classes

Many of the core RJSF templates and field implementations that are shared across all themes were updated to add the
rjsf- prefix to the marker classes that are being added to the rendered HTML. The following table highlights the old
and new marker classes. If you were relying on any of these classes, simply do a rename:

old marker class new marker class
field rjsf-field
field-<schema.type> rjsf-field-<schema.type>
field-array rjsf-field-array
field-array-of-<schema.type> rjsf-field-array-of-<schema.type>
field-array-fixed-items rjsf-field-array-fixed-items
field-error rjsf-field-error
field-hidden rjsf-field-hidden
array-item rjsf-array-item
config-error rjsf-config-error
array-item-add rjsf-array-item-add
array-item-copy rjsf-array-item-copy
array-item-move-down rjsf-array-item-move-down
array-item-move-up rjsf-array-item-move-up
array-item-remove rjsf-array-item-remove
object-property-expand rjsf-object-property-expand
object-property-remove rjsf-object-property-remove

optionsList

The generics ordering on the optionsList() function was changed from <S, T, F> to <T, S, F> to be consistent with the rest of the APIs.

New Features

New types

The following new types were added to @rjsf/utils:

  • ArrayFieldItemTemplateProps: The properties of each element in the ArrayFieldTemplateProps.items array.
  • ContainerFieldTemplateProps: The common properties of the two container templates: ArrayFieldTemplateProps and ObjectFieldTemplateProps
  • FallbackFieldProps: The properties passed to the new FallbackField component
  • FallbackFieldTemplate: The properties passed to the new FallbackFieldTemplate component
  • FieldPathList - The list of path elements that represents where in the schema a field is located
  • FieldPathId - Type describing an id and path used for a field
  • FoundFieldType: The interface for the return value of the findFieldInSchema function
  • GlobalFormOptions: The set of options from the Form that will be available on the Registry for use in everywhere the registry is available.
  • GridTemplateProps: The properties that are passed to a GridTemplate
  • MultiSchemaFieldTemplateProps: The properties that are passed to a MultiSchemaFieldTemplate
  • OptionalDataControlsTemplateProps: The properties that are passed to a OptionalDataControlsTemplate implementation
  • TestIdShape: The interface for the test ID proxy objects that are returned by the getTestId utility function

New non-validator utility functions

Many new or formerly internally private utility functions are available in @rjsf/utils:

  • buttonId(id: FieldPathId | string, btn: 'add' | 'copy' | 'moveDown' | 'moveUp' | 'remove'): Generates consistent ids for RJSF buttons
  • getTestIds(): TestIdShape: Returns an object of test IDs that can only be used in test mode, helpful for writing unit tests for React components
  • hashObject(object: unknown): string: Stringifies an object and returns the hash of the resulting string
  • hashString(string: string): string: Hashes a string into hex format
  • isFormDataAvailable<T = any>(formData?: T)<T = any>(formData?: T): boolean: Determines whether the given formData represents valid form data, such as a primitive type, an array, or a non-empty object
  • isRootSchema<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(registry: Registry<T, S, F>, schemaToCompare: S): boolean: Helper to check whether a JSON schema object is the root schema
  • lookupFromFormContext<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(regOrFc: Registry<T, S, F> | Registry<T, S, F>['formContext'], toLookup: string, fallback?: unknown): Given a React JSON Schema Form registry or formContext object, return the value associated with toLookup
  • optionalControlsId(id: FieldPathId | string, element: 'Add' | 'Msg' | 'Remove'): Return a consistent id for the optional data controls element
  • shouldRenderOptionalField<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(registry: Registry<T, S, F>, schema: S, required: boolean, uiSchema?: UiSchema<T, S, F>): boolean: Determines if this field should be rendered with the Optional Data Controls UI
  • sortedJSONStringify(object: unknown): string: Stringifies an object, sorts object fields in consistent order before stringifying it
  • toFieldPathId(fieldPath: string | number, globalFormOptions: GlobalFormOptions, parentPath?: FieldPathId | FieldPathList, isMultiValue?: boolean): Constructs the FieldPathId for fieldPath and the optional parentPath, using globalFormOptions
  • useAltDateWidgetProps<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(props: WidgetProps<T, S, F>): UseAltDateWidgetResult: which encapsulates the logic needed to render an AltDateWidget with optional time elements
  • useDeepCompareMemo<T = unknown>(newValue: T): T: Hook that stores and returns a T value. If newValue is the same as the stored one, then the stored one is returned, otherwise newValue is stored and returned
  • useFileWidgetProps(value: string | string[] | undefined | null, onChange: (value?: string | null | (string | null)[]) => void, multiple?: boolean): UseFileWidgetPropsResult: Hook which encapsulates the logic needed to read and convert a value of File or File[] into the props needed by a FileWidget implementation.

New validator-based utility functions

Three new validator-based utility functions are available in @rjsf/utils:

  • findFieldInSchema<T = undefined, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(validator: ValidatorType<T, S, F>, rootSchema: S, path: string | string[], schema: S, formData?: T, experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>): FoundFieldType<S>: Finds the field specified by the path within the root or recursed schema
  • findSelectedOptionInXxxOf<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(validator: ValidatorType<T, S, F>, rootSchema: S, schema: S, fallbackField: string,xxx: 'anyOf' | 'oneOf', formData?: T, experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>): S | undefined: Finds the option that matches the selector field in the schema or undefined if nothing is selected
  • getFromSchema<T = any, S extends StrictRJSFSchema = RJSFSchema, F extends FormContextType = any>(validator: ValidatorType<T, S, F>, rootSchema: S, schema: S, path: string | string[], defaultValue: T | S, experimental_customMergeAllOf?: Experimental_CustomMergeAllOf<S>): T | S: Reads the value at path within a schema, additionally retrieving $refs as needed to resolve schemas

Changes to existing utility functions

  • getDefaultFormState(): Added an optional initialDefaultsGenerated boolean flag that indicates whether or not initial defaults have been generated
  • retrieveSchema(): Added an optional resolveAnyOfOrOneOfRefs boolean flag that causes the internal resolveAllSchemas() to resolve $refs inside of the options of anyOf/oneOf schemas
    • This new optional flag was added to the SchemaUtilsType interface's version of retrieveSchema() as well.
  • validationDataMerge(): Added optional preventDuplicates boolean flag that causes the mergeObjects() call to receive preventDuplicates instead of true

initialFormData prop added to Form

A new initialFormData prop was added to Form to support providing initial values for an "uncontrolled" React component.
As a result, a small change was made so that formData now causes the Form to behave as a "controlled" React component.

The programmatic reset() will ensure that an "uncontrolled" form is reset back to the initialFormData values when triggered.

setFieldValue() added to Form

A new programmatic function, setFieldValue(fieldPath: string | FieldPathList, newValue?: T): void was added to the Form.
It allows a user to set a value for the provided fieldPath, which must be either a dotted path to the field OR a FieldPathList.
To set the root element, used either '' or [] for the path. Passing undefined will clear the value in the field.

liveValidate and liveOmit performance improvement

Because liveValidate and liveOmit can have serious performance impacts in the Form, those flags were updated to add the following new options:

  • 'onChange' - Live validate and live omit will happen as part of the onChange process