Use a custom react library to render a headless form
- Topics:
- Adaptive Forms
CREATED FOR:
- Beginner
- Intermediate
- Admin
- Developer
You can create and implement custom components to customize the appearance and functionality (Behavior) of your Headless Adaptive forms as per the requirement and guidelines of your organization.
These components serve two primary purposes: to control the appearance or style of form fields, and to store the data collected through these fields within the form model instance. If this sounds confusing, don’t worry - you are going to explore these purposes in greater detail shortly. For now, let’s focus on the initial steps of creating custom components, rendering the form using these components, and using events to save and submit data to a REST endpoint.
In this tutorial, Google Material UI components are employed to demonstrate how to render a Headless Adaptive Form using custom React components. However, you are not limited to this library and are free to use any React components library or develop your own custom components.
By the conclusion of this article, the Contact Us form created in Create and publish a headless form using the starter kit article transforms into the following:
The major steps involved in using Google Material UI components to render a form are:
1. Install Google Material UI
By default, the starter kit uses Adobe’s Spectrum components. Let’s set it to use Google’s Material UI:
-
Ensure that the starter kit is not running. To stop the starter kit, open your terminal, navigate to the react-starter-kit-aem-headless-forms, and press Ctrl-C (it’s the same on Windows, Mac, and Linux®).
Do not attempt to close the terminal. Closing your terminal does not stop the starter kit.
-
Run the following command:
npm install @mui/material @emotion/react @emotion/styled --force
It installs the Google Material UI npm libraries and adds the libraries to starter kits dependencies. You can now use Material UI components to render form components.
2. Create custom React components
Let’s create a custom component that replaces the default text input component with the Google Material UI Text Field component.
A separate component is required for each component type (fieldType or :type
) used in a Headless Form definition. For example, in the Contact Us form that you created in the previous section, the Name, Email, and Phone fields of type text-input
(fieldType: “text-input”) and the message field is of type multiline-input
(“fieldType”: “multiline-input”).
Let’s create a custom component to overlay all form fields that use the fieldType: “text-input” property with the Material UI Text Field component.
To create the custom component and map the custom component with the fieldType property :
-
Open the react-starter-kit-aem-headless-forms directory in a code editor and navigate to
\react-starter-kit-aem-headless-forms\src\components
. -
Create a copy of the
slider
orrichtext
folder, and rename the copied folder to materialtextfield. Theslider
andrichtext
are two sample custom components available in the starter app. You can use these components to create your own custom components. -
Open the
\react-starter-kit-aem-headless-forms\src\components\materialtextfield\index.tsx
file and replace the existing code with the below code. This code returns and renders a Google Material UI Text Field component.
import React from 'react';
import {useRuleEngine} from '@aemforms/af-react-renderer';
import {FieldJson, State} from '@aemforms/af-core';
import { TextField } from '@mui/material';
import Box from '@mui/material/Box';
import { richTextString } from '@aemforms/af-react-components';
import Typography from '@mui/material/Typography';
const MaterialtextField = function (props: State<FieldJson>) {
const [state, handlers] = useRuleEngine(props);
return(
<Box>
<Typography component="legend">{state.visible ? richTextString(state?.label?.value): ""} </Typography>
<TextField variant="filled"/>
</Box>
)
}
export default MaterialtextField;
The state.visible
part checks if the component is set to be visible. If it is, the label of the field is retrieved and displayed using richTextString(state?.label?.value)
.
Your custom component materialtextfield
is ready. Let’s set this custom component to replace all the instances of fieldType: “text-input” with Google Material UI Text Field.
3. Map custom component with headless form fields
The process of using a third-party library components to render form fields is known as mapping. You map each (fieldType) to a corresponding component of a third-party library.
All the mapping-related information is added to the mappings.ts
file. The ...mappings
statement in the mappings.ts
file refers to the default mappings, which overlays the (fieldType or :type
) with Adobe Spectrum components.
To add mapping for the materialtextfield
component, created in last step:
-
Open the
mappings.ts
file. -
Add the following import statement to include the
materialtextfield
component to themappings.ts
file:import MaterialtextField from "../components/materialtextfield";
-
Add the following statement to map the
text-input
with the materialtextfield component."text-input": MaterialtextField
The final code of the file looks like the following :
import { mappings } from "@aemforms/af-react-components"; import MaterialtextField from "../components/materialtextfield"; const customMappings: any = { ...mappings, "text-input": MaterialtextField }; export default customMappings;
-
Save and run the app. The first three fields of the form are rendered using Google Material UI Text Field:
Similarly, you can create custom components for message (“fieldType”: “multiline-input”) and rate the service (“fieldType”:“number-input”) fields. You can clone the following Git repository for custom components of the message and rate the service fields:
https://github.com/singhkh/react-starter-kit-aem-headless-forms
Next step
You have successfully rendered the form with custom components that use Google Material UI. Have you tried submitting the form by clicking the Submit Button (Mapped with the corresponding Google Material UI component)? If not, go ahead and give it a try.
Is the form submitting the data to any data source? No? Don’t worry. The reason is because your form is not configured to communicate with the runtime library.
How can you configure your form to communicate with it? An article is coming soon that explains everything in detail. Stay tuned!