FormEngine: JSON Forms for React and MUI

Description:

FormEngine is a React form library that renders inputs, layout, validation, and event actions from JSON.

Preview

FormEngine JSON Forms for React and MUI

Features

  • JSON component trees with field properties and event actions.
  • Built-in Zod validation and custom validation integrations.
  • Conditional rendering and computed properties.
  • Fluent-based localization and language settings.
  • Material UI and React Suite component adapters.
  • Custom React components registered through typed definitions.
  • Responsive styling through component and wrapper CSS settings.

How To Use It

Install Core and its Material UI adapter.

npm install @react-form-builder/core @react-form-builder/components-material-ui @mui/material@^7.3.2 @emotion/react @emotion/styled

Import the required Core stylesheet once at your app entry:

import "@react-form-builder/core/assets/styles.css";

Render a Validated Contact Form

Create ContactForm.tsx. The submit button runs validation before the custom action; failOnError stops the action chain when a field fails validation.

import { view as muiView } from "@react-form-builder/components-material-ui";
import { FormViewer } from "@react-form-builder/core";
const contactForm = {
  errorType: "MuiErrorWrapper",
  form: {
    key: "Screen",
    type: "Screen",
    children: [
      {
        key: "email",
        type: "MuiTextField",
        props: { label: { value: "Email address" } },
        schema: {
          validations: [{ key: "required" }, { key: "email" }],
        },
      },
      {
        key: "submit",
        type: "MuiButton",
        props: {
          variant: { value: "contained" },
          children: { value: "Submit" },
        },
        events: {
          onClick: [
            {
              name: "validate",
              type: "common",
              args: { failOnError: true },
            },
            { name: "onSubmit", type: "custom" },
          ],
        },
      },
    ],
  },
};
const getForm = () => JSON.stringify(contactForm);
export default function ContactForm() {
  return (
    <FormViewer
      view={muiView}
      getForm={getForm}
      actions={{
        onSubmit: (event) => {
          console.log("Contact data", event.data);
        },
      }}
    />
  );
}

Load the Form in Next.js

FormEngine requires client-side rendering. Put the form above in components/ContactForm.tsx, import its stylesheet in app/layout.tsx, and create components/ContactFormClient.tsx to load the entire form with SSR disabled:

"use client";
import dynamic from "next/dynamic";
const ContactForm = dynamic(() => import("./ContactForm"), {
  ssr: false,
});
export default function ContactFormClient() {
  return <ContactForm />;
}

JSON Configuration and Component Registration

Every component node has a unique key and a type that matches an entry in the selected view. Properties use descriptors such as label: { value: "Email address" }. Validation rules sit under schema.validations; event action chains sit under events.

Store form JSON in your application’s preferred storage and return the serialized definition through getForm. FormEngine’s JSON describes a component tree, properties, and behavior; it is not interchangeable with an arbitrary JSON Schema document.

Create form-view.tsx to register custom controls before rendering. Import its exported muiView from ./form-view in ContactForm.tsx, and use type: "StatusNote" for this control in JSON:

import { define, string } from "@react-form-builder/core";
import { view as muiView } from "@react-form-builder/components-material-ui";
function StatusNote({ children }: { children?: string }) {
  return <p role="status">{children}</p>;
}
const statusNote = define(StatusNote, "StatusNote")
  .props({ children: string })
  .build();
muiView.define(statusNote.model);
export { muiView };

React Suite Adapter

For React Suite controls, install @react-form-builder/components-rsuite and pass that adapter’s view to FormViewer. Use its component type names in the JSON.

Rendering API Used Here

APIRole
FormViewer.viewComponent models that resolve JSON type names
FormViewer.getFormReturn serialized form JSON or a promise for it
FormViewer.actionsNamed custom action handlers; read submitted values through the handler’s event.data
define(Component, typeName)Create a typed component definition
.props(annotations)Describe the component’s configurable properties
.build().modelObtain the model from the built definition
view.define(model)Register the model in the renderer’s view

Styling

Use css for component styling and wrapperCss for its wrapper. Both accept device-specific entries such as any, desktop, and mobile, with an object of CSS properties or a CSS string.

For example, an email field can use a wrapper rule in its JSON node:

{
  "wrapperCss": {
    "any": {
      "object": {
        "marginBottom": "16px",
        "width": "100%"
      }
    }
  }
}

Core, Designer, and Online FormBuilder

ProductRoleLicensing or delivery
FormEngine CoreRender JSON definitions, manage form state, and run validation and actionsMIT-licensed React library
FormEngine DesignerEmbed a visual drag-and-drop form editorCommercial package, @react-form-builder/designer
Online FormBuilderCreate forms in a browser and export FormEngine JSONHosted builder

Alternatives and Related Resources

Add Comment