You will not surprise anybody these days with splitting long forms into multi-step wizards, live client-side validation, initializing data and making sections/fields visibile depending on other fields. It is ‘must-have’ now. Otherwise, using complicated forms feels awkward and painful. In ProductCrafters we use Redux for state-management, so it’s logical to choose the best package for the form management. Redux-Form (~10k stars on GitHub) contains all listed features and a lot more, like tools for normalizing data, the array of fields and much more. After using it more than 2 years we are very happy with it.
We are facing client requirement to have partly or even 100% dynamic form. We get such a request from our fintech app customer. Recently, we’ve got a similar request for a heathlcare app. Meaning, form structure and validation rules will be fetched from the server; based on these data form (or wizard) should be created without making any changes on the client side. In this article, I want to share own experience of building such dynamic form wizard.
Here is the demo:
Here is the usual way to render field in Redux-Form:
We need to specify the field name, and a single component that should render it (input, checkbox, select, etc), the label is optional, but I like to have single component that can both describe a field and show it.
To get started, I have created sample server response mock, to render this field:
To simplify this tutorial I will cut fetching data and parsing JSON. We will use mock as it would look like after parsing.
Using this data to feed the <Field>
gonna give us fully-functional input.
In code above I do not use standard HTML5 <input />
. There are custom created components. And stringToComponentMapper
helps to choose correct component using key from json data. If you have never worked with redux-form before, just use default HTML 5 elements: “input”, “checkbox”, “select”.
Redux-form has a cool feature — FormSection. It allows to group together common fields for one entity.
The
_FormSection_
component makes it easy to split forms into smaller components that are reusable across multiple forms. It does this by prefixing the name of_Field_
,_Fields_
and_FieldArray_
children, at any depth, with the value specified in the_name_
prop.
Here what we had to write before it:
With <FormSection />
:
I made some changes to mock data, extracted section
object with own name and moved previous content inside fields
:
Now we may easily render form section. FormGenerator
receives data via prop and loops over it. Then each section loops over its fields.
It makes sense to extract SectionList
and SectionRenderer
components to avoid code in jsx
. I have not done it here to make code shorter and focus on dynamic UI.
Let’s make a change to the previous mock:
Now let’s add 2 files:
WizardProdiver.js — will remember current wizard page and manage page change. In this example, I also experiment with latest React Context, if it’s new for you, read official docs.
And PageTemplate.js will use FormGenerator and create a form around it:
Finally, we are wrapping everything together in Wizard.js:
Sample code:
ProductCrafters/Dynamic-Redux-Form-Wizard_Contribute to Dynamic-Redux-Form-Wizard development by creating an account on GitHub._github.com
Here is a demo.
In repo for this article, you may find simple regex validation also. This is very basic dynamic form. In real projects, we have much harder requirements, for example, dynamic rules for visibility of particular fields or section. It may be a topic for the second part of this article :)
P.S. 🚀My team uses React/React Native to build production apps over 3 years. We help US startup founders to bring their ideas to life. Need help with your project? ✉️ [email protected]