A lightweight form builder package for creating easy forms in React with just a config. The component removes all necessity to write long boilterplate for handling state, change & errors for any React form. Just pass in a config, and attach a form submit handler, and you're done!
- Render a form with just a config of all the fields needed in the form, with their
label
andinitialValue
. - Ability to add custom header and footer elements (including the Submit button, don't forget it!) for the form.
- Ability to handle form submission, by passing an
onSubmit
callback prop. The callback receives the form state (an object of form labels as keys and the input value as values) as an argument. - High customizability:
- Custom form, form container, inputs, labels, form groups(a group contains the label & input for a form element) & form sections.
- Custom input sizes [small | medium (default) | large]
- Customize by passing
className
or/andstyles
as props - Customize all forms on your app globally using global classnames, or
- Customize each form differently using props for individual forms.
- Error handling on form level & input level for inputs which are
required
to be filled. - Fully keyboard accessible & responsive.
- A built in
SubmitButton
component for providing a custom form submit button easily.
Install the package using:
npm install --save-dev react-config-form
import React from "react";
import { createRoot } from "react-dom/client";
import {
FormBuilder,
SubmitButton
FormInputConfig,
FormSubmitState,
} from "react-config-form";
const LoginForm = () => {
const loginFormConfig: FormInputConfig[] = [
{
label: "Username",
initialValue: "",
type: "text",
required: true,
},
{
label: "Password",
initialValue: "",
type: "password",
required: true,
}
];
const handleLoginFormSubmit = (form: FormSubmitState) => {
console.log(form);
};
return (
<FormBuilder
config={loginFormConfig}
formStyles={{
backgroundColor: "#4cd8d3",
boxShadow: "none",
borderColor: "#1e014a",
}}
formHeader={
<header>
<h1>Login</h1>
</header>
}
onSubmit={handleLoginFormSubmit}
>
<SubmitButton text="Login" />
</FormBuilder>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(<LoginForm/>);
There is a Parcel-based playground for an example form inside /example
. You can run the playground locally using these commands:
cd example
npm i # or yarn to install dependencies
npm start # or yarn start
The default example imports and live reloads whatever is in /dist
, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. No symlinking required, due to Parcel's aliasing.
For seeing the more example forms demo, please check the website.
The Playground is just a simple Parcel app, you can deploy it anywhere you would normally deploy that. Here are some guidelines for manually deploying with the Netlify CLI (npm i -g netlify-cli
):
cd example # if not already in the example folder
npm run build # builds to dist
netlify deploy # deploy the dist folder
Alternatively, if you already have a git repo connected, you can set up continuous deployment with Netlify:
netlify init
# build command: yarn build && cd example && yarn && yarn build
# directory to deploy: example/dist
# pick yes for netlify.toml
Required props are marked with an asterisk(*)
Prop | Type | Description |
---|---|---|
config* | Array |
An array of config objects for all form input fields. |
onSubmit* | Function |
A callback function that takes the form state as an argument and gets called when the form is submitted. |
formHeader | JSX Element |
A JSX Element that gets rendered above the actual form. |
formClass | string |
A string that includes class(es) to be attached with the form. |
formStyles | Object |
A style object that includes styles for the form. |
containerClass | string |
A string that includes class(es) to be attached with the form container. |
containerStyles | Object |
A style object that includes styles for the form container. |
children | ReactNode |
React Elements (like a Submit button) that gets rendered beneath the form body (all the form fields). |
Prop | Type(s) | Description |
---|---|---|
text | string |
The button text [By default, it'll show a 'Submit' text] |
position | left middle right |
The alignment for the submit button. [By default, it'll show up in the middle] |
submitClass | string |
A string that includes class(es) to be attached with the submit button. |
Each form input config object contains the following:
Required properties are marked with an asterisk(*)
Property | Type(s) | Description |
---|---|---|
label* | string |
The label for the input. The label is used as a key for storing values in the form state on submission. |
type* | all input typestextarea dropdown |
The type for the input. (Like - "text", "email" etc). There are two custom types as of now - "textarea" & "dropdown". [All input types are not tested, some input types may show unexpected behaviours.] |
initialValue | As per the type | The initialValue for the input. [Not required for types like "file" & "dropdown".] |
required | boolean |
Boolean denoting whether a value is required for the input. |
options | Array |
A list of options for the input. Required for selective inputs like "dropdown" or "radio". |
checked | boolean |
Boolean denoting the condition when a field should be checked/filled. [Useful for "checkbox"/"radio" type inputs.] |
size | small medium large |
Specifies the size of the input. [Default value - "medium"]. |
placeholder | string |
A placeholder for the input. |
onChange | Function |
A callback for that gets called with the current input value whenever the input is changed. [Avoid using it for managing state for the form to avoid multiple sources of truth.] |
className | string |
A string that includes class(es) to be attached with the input. |
styles | Object |
A style object that includes styles for the input. |
labelClass | string |
A string that includes class(es) to be attached with the label. |
groupClass | string |
A string that includes class(es) to be attached with the form group (label and input box). |
groupHeader | JSX Element |
A header element for a particular form group. [This effectively makes dividing a form into multiple sections possible]. |
groupFooter | JSX Element |
A footer element for a particular form group. |
Global classNames can be used inside your project to style all forms globally across your app. If you have a lot of forms, and want to apply common styles to each form, this will be much faster as opposed to having to add props for each form individually. Here goes the list of global classnames:
Classname | Element |
---|---|
form | The main form element |
form-container | The form container |
form-group | Each form group (A form group consists of the label & the input for each form field) |
form-group-{type} | A dynamic classname for form group of a particular input type. [For example, this will be form-group-text for a text input] |
form-label | Each label for all inputs in the form |
form-required | The * element marking an input field as required |
form-group-error | The error text shown for required fields in the form that are still empty. |
There are some known issues you might encounter while using the FormBuilder
component.
- Inputs of type "file" don't reset after submitting the form.
- The dropdown input takes full available width of the form. (Feel free to override this behaviour using global classnames
form-input-dropdown
&form-group-dropdown
).
P.S: This project is bootstrapped with TSDX
TSDX is a Zero-config CLI tool for TypeScript package development. Please check out more about TSDX on the site.