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

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/styledImport 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
| API | Role |
|---|---|
FormViewer.view | Component models that resolve JSON type names |
FormViewer.getForm | Return serialized form JSON or a promise for it |
FormViewer.actions | Named 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().model | Obtain 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
| Product | Role | Licensing or delivery |
|---|---|---|
| FormEngine Core | Render JSON definitions, manage form state, and run validation and actions | MIT-licensed React library |
| FormEngine Designer | Embed a visual drag-and-drop form editor | Commercial package, @react-form-builder/designer |
| Online FormBuilder | Create forms in a browser and export FormEngine JSON | Hosted builder |





