Building the Form Builder
The Form Builder app is the most complex we've built so far. It builds on concepts from earlier modules and reenforces the idea of building modular, component-driven UIs. We'll walk through the app build together to create a dynamic form powered from a set of JSON objects.
Building the Form Builder#
Right, time to build something fun, the Form Builder app!
In this app, we’ll be taking a simple HTML form powered by React and allowing it to load in a range of form fields dynamically from a JSON file.
It’s going to look like this when we’re done:
Visualizing the components#
Before we start building anything in code, however, it’s a great place to practice some of our ‘thinking in React’ skills.
As you get more experienced you can code up what you need to and look at refactoring this as you go. In fact, it can be really helpful to rapidly and roughly build something out and just get it working and then concern yourself with refining it once it does.
But for us, at this stage, it’s a super useful exercise to do a bit of planning beforehand to get a mental model and layout of what components we’ll need to build, and how they’ll interact.
Opportunities for breaking down components#
Sticking with the finished demo that we’ve just looked at, if we were to code this all up in one big component, it would look like this:
Ok, so this is already a really long component with a lot of repetition, or very very close to having identical blocks of code — e.g. the label and input element combinations.
Granted, some of this additional markup is due to the styling imposed by Bulma, but even without that, we would still have a lot of repeated blocks of code. This has a few disadvantages:
Readability becomes more difficult as the file or component grows in size or complexity.
Any universal changes (i.e. if we needed to change the styling or structure or logic) need to be made to each and every separate block rather than in one place.
More repetition usually introduces more places for errors to occur.
We also essentially ‘lock in’ this form and make it concrete. For example, we can’t reuse it anywhere, despite the fact that the mechanism of how it works (e.g. collecting data from the user and doing something with it) is going to be largely identical from form to form.
Creating a visual map of components#
An improvement on this would be to look at the component we have and refactor it, thinking how we can maximize reuse and minimize errors and lines of code.
Thinking about the previous example and the previous demo of the app, we can create a visual mapping of how we might break down the single components into smaller parts.
Looking at this visual mapping, you can see we have three main components and an additional file,
App.js— The usual project entry point that defines the starting place for our app to begin.
Form.jsx— This will be a container component that pulls in our JSON data from the
formfields.jsonfile and uses it to populate a dynamic list of
FormFieldInput.jsx— A semi-presentational component that renders an HTML input with a label, wrapped in a little bit of Bulma markup. It manages its own state for the input’s value.
formfields.json— A simple JSON file that contains an array of objects, each representing a form field with some information like a name, label text, and input type.
This part of the build should be starting to look familiar by now as we’re going to be creating a new project with Create React App, removing some default files that we don’t need, and adding Bulma’s CSS framework to the project.
Open up a terminal window and navigate to the parent folder that you want to create the new project in. Next, type the
create react-app command as follows:
Let the command line finish installing the dependencies, waiting until you see the ‘success’ message and
yarn commands to start and build the app.
Testing the new project#
Let’s give everything a quick check to see if it’s working before we take the coding hatchet out.
Once it’s built and ready, navigate to
http://localhost:3000 in a browser check out the project running as expected.
Initial clean up#
index.js, located in
/form-builder/src/ and remove the default styles:
It should be on line 3 of the
index.js file. This will just remove a link to the default styles from the project that we won’t need.
After that, locate
/src/index.css and delete the file.
Next, find the
/src/App.css file and open it up. Highlight all the contents and delete the existing styles. Save and close the file.
Finally, open the main
App.js file located at
/src/App.js. Locate the following line (around line 2) that imports a
logo.svg file, and remove it:
import logo from ‘./logo.svg'
Now, select everything in the return statement (everything between
return ( and
) and replace it with the following so that the new return statement looks like this:
The final stage in the setup is to, once more, bring Bulma onboard to help style our app.
Open up the file
/public/index.html . If you remember, this is the template HTML file that the project uses to render the initial output of the app.
Next, add the following line somewhere between the opening and closing
You can also edit the title of the page between the
<title></title> tags too if you like.
We’ve given some thought to the files we want and how we’re going to break the components down, but where are we going to house everything?
Let’s start by creating two folders directly underneath our
/src folder: one that will hold our components and one for our JSON data. Create a new folder,
/components and another one called
When you start dealing with more complex projects and components that depend on each other, it can be helpful to start with the child furthest down the tree and build upwards from there. That’s how we’re going to build our components out for the Form Builder. Starting with our JSON data, then we’ll look at the
FormFieldInput component and build upwards (or backward, depending on how you look at it) from there.
This is helpful because it allows us to decide what information a child component will need ahead of time and then make sure we pass that down from the parent component when we’re building the parent out.
We want our HTML input elements to be rendered dynamically. This means they won’t know what to render ahead of time and will work this out at runtime, deciding which parts of the HTML to render, what type of field, etc.
This is good because it makes the component more flexible: want to render a simple text box? No problem. Want to use the exact same component to render a date picker instead that has some helper text? Fine and dandy.
However, at some point, we do have to let our form field component know what we expect of it. A good way to do that is with some good, old fashioned structured JSON data.
Inside of the
/data folder, create a new file called
formfields.json and populate it with the following basic data: