A React Material UI Library to Build Any Form With Only JSON Config

Jeremy Ling
Geek Culture
Published in
3 min readNov 12, 2021

--

Suppose we want to create a form to collect shipping address. Here’s how we can replicate the form below with just JSON config and the open-source library I built @jeremyling/react-material-ui-form-builder.

The JSON Config

const fields = [
{
title: “Shipping Address”,
component: “display-text”,
titleProps: {
style: {
fontSize: 20,
marginTop: 16,
fontWeight: “bold”,
userSelect: “none”,
fontVariant: “small-caps”,
marginBottom: 8,
},
},
},
{
col: {
xs: 6,
},
label: “First Name”,
props: {
required: true,
},
attribute: “firstName”,
component: “text-field”,
validations: {
label: “First Name”,
required: “Required”,
},
validationType: “string”,
},
{
col: {
xs: 6,
},
label: “Last Name”,
props: {
required: true,
},
attribute: “lastName”,
component: “text-field”,
validations: {
label: “Last Name”,
required: “Required”,
},
validationType: “string”,
},
{
label: “Address Line 1”,
props: {
required: true,
},
attribute: “address1”,
component: “text-field”,
validations: {
label: “Address 1”,
required: “Required”,
},
validationType: “string”,
},
{
label: “Address Line 2”,
attribute: “address2”,
component: “text-field”,
validations: {
label: “Address 2”,
},
validationType: “string”,
},
{
col: {
xs: 6,
},
label: “City”,
attribute: “city”,
component: “text-field”,
validations: {
label: “City”,
},
validationType: “string”,
},
{
col: {
xs: 6,
},
label: “State”,
attribute: “state”,
component: “text-field”,
validations: {
label: “State”,
},
validationType: “string”,
},
{
col: {
xs: 6,
},
label: “Postcode”,
props: {
required: true,
},
attribute: “postcode”,
component: “text-field”,
validations: {
label: “Postcode”,
required: “Required”,
},
validationType: “string”,
},
{
col: {
xs: 6,
},
label: “Country”,
props: {
required: true,
},
attribute: “country”,
component: “text-field”,
validations: {
label: “Country”,
required: “Required”,
},
validationType: “string”,
},
{
options: [{
label: “Same as Billing”,
value: true,
}],
optionConfig: {
key: “label”,
label: “label”,
value: “value”,
},
attribute: “sameAsBilling”,
component: “checkbox-group”,
},
];

Standard Code For All Forms

import React, { useRef, useState } from “react”;
import { FormBuilder } from “@jeremyling/react-material-ui-form-builder”;
import { Button } from “@mui/material”;
import { get, isEmpty } from “lodash”;
async function validate(refs, form) {
var errors = {};
for (const [attribute, ref] of Object.entries(refs.current)) {
if (ref.validate) {
const error = await ref.validate(get(form, attribute));
if (error.length) {
errors[attribute] = error;
}
}
}
if (!isEmpty(errors)) {
console.log(errors);
return false;
}
return true;
}
export default function ShippingAddress() {
const [form, setForm] = useState({});
const refs = useRef({});

const updateForm = (updates) => {
const copy = { …form };
for (const [key, value] of Object.entries(updates)) {
copy[key] = value;
}
setForm(copy);
};
const handleNext = async (event) => {
event.preventDefault();
const ok = await validate(refs, form);
if (!ok) {
return;
}
console.log(form);
};

return (
<>
<FormBuilder
fields={fields}
form={form}
updateForm={updateForm}
refs={refs}
/>
<Button
type=”submit”
variant=”contained”
color=”primary”
sx={{ mt: 1 }}
onClick={handleNext}
>
Next
</Button>
</>
);
}

Explanation

Here, we only use a few components from the library, display-text, text-field and checkbox-group. There are many more you can use. You can view the documentation here. Just note, in general, all input components would have these core field props.

{  title: “State”, // Display text above the input  label: “State”, // Input label  attribute: “state”, // Attribute of the form to set/control  component: “text-field”, // Type of component  col: {    // Breakpoints and corresponding width (1–12)    xs: 6,    sm: 6,  },  validations: {    // Any validations accepted by yup    required: true,    length: 10,    min: 5,    max: 20,    matches: [‘/[a-z]/i’, ‘Can only contain letters’],    email: true,    url: true,    uuid: true,  },}

Concluding Remarks

I actually created the form above with 3 clicks and a few renames on FormBlob. Try it out and make building forms a breeze. If you’re a developer, contact us and I’ll turn on a feature for you to export the forms you build into your own project. Alternatively, you can even build and deploy a hosted form entirely on FormBlob and embed the form in your own domain. If you use this method, you don’t have to use React in your app and it still works out of the box!

If data privacy is a concern, you can define webhooks to call on each submission to pass the form data to your own backend. If you choose, FormBlob does not store any data on our servers beyond the form structure.

--

--

Jeremy Ling
Geek Culture

📋 Founder at https://formblob.com. 👻 Serial wannapreneur. 📚 Full-time philomath.