{"id":25683344,"url":"https://github.com/mikechabot/react-json-form-engine","last_synced_at":"2025-04-23T19:13:11.954Z","repository":{"id":32456893,"uuid":"79622980","full_name":"mikechabot/react-json-form-engine","owner":"mikechabot","description":"Build lightning fast web forms from JSON.","archived":false,"fork":false,"pushed_at":"2023-01-26T04:24:45.000Z","size":7905,"stargazers_count":51,"open_issues_count":31,"forks_count":11,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-23T19:12:52.066Z","etag":null,"topics":["form-engine","form-framework","json-forms","mobx","react","web-forms"],"latest_commit_sha":null,"homepage":"https://mikechabot.github.io/react-json-form-engine-storybook/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mikechabot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-21T04:13:43.000Z","updated_at":"2024-09-24T02:20:55.000Z","dependencies_parsed_at":"2023-02-14T14:15:35.160Z","dependency_job_id":null,"html_url":"https://github.com/mikechabot/react-json-form-engine","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikechabot%2Freact-json-form-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikechabot%2Freact-json-form-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikechabot%2Freact-json-form-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikechabot%2Freact-json-form-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikechabot","download_url":"https://codeload.github.com/mikechabot/react-json-form-engine/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250496991,"owners_count":21440231,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["form-engine","form-framework","json-forms","mobx","react","web-forms"],"created_at":"2025-02-24T16:51:25.542Z","updated_at":"2025-04-23T19:13:11.906Z","avatar_url":"https://github.com/mikechabot.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003ca href='https://github.com/mikechabot/react-json-form-engine'\u003e\u003cimg src='https://raw.githubusercontent.com/mikechabot/react-json-form-engine-demo/master/src/assets/banner_dark.png' alt='logo' aria-label='https://github.com/mikechabot/react-json-form-engine' /\u003e\u003c/a\u003e\n\nBuild lightning fast web forms from JSON.\n\n:heart: Conditional logic \n\u003cbr/\u003e\n:heart: Flexible validation \n\u003cbr/\u003e\n:heart: Infinite depth\n\u003cbr/\u003e\n:heart: Rehydratable \n\nWhile other libraries might utilize [react-redux](https://github.com/reduxjs/react-redux), [`refs`](https://reactjs.org/docs/refs-and-the-dom.html), or [Context](https://reactjs.org/docs/context.html) for form state management, `react-json-form-engine` relies on React as little as possible, and offloads its core logic to plain JavaScript, while utilzing [mobx](https://mobx.js.org/) bindings for rendering. The result is scalable, lightning-fast performance with neglible reliance on the React lifecycle.\n\nIt's important to note that this library was designed to manage large, multi-section forms, that may contain conditional logic (e.g. Show field `Foo` based on the response given in field `Bar`). This may or may not be for you, but it can also handle simple forms with extreme ease.\n\nIt also offers a mechanism for serializing all form responses to JSON for persistence. The reverse also stands, as any form can be easily rehydrated from historical data, and returned to its previous state.\n\n\u003cdiv align=\"center\"\u003e  \n  \u003ca href=\"https://travis-ci.org/mikechabot/react-json-form-engine\"\u003e\n    \u003cimg src=\"https://travis-ci.org/mikechabot/react-json-form-engine.svg?branch=master\" alt=\"build status\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/react-json-form-engine\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/react-json-form-engine.svg\" alt=\"npm version\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://david-dm.org/mikechabot/react-json-form-engine\"\u003e\n    \u003cimg src=\"https://david-dm.org/mikechabot/react-json-form-engine.svg\" alt=\"dependency status\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/mikechabot/react-json-form-engine/pulls\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\" alt=\"prs welcome\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n----\n\n## Table of Contents\n\n- [Live Demo](#live-demo)\n- [Installing](#installing)\n- [Storybook](#storybook)\n- [Getting Started](#getting-started)\n  - [Login Form Example](#login-form-example)\n- [Form Engine](#form-engine)\n  - [Form Definition](#form-definition)\n  - [Form Props](#form-props)\n  - [Field Definition](#field-definition)\n  - [Field Type](#field-type)\n  - [Field Children](#field-children)\n  - [Field Options](#field-options)\n  - [Field Props](#field-props)\n  - [Field Type Transitions](#field-type-transitions)\n  - [Field Decorators](#field-decorators)\n- [Serialize](#serialize)\n- [Validation](#validation)\n  - [Required](#required-validation)\n  - [Numeric](#numeric-validation)\n  - [Regular Expression](#regex-validation)\n- [Conditions](#conditions)\n  - [Condition Types](#condition-types)\n  - [Expression Types](#expression-types)\n  - [Condition Examples](#condition-examples)\n  \n----\n\n## \u003ca id=\"live-demo\"\u003eLive Demo\u003c/a\u003e\n\nhttps://mikechabot.github.io/react-json-form-engine-storybook/\n\n## \u003ca id=\"installing\"\u003eInstalling\u003c/a\u003e\n\nRequires React 15.0.0+\n\n`$ npm install --save react-json-form-engine`\n\n\u003e Note: This library renders [Bulma](https://bulma.io/documentation/overview/start/) semantics; you'll need to import the styles for everything to look nice.\n\n```js\n// Import the styles\nimport 'react-json-form-engine/dist/css/styles.min.css';\n\n// Import the API\nimport { Form, FormEngine } from 'react-json-form-engine';\n```\n\n----\n\n## \u003ca id=\"storybook\"\u003eStorybook\u003c/a\u003e\n\nTo run the `react-json-form-engine` [storybook](https://storybook.js.org/) locally:\n\n```bash\n$ git clone https://github.com/mikechabot/react-json-form-engine.git\n$ npm install\n$ npm run storybook\n```\n\nAvailable at http://localhost:6006/\n\n----\n\n## \u003ca id=\"getting-started\"\u003eGetting Started\u003c/a\u003e\n\nFirst, let's import the API:\n\n```js\nimport { Form, FormEngine } from 'react-json-form-engine';\n```\n\nNext, we'll need to build a [Form Definition](#form-definition), which is the skeleton structure that describes how the form should look and behave. The definition must adhere to a strict schema, and can be represented as a JavaScript object or a [JSON Schema](http://json-schema.org). But don't worry about the details yet, we'll get into those. \n\nOnce we've built our definition, we'll feed it to the `FormEngine`, which returns an instance:\n\n```javascript\nconst instance = new FormEngine(definition);\n```\n\nTo rehydrate a form instance from a previous state, we'd pass in our model as the second argument.\n\n```javascript\n\nconst model = {username: 'mikechabot', city: 'Boston', state: 'MA'};\nconst instance = new FormEngine(definition, model);\n```\n\nThen, we just pass the instance to the `\u003cForm /\u003e` component, and `react-json-form-engine` takes care of the rest:\n\n```jsx\n\u003cForm\n  instance={instance}\n  onUpdate={(id, value) =\u003e {}}\n  onSubmit={(hasError) =\u003e {}}\n/\u003e\n```\n----\n\n### \u003ca id=\"login-form-example\"\u003eLogin Form Example\u003c/a\u003e\n\nLet's create a simple login form. Either follow along below, or check out the [Login](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/examples--login-form) demo on storybook.\n\n#### Login Form Definition\n\nHere's our definition, which is a rather simple one. It consists of just a single section with a single subsection, which houses three fields. Note, we're also using a [Field Decorator](#field-decorators) to ensure `user_pass` renders as a password field:\n\n```js\nconst loginForm = {\n  id: 'loginForm',\n  title: 'Welcome to Foo!',\n  sections: [\n    {\n      id: 'loginSection',\n      title: 'Login Section',\n      subsections: [\n        {\n          id: 'loginSubsection',\n          title: 'Login',\n          subtitle: 'Please enter your credentials.',\n          fields: [\n            {\n              id: 'username',\n              title: 'Username',\n              type: 'string',\n              required: true\n            },\n            {\n              id: 'password',\n              title: 'Password',\n              type: 'string',\n              required: true\n            },\n            {\n              id: 'rememberMe',\n              title: 'Remember me',\n              type: 'boolean'\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  decorators: {\n    password: {\n      component: {\n        type: 'password'\n      }\n    }\n  }\n};\n```\n\nNow that we have our definition, let's create an instance of `FormEngine`:\n\n```javascript\nconst instance = new FormEngine(loginForm); \n```\n\nWith the instance in hand, we can pass it our `\u003cForm /\u003e` component:\n\n```jsx\nconst LoginForm = () =\u003e (\n  \u003cForm\n    instance={instance}\n    onUpdate={(id, value) =\u003e {\n       // Do stuff\n    }}\n    onSubmit={hasError =\u003e {\n       // Do stuff\n    }}\n  /\u003e\n);\n```\n\nAnd once filled out, `onSubmit` will get us the form responses, and also pass along the state of the form \n\n```jsx\nconst LoginForm = () =\u003e (\n  \u003cForm\n    instance={instance}\n    onUpdate={(id, value) =\u003e {\n       // Log the change set\n       console.log(`FieldId ${id} was changed to ${value}`);\n       \n       // Get the full validation results of the field\n       console.log(instance.getValidationResultById(id);\n       \n       // Get just the validation status of the field (i.e. ERROR, OK)\n       console.log(instance.getValidationStatusById(id);\n    }}\n    onSubmit={hasError =\u003e {\n      if (hasError) {\n        // Get form validation results\n        console.log(intance.getValidationResults(id)); \n      }\n      // Get form responses\n      console.log(instance.getModel());               \n      \n      // Serialize form responses\n      console.log(instance.serializeModel());         \n    }}\n  /\u003e\n);\n```\n\n----\n\n## \u003ca id=\"form-engine\"\u003eForm Engine\u003c/a\u003e\n\n- [Form Definition](#form-definition)\n- [Form Props](#form-props)\n- [Field Definition](#field-definition)\n- [Field Type](#field-type)\n- [Field Children](#field-children)\n- [Field Options](#field-options)\n- [Field Props](#field-props)\n- [Field Type Transitions](#field-type-transitions)\n- [Field Decorators](#field-decorators)\n\n### \u003ca id=\"form-definition\"\u003eForm Definition\u003c/a\u003e\n\nForm definitions adhere to a strict schema. They must contain at least **one section**, which contains at least **one subsection**, which contains at least **one [Field Definition](#field-definition)**. You may find this schema verbose for smaller forms, however its purpose is to scale for significantly complex forms.\n\n\u003e View the full schema in the [FormAPIService](https://github.com/mikechabot/react-json-form-engine/blob/master/src/form/service/form-api-service.js#L27)\n\n\u003e In forms with a single section, vertical tabs are not displayed. In sections with a single subsection, horizontal tabs are not displayed. See the [Layout](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/layout--multi-section) demos on storybook.\n\n```js\n// The most minimal form possible\nexport default {\n  id: \u003cstring\u003e,\n  title: \u003cstring\u003e,\n  faIcon: {\n      name: \u003cstring\u003e,\n      prefix: \u003cstring\u003e\n  },\n  sections: [\n    {\n      id: \u003cstring\u003e,\n      title: \u003cstring\u003e,\n      subsections: [\n        {\n          id: \u003cstring\u003e,\n          title: \u003cstring\u003e,\n          fields: [\n            {\n                ...\n            }\n          ]\n        }\n      ]\n    }\n  ]\n};\n```\n\u003e The `faIcon` object is optional on the form definition; it supports [Font Awesome](https://fontawesome.com/icons?d=gallery) icons.\n\nHave a look the [Simple Form](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/examples--simple-form) demo on storybook.\n\n---\n\n#### Form Definition Validation\n\nDon't worry about making mistakes with your definition. If the `FormEngine` is instantiated with a malformed definition, the UI will be notified of the failure location.\n\nIn the case below, our definition was missing the `sections` array:\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg src='https://raw.githubusercontent.com/mikechabot/react-json-form-engine-demo/master/src/assets/form-engine-api-check.png' alt='api-check' aria-label='api-check' /\u003e\n\u003c/div\u003e\n\nHave a look at the [Malformed Form](https://mikechabot.github.io/react-json-form-engine-demo/?path=/story/examples--malformed-form) demo on storybook.\n\n----\n\n### \u003ca id=\"form-props\"\u003eForm Props\u003c/a\u003e\n\n| Prop                      | Required? | Type                 | Description\n|---------------------------|-----------|----------------------|-----------------------------------------|\n| `instance`                | Yes       | `object`             | Created by `new FormEngine(definition)` |\n| `onSubmit`                | Yes       | `func`               | Invoked when `Submit` is clicked. Is passed with `hasError`, which is the overall status of the form      |\n| `onUpdate`                | No        | `func`               | Invoked when the user updates the form. Is passed with the `id` and `value` of the field that was updated  |\n| `submitButtonLabel`       | No        | `string`             | Custom label for the \"Submit\" button.   |\n| `hideFormTitle`           | No        | `boolean`            | Hide the form's title                   |\n| `hideFormBorder`          | No        | `boolean`            | Hide the form's border                  |\n| `hideSubsectionTitles`    | No        | `boolean`            | Hide subsection titles. Only applies to sections with a single subsection**                |\n| `hideSubsectionSubtitles` | No        | `boolean`            | Hide subsection subtitles               |\n| `width`                   | No        | `number` or `string` | Apply a width to the form               |\n\n\u003e ** Section titles are only used in **multi-section** forms, and are used as the label for vertical tabs. Subsection titles are displayed as a heading in sections that contain a single subsection, and as labels for horizontal tabs in sections that are **multi-subsection**. See the [Layout](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/layout--multi-section) demo on storbyook, and tinker with the prop knobs to see this behavior in action.\n \n### \u003ca id=\"field-definition\"\u003eField Definition\u003c/a\u003e\n\nField definitions also adhere to a strict schema. At minimum, they must contain an `id`, `type` and `title`:\n\n```js\n// The most minimal field object\n{\n  id: \u003cstring\u003e,       // Uniquely identifies the field within the DOM, and FormEngine instance\n  type: \u003cstring\u003e,     // Determines the data type of the field response\n  title: \u003cstring\u003e     // Label of the field\n}\n```\n\n----\n\n### \u003ca id=\"field-type\"\u003eField Type\u003c/a\u003e\n\nDetermines the *data type* of the response value stored in the model, and which Default Control to render. To override the default and render an Allowed Control instead, use a [Field Decorator](#field-decorators).\n\nNote, the `info` field is the only field type that does not accept input from the end-user; its purpose is to provide a place for the form author to render informational content, such as instructions, to the end-user. This field type utilizes `dangerouslySetInnerHTML` meaning you're able to render pure HTML. *Be aware of XSS concerns.*\n\n| Field Type       | Default Control   | Allowed Controls                                          | Supports `options`? |\n|------------------|-------------------|-----------------------------------------------------------|---------------------|\n| `string`         | `\u003cText /\u003e`        | `\u003cPassword /\u003e`, `\u003cTextarea /\u003e`, `\u003cSelect /\u003e`, `\u003cRadio /\u003e` | Yes**               |\n| `boolean`        | `\u003cCheckbox /\u003e`    | `\u003cRadio /\u003e`                                               | Yes**               |\n| `number`         | `\u003cNumber /\u003e`      | `\u003cRange /\u003e`                                               | No                  |\n| `array`          | `\u003cSelect /\u003e`      | `\u003cCheckboxgroup /\u003e`                                       | Yes                 |\n| `date`           | `\u003cDateTime /\u003e`    | N/A                                                       | No                  |\n| `info`**         | `\u003csection /\u003e `    | N/A                                                       | No                  |\n\n\u003e ** Some field types will *automatically* transition from their Default Control to another Allowed Control if an `options` array is present in the field definition. (See [Field Type Transitions](#field-type-transitions)). However, in most cases, you must use a \n[Field Decorator](#field-decorators) to use another Allowed Control.\n\n----\n\n### \u003ca id=\"field-children\"\u003eField Children\u003c/a\u003e\n\nAny field can contain child fields. Simply create a `fields` array on the field, and drop in valid [Field Definitions](#field-definition). Here's an example of some nested fields, but take a look at the [Nesting](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/field-nesting--simple-nesting) demo on storybook.\n\n\u003e Note: Field children can recurse infinitely, and also be placed on [Field Options](#field-options).\n\n```js\n{\n  id: 'parent',\n  type: 'number',\n  title: 'Parent',             \n  fields: [\n    {\n      id: 'child',\n      type: 'string',\n      title: 'Child',\n      fields: [\n        {\n          id: 'grandchild',\n          type: 'number',\n          title: 'Grandchild'\n        }\n      ]\n    },\n    {\n      id: 'child-2',\n      type: 'array',\n      title: 'Child',\n      options: [\n        { id: 'op1', title: 'Option 1'},\n        { id: 'op2', title: 'Option 2' },\n      ]\n    }\n  ]\n}\n```\n\nHave a look at the [Nested Fields](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/field-nesting--simple-nesting) demo on storybook.\n\n----\n\n### \u003ca id=\"field-options\"\u003eField Options\u003c/a\u003e\n\n\u003e Applies to `string`, `boolean`, and `array` field types only.\n\n#### `boolean`\n\nFields of type `boolean` only accept a maximum of **two** options; each of which should contain just a `title` property. The first option is considered the affirmative response:\n\n```js\n{\n  id: 'my_bool',\n  title: 'How often does it occur?',\n  type: 'boolean',\n  options: [\n    { title: 'Always' },\n    { title: 'Never' },\n  ]\n}\n```\n\n#### `string` / `array`\n\nFor field types that accept unlimited options (`string`, `array`), you must include both an `id` and `title`. The `ids` of the selected option(s) are stored in the model.\n\n```js\n{\n  id: 'my_arr',\n  title: 'Pick some',  \n  type: 'array',      // Array type allows for multiple selections\n  options: [\n    { id: 'op1', title: 'Option 1' },\n    { id: 'op2', title: 'Option 2' },\n    { id: 'op3', title: 'Option 3' },\n  ]\n},\n{\n  id: 'my_str',\n  title: 'Pick one',\n  type: 'string',    // String type allows for single selection\n  options: [\n    { id: 'op1', title: 'Option 1' },\n    { id: 'op2', title: 'Option 2' },\n    { id: 'op3', title: 'Option 3' },\n  ]\n}\n```\n\n#### Field Children on Options\n\nFor field controls that render selectable options, like `\u003cRadio /\u003e` or `\u003cCheckboxgroup /\u003e`, you can include [Field Children](#field-children) on any of the options. Take a look at the [Complex Nesting](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/field-nesting--complex-nesting) demo on storybook.\n\n```js\n{\n  id: 'field_2',\n  type: 'string',\n  title: 'Select One (Field Type: String)',\n  options: [\n    {\n      id: 'op1',\n      title: 'Option 1',\n      fields: [{ id: 'explain_1', type: 'string', title: 'Explain' }]\n    },\n    {\n      id: 'op2',\n      title: 'Option 2',\n      fields: [{ id: 'explain_2', type: 'string', title: 'Explain' }]\n    },\n    {\n      id: 'op3',\n      title: 'Option 3',\n      fields: [{ id: 'explain_3', type: 'string', title: 'Explain' }]\n    }\n  ]\n}\n```\n\n----\n\n### \u003ca id=\"field-props\"\u003eField Props\u003c/a\u003e\n\nHere's the complete list of props that can be passed to [Field Definitions](#field-definition):\n\n| Property        | Type      | Required | Description                                                                                                              |\n|-----------------|-----------|----------|--------------------------------------------------------------------------------------------------------------------------|\n| `id`            | `string`  | Yes      | See [Field ID](#field-id)                                                                                                |\n| `type`          | `string`  | Yes      | See [Field Type](#field-type)                                                                                            |\n| `title`         | `string`  | Yes      | Display label for the field                                                                                              |\n| `options`       | `array`   | No       | See [Field Options](#field-options)                                                                                      |\n| `fields`        | `array`   | No       | See [Field Children](#field-children)                                                                                    |\n| `placeholder`   | `string`  | No       | Placeholder text to display                                                                                              |\n| `showCondition` | `object`  | No       | Condition object (See [Conditions](#conditions))                                                                         |\n| `required`      | `boolean` | No       | Whether the field is required (See [Validation](#validation))                                                            |\n| `pattern`       | `string`  | No       | Pattern to match during validation (See [Validation](#validation))                                                       |\n| `min`           | `number`  | Yes*     | Minimum value. (Used for `number` field types)                                                                           |\n| `max`           | `number`  | Yes*     | Maximum value. (Used for `number` field types)                                                                           |\n| `showTimeSelect`| `boolean` | No       | Only show Date in Date/Time. (Used for `date` field types)                                                               |\n| `hideCalendar`  | `boolean` | No       | Only show Time in Data/Time. (Used for `date` field types)                                                               |\n| `content`       | `string`  | No       | Informational content to be displayed to the end-user. Utilizes `dangerouslySetInnerHTML`. (Used for `info` field types) |\n\n\u003e `min` and `max` are only required for `\u003cRange /\u003e` component types.\n\n\u003e `date` field types implement [react-datepicker](https://reactdatepicker.com/). Any prop that can be passed to `react-datepicker` can be added to a `date` field, and it will be passed directly to `\u003cDate /\u003e`, such as `timeIntervals`, or `dateFormat`.\n\n----\n\n### \u003ca id=\"field-type-transitions\"\u003eField Type Transitions\u003c/a\u003e\n\n#### `string`\n\nBy default, a `string` field is rendered as `\u003cText /\u003e` (See [Field Type](#field-type)), but with `options` it automatically renders as a `\u003cSelect /\u003e`.\n\n```js\n{ \n  // Renders as \u003cText /\u003e\n  id: 'field_1',\n  type: 'string', \n  title: 'Text Field'\n},\n{             \n  // Renders as \u003cSelect /\u003e\n  id: 'field_2',\n  type: 'string',\n  title: 'Select Field',\n  options: [\n    { id: \"op1\", title: \"Option 1\" },\n    { id: \"op2\", title: \"Option 2\" },\n  ]\n}\n```\n\nHave a look at the [Strings](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/data-types--strings) demo on storybook.\n\n----\n\n#### `boolean`\n\nBy default, a `boolean` field is rendered as `\u003cCheckbox /\u003e` (See [Field Type](#field-type)), but with `options` it automatically renders as a `\u003cRadio /\u003e`.\n\n```js\n{\n  id: \"field_1\",\n  type: \"boolean\",\n  title: \"Checkbox Field\"\n},\n{\n  id: \"field_2\",\n  type: \"boolean\",\n  title: \"Radio Field\",\n  options: [\n    { title: \"Yes\" },\n    { title: \"No\" }\n  ]\n}\n```\n\n\u003e A maximum of two (2) options is allowed for `boolean` fields. For unlimited `\u003cRadio /\u003e` options, use the `string` type with a `component` of `radio`.\n\nHave a look at the [Booleans](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/data-types--booleans) demo on storybook.\n\n----\n\n### \u003ca id=\"field-decorators\"\u003eField Decorators\u003c/a\u003e \n\nField decorators contain metadata about the fields you've configured in your form definition. Add the `decorators` object to the root of the [Form Definition](#form-definition):\n\n```js\n{\n  id: 'my_form'\n  title: 'My Form',\n  sections: [...],\n  decorators: {}\n}\n```\nThe `decorators` object will be keyed by [Field ID](#field-id), and can contain the properties `hint` and `component`.\n\n----\n\n#### Hint Decorator\n\nAdd hint text to any field:\n\n```js\n{\n  id: \"Form_ID\",\n  title: \"Form Title\",\n  sections: [{\n    ...\n    subsections: [{\n      ...     \n      fields: [{\n        id: \"field_1\",\n        type: \"string\",\n        title: \"Field title\"\n      }]\n    }]\n  }],\n  decorators: {\n    field_1: {\n      hint: \"This is some hint text!\"   // Add hint text to any field\n    }\n  }\n}\n```\n\n----\n\n#### Component Decorator\n\nEvery field `type` renders a Default Control (See [Field Type](#field-type)), however you'll often want to explicitly override the default component type in favor of another. In some cases, this occurs automatically (See [Field Type Transitions](#field-type-transitions)), however most times you'll need to specify a component decorator.\n\nLet's update `field_1` from a `\u003cSelect /\u003e` to a `\u003cCheckboxgroup /\u003e`:\n\n```js\n{\n  id: \"Form_ID\",\n  title: \"Form Title\",\n  sections: [{\n    ...\n    subsections: [{\n      ...     \n      fields: [{\n        id: \"field_1\",\n        type: \"array\",\n        title: \"Field title\",\n        options: [\n           ...\n        ]\n      }]\n    }]\n  }],\n  decorators: {\n    field_1: {\n      hint: 'More hint text!',\n      component: {\n        type: 'checkboxgroup'   // Override the default component type\n      }\n    }\n  }\n}\n```\n\nHere's a list of field types with overrideable components:\n\n| Field Type       | Component Decorator Overrides   | \n|------------------|---------------------------------|\n| `string`         | `password`, `textarea`, `radio` |\n| `number`         | `range`                         |  \n| `array`          | `checkboxgroup`                 |\n\n\nTake a look at a component override in the [Arrays](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/data-types--arrays) demo.\n\n----\n\n## \u003ca id=\"serialize\"\u003eSerialize\u003c/a\u003e\n\nEasily serialize the form's responses by calling `serializeModel` on the instance:\n\n```js\nconst json = instance.serializeModel();\n```\nTo access the model without serialization, use the below:\n```js\nconst map = instance.getModel();           // {fooId: 'bar', bazId: 'qux'}\nconst array = instance.getModelAsArray();  // [{fooId: 'bar'}, {bazId: 'qux'}]\n```\n\n----\n\n## \u003ca id=\"validation\"\u003eValidation\u003c/a\u003e\n\nThree types of validation are supported:\n\n| Type               | Supported Data Types    |\n|--------------------|-------------------------|\n| Required           | All                     |\n| Numeric (min/max)  | `number`                | \n| Regular Expression | `string`, `number`      |\n\nTake a look at the [Validation](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/validations--required-validation) demos on storybook.\n\n----\n\n### \u003ca id=\"required-validation\"\u003eRequired\u003c/a\u003e\n\nAdd `required: true` to any field definition:\n\n```js\n{\n  id: 'username',\n  type: 'string',\n  title: 'Username',\n  required: true\n},\n{\n  id: 'myOptions',\n  type: 'array',\n  title: 'Option Group',\n  required: true,\n  options: [\n    { id: 'op1', title: 'Option 1' },\n    { id: 'op2', title: 'Option 2' },\n    { id: 'op3', title: 'Option 3' },\n    { id: 'op4', title: 'Option 4' }\n  ]\n}\n```\n\u003e Note: Fields are **only** validated if they are visible in the DOM. For instance, if a field's `showCondition` (See [Conditions](#conditions)) is not met, it will not be displayed to the end-user; conditionally hidden fields are not validated.\n\nTake a look at the [Required Validation](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/validations--required-validation) demo in storybook.\n\n----\n\n### \u003ca id=\"numeric-validation\"\u003eNumeric\u003c/a\u003e\n\nAdd `min: \u003cnumber\u003e` or `max: \u003cnumber\u003e` or both to any `number` type field:\n\n```js\n{\n  id: 'age',\n  type: 'number',\n  title: 'Age',\n  min: 0,\n  max: 120\n}\n```\n\u003e Note `min`/`max` values are only validated once the field is marked as dirty, that is, the user inputs a value.\n\nTake a look at the [Numeric Validation](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/validations--numeric-validation) demo on storybook.\n\n----\n\n### \u003ca id=\"regex-validation\"\u003eRegular Expression\u003c/a\u003e\n\nAdd `pattern: \u003cregex\u003e` to any `string` or `number` field:\n\n```js\n{\n  id: 'myRegEx',\n  type: 'string',\n  title: 'My Field',\n  pattern: '^foobar$',\n}\n```\n\nTake a look at the [Regex Demo](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/validations--regex-validation) on storybook.\n\n----\n\n### Multiple Validators\n\nValidators can be combined. The following `number` field will only pass validation if the following conditions are met:\n\n1. The value is not `undefined`, per `required`.\n1. The value is greater-than or equal to zero, per `min`.\n1. The value is less-than or equal to 300, per `max`.\n1. The value starts with the numeral `3`, per `pattern`.\n\n```js\n{\n  id: 'num1',\n  type: 'number',\n  title: 'Number Regex',\n  pattern: '^3',\n  required: true,\n  min: 0,\n  max: 300\n}\n```\n\n----\n\n## \u003ca id=\"conditions\"\u003eConditions\u003c/a\u003e\n\nConditionally show any field by giving it a `showCondition`. Take a look at the [Conditions](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/conditions--array-conditions) demos before moving on.\n\n```js\n{\n  id: 'myString',\n  type: 'string',\n  title: 'Conditional Field',\n  showCondition: {...}\n}\n```\n\nA `showCondition` contains a `type` and one or more `expressions`, which also contain a `type`. Expressions are evaluated against one another, or the form model itself to conditionally show a field (e.g. Show field `Foo` based on the response given in field `Bar`).\n\n\u003e Note: `showConditions` also accept a `not` property, and if set to `true`, the condition will be negated.\n\n### \u003ca href=\"condition-types\"\u003eCondition Types\u003c/a\u003e\n\n| Type           | Data Types                           | Description                                               | \n|----------------|--------------------------------------|-----------------------------------------------------------|\n| `BETWEEN`      | `number`                             | Determine if a `FORM_RESPONSE` is between a `CONST` value |\n| `BLANK`        | `string`, `array`, `date`            | Determine if a `FORM_RESPONSE` is blank**                 |\n| `CONTAINS`     | `array`                              | Determine if a `FORM_RESPONSE` contains a `CONST` value   |\n| `EMPTY`        | `string`, `array`, `date`            | Determine if a `FORM_RESPONSE` is empty***                |\n| `EQUAL`        | `string` `number`, `date`, `boolean` | Determine if a `FORM_RESPONSE` is equal to a `CONST`      |\n| `GREATER_THAN` | `number`                             | Determine if a `FORM_RESPONSE` is greater than a `CONST`  |\n| `LESS_THAN`    | `number`                             | Determine if a `FORM_RESPONSE` is less than a `CONST`     |\n\n\u003e ** `BLANK` is defined as an empty array or string, undefined, or null.\n\n\u003e *** `EMPTY` implements Lodash's [isEmpty](https://lodash.com/docs/4.17.11#isEmpty)\n\n### \u003ca href=\"expression-types\"\u003eExpression Types\u003c/a\u003e\n\n| Type            | Uses                                          | \n|-----------------|-----------------------------------------------|\n| `CONST`         | A constant `value`                            |\n| `FORM_RESPONSE` | References a field `id` in the form instance  |\n\n\u003e `showConditions` are evaluated every time the form is updated. \n\n----\n\n### \u003ca href=\"condition-examples\"\u003eCondition Examples\u003c/a\u003e\n\nTake a look at the [Conditions](https://mikechabot.github.io/react-json-form-engine-storybook/?path=/story/conditions--array-conditions) demos for live examples.\n\n### `CONTAINS` Example\n\nThe following `checkboxgroup` has three option fields. The **second** option has a child field; if this option is selected, a `string` field is rendered underneath it. \n\n\u003e Have a look at the field definition below, and then we'll walk through it.\n\n```js\n{\n  id: 'myArray',\n  type: 'array',\n  title: 'Select some options to display the children',\n  options: [\n    {\n      id: 'option1',\n      title: 'Option 1'\n    },\n    {\n      id: 'option2',\n      title: 'Option 2',\n      fields: [\n        {\n          id: 'myString',\n          type: 'string',\n          title: 'Conditional Field',\n          showCondition: {\n            type: 'CONTAINS',\n            expressions: [\n              {\n                type: 'FORM_RESPONSE',\n                id: 'myArray'\n              },\n              {\n                type: 'CONST',\n                value: 'option2'\n              }\n            ]\n          }\n        }\n      ]\n    },\n    {\n      id: 'option3',\n      title: 'Option 3',\n    }  \n  ]\n}\n```\n\nThe `showCondition` on the `myString` field can appear cryptic, but let's take a closer look at it:\n\n```js\nshowCondition: {\n  type: 'CONTAINS',\n  expressions: [\n    {\n      type: 'FORM_RESPONSE',\n      id: 'myArray'\n    },\n    {\n      type: 'CONST',\n      value: 'option2'\n    }\n  ]\n}\n```\n\nThe condition is of type `CONTAINS`, and contains an array of expressions.\n\n- One `expression` is of type `FORM_RESPONSE` and references by `id` the field `myArray`. \n- One `expression` is of type `CONST`, and contains the value `option2`.\n\nThe [expression-service](https://github.com/mikechabot/react-json-form-engine/blob/master/src/form-engine/service/expression-service.js) will pull the value of `myArray` from the instance, and determine if the `CONST` value of `option2` is contained within in. If so, `myString` will be displayed.\n\n\u003e At its core, this `showCondition` says *\"Show `myString` if the user selected `option2` in the `myArray` field.\"* \n\nIf the user selects all three options for `myArray`, its form response value in the instance would be `[\"option1\", \"option2\", \"option3\"]`, therefore `myString` would be shown since the `value` in the `CONST` expression (`option2`) is contained within the the form response.\n\n----\n\n### `EMPTY` Example\n\nLet's take a look at an `EMPTY` example. We'll use the same `checkboxgroup` field from the condition example above, however in this case, the conditional field (`myNumber`) won't be rendered under an option field, but rather under the entire field itself regardless of which option is selected.\n\n\u003e Have a look at the field definition below, and then we'll walk through it.\n\n```js\n{\n  id: 'myArray',\n  type: 'array',\n  title: 'Select some options to display the children',\n  options: [\n    {\n      id: 'option1',\n      title: 'Option 1'\n    },\n    {\n      id: 'option2',\n      title: 'Option 2',\n    },\n    {\n      id: 'option3',\n      title: 'Option 3',\n    },\n  ],\n  fields: [\n    {\n      id: 'myNumber',\n      type: 'number',\n      title: 'Number Field',\n      showCondition: {\n        type: 'EMPTY',\n        not: true,\n        expression: {\n            type: 'FORM_RESPONSE',\n            id: 'myArray'\n        }\n      }\n    }\n  ]\n}\n```\n\nLet's pull out the `showCondition` and take a closer look:\n\n```js\nshowCondition: {\n  type: 'EMPTY',\n  not: true,\n  expression: {\n      type: 'FORM_RESPONSE',\n      id: 'myArray'\n  }\n}\n```\n\nThe condition is of type `EMPTY`, contains a single expression, and also the `not` flag for negation.\n\n- The `expression` is of type `FORM_RESPONSE` and references by `id` the field `myArray`. \n- The `not` flag will negate the `EMPTY` condition being evaluated.\n\nThe [expression-service](https://github.com/mikechabot/react-json-form-engine/blob/master/src/form-engine/service/expression-service.js) will pull the value of `myArray` from the instance, and determine if it is **not** empty. If so, the `myNumber` field will be displayed.\n\n\u003e At its core, this expression says *\"Show `myNumber` if the user selected any of the options in `myArray`\"*\n\nConversely, if the `not` flag was removed from the condition, the `myNumber` field would immediately display to the user, but would be conditionally hidden if the user selected any of the options in `myArray`.\n\n----\n\n### `GREATER_THAN` Example\n\nLet's take a look at a `GREATER_THAN` example. The `number` field below (`myNumber`) has a single conditional child field, which will be displayed based based on the value input into `myNumber`.\n\n\u003e Have a look at the field definition below, and then we'll walk through it.\n\n```js\n{\n  id: 'myNumber',\n  type: 'number',\n  title: 'Greater-Than (\u003e)',\n  min: 0,\n  max: 10,\n  fields: [\n    {\n      id: 'myString',\n      type: 'string',\n      title: 'Field',\n      showCondition: {\n        type: 'GREATER_THAN',\n        expressions: [\n          {\n            type: 'FORM_RESPONSE',\n            id: 'myNumber'\n          },\n          {\n            type: 'CONST',\n            value: 5\n          }\n        ]\n      }\n    }\n  ]\n}\n```\n\nLet's pull out the `showCondition` and take a closer look:\n\n```js\nshowCondition: {\n  type: 'GREATER_THAN',\n  expressions: [\n    {\n      type: 'FORM_RESPONSE',\n      id: 'myNumber'\n    },\n    {\n      type: 'CONST',\n      value: 5\n    }\n  ]\n}\n```\n\nThe condition is of type `GREATER_THAN`, and contains an array of expressions.\n\n- One `expression` is of type `FORM_RESPONSE` and references by `id` the field `myNumber`. \n- One `expression` is of type `CONST`, and contains the value `5`.\n\nThe [expression-service](https://github.com/mikechabot/react-json-form-engine/blob/master/src/form-engine/service/expression-service.js) will pull the value of `myNumber` from the instance, and determine if it is greater than `5`. If so, the `myString` field will be displayed.\n\n\u003e At its core, this expression says *\"Show `myString` if `myNumber` is greater than 5.\"*\n\n----\n\n### `BETWEEN` Condition Example\n\nLet's take a look at a `BETWEEN` example. The following `range` field (`myNumber`) has a min/max of `0` and `100` respectively, and also contains a single conditional child field, which will be displayed when the value of `myNumber` is between `25` and `75`.\n\n```js\n{\n  id: 'myNumber',\n  type: 'number',\n  title: 'Between 25 and 75',\n  min: 0,\n  max: 100,\n  fields: [\n    {\n      id: 'myString',\n      type: 'string',\n      title: 'Field',\n      showCondition: {\n        type: 'BETWEEN',\n        expressions: [\n          {\n            type: 'FORM_RESPONSE',\n            id: 'myNumber'\n          },\n          {\n            type: 'CONST',\n            value: [25, 75]\n          }\n        ]\n      }\n    }\n  ]\n}\n```\n\nLet's pull out the `showCondition` and take a closer look:\n\n```js\nshowCondition: {\n  type: 'BETWEEN',\n  expressions: [\n    {\n      type: 'FORM_RESPONSE',\n      id: 'myNumber'\n    },\n    {\n      type: 'CONST',\n      value: [25, 75]\n    }\n  ]\n}\n```\n\nThe condition is of type `BETWEEN`, and contains an array of expressions.\n\n- One `expression` is of type `FORM_RESPONSE` and references by `id` the field `myNumber`. \n- One `expression` is of type `CONST`, and contains an array of values.\n\nThe [expression-service](https://github.com/mikechabot/react-json-form-engine/blob/master/src/form-engine/service/expression-service.js) will pull the value of `myNumber` from the instance, and determine if it is between `25` and `75`. If so, the `myString` field will be displayed.\n\n\n\u003e At its core, this expression says *\"Show `myString` if `myNumber` is between 25 and 75.\"*\n\nNote that the `CONST` array on `BETWEEN` condition types **requires** a length of two (2); the condition will not be evaluted otherwise.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikechabot%2Freact-json-form-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikechabot%2Freact-json-form-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikechabot%2Freact-json-form-engine/lists"}