Build forms π with React π
Explore the docs Β»
View Demo
Β·
Open an Issue
Β·
Request Feature
- π Table of Contents
- π About The Project
- π« Getting Started
- π² Usage
- π Documentation
- π₯ Add your values
- π Using existing components
βοΈ Roadmap- π Contributing
- π° License
- π Contact
This project implements a form generator with React Hooks.
To start to use the library, follow these simple steps.
This is an example of how to list things you need to use the software and how to install them.
npm install react react-dom
npm install @wavelop/dynamic-form @wavelop/dynamic-form-base-components
Create a configuration file:
// config.js
import { Input } from "@wavelop/dynamic-form-base-components";
import { validations } from "@wavelop/dynamic-form";
const { required, pattern } = validations;
export default [
{
name: "email",
label: "Email",
helperText: "Write your email",
tag: Input,
type: "email",
defaultValue: "[email protected]",
validations: [
{
kind: required,
message: "Email is required"
},
{
kind: pattern,
reg: /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/,
negate: true,
message: "You must type an email i.e. [email protected]"
}
]
}
];
import React, { useRef } from "react";
import PropTypes from "prop-types";
import {
DynamicForm,
useDynamicForm,
withDynamicForm
} from "@wavelop/dynamic-form";
import { form as formConfig } from "./config.js";
function Example(props) {
const dynamicForm = useDynamicForm();
const onSubmit = event => {
event.preventDefault();
try {
const { state, stateCrypted } = dynamicForm.submit();
// Do something with you valid state...
console.log(state, stateCrypted);
} catch ({numberOfErrors, errors}) {
// Do something in case of error...
console.log(numberOfErrors, errors);
}
};
// Render
return (
<form onSubmit={onSubmit}>
<DynamicForm
config={formConfig}
updateErrorAtBlur={true}
debug={true}
/>
<button
type="submit"
onClick={onSubmit}
>
Confirm
</button>
</form>
);
}
Example.propTypes = {
classes: PropTypes.object.isRequired
};
export default withDynamicForm()(Example);
For more examples, please refer to the Example folder.
Check out our documentation website.
Use the deafultValue
option to add an initial value to a field.
// config.js
...
fields: [
{
name: "field1_row2",
label: "field1_row2",
helperText: "field1_row2",
tag: "notRow",
defaultValue: "hello",
}
]
...
Core functionalities can be used with exinsing components, as with the one of the package @wavelop/dynamic-form-base-components
or you can create your custom components to inject inside the configuration.
WIP.
There are more way to create repeater components:
- Update your configuration dinamically adding new piece of configuration. To group state results you should use
rowOptions
, both on row container and field.
Example point 1
In the configuration create the initial configuration:
// config.js
// import and other stuff..
export default [
{
name: "row1",
tag: "row",
fields: [
{
name: "field1_row1",
label: "field1_row1",
helperText: "field1_row1",
tag: "notRow"
}
]
},
{
name: "row2",
tag: "row",
rowOptions: { // <--- Add rowOptions to the row container and use the property groupIn
groupIn: "rowsToGroupAsArray"
},
fields: [
{
name: "field1_row2",
label: "field1_row2",
helperText: "field1_row2",
tag: "notRow",
rowOptions: { // <--- Add rowOptions to the child and use the property alternativeName
alternativeName: "field1",
}
}
]
},
{
name: "row3",
tag: "row",
rowOptions: { // <--- Add rowOptions to the row container and use the property groupIn
groupIn: "rowsToGroupAsArray"
},
fields: [
{
name: "field1_row3",
label: "field1_row3",
helperText: "field1_row3",
tag: Input,
rowOptions: { // <--- Add rowOptions to the child and use the property alternativeName
alternativeName: "field1",
}
}
]
},
{
name: "row4",
tag: "row",
rowOptions: { // <--- Add rowOptions to the row container and use the property groupIn
groupIn: "rowsToGroupAsArray2"
},
fields: [
{
name: "field2_row4",
label: "field2_row4",
helperText: "field2_row4",
tag: "notRow",
rowOptions: { // <--- Add rowOptions to the child and use the property alternativeName
alternativeName: "field2",
}
},
]
},
{
name: "row5",
tag: "row",
rowOptions: { // <--- Add rowOptions to the row container and use the property groupIn
groupIn: "rowsToGroupAsArray2"
},
fields: [
{
name: "field2_row5",
label: "field2_row5",
helperText: "field2_row5",
tag: "notRow",
rowOptions: { // <--- Add rowOptions to the child and use the property alternativeName
alternativeName: "field2",
}
},
]
}
];
Where you use DynamicForm and execute submit having this current state:
{
"field1_row1": "1a",
"field1_row2": "2a",
"field1_row3": "3a",
"field2_row4": "4b",
"field2_row5": "5b",
}
// Other stuff...
const { state, stateGroupedByRows, stateGroupedByRowsGroupIn } = dynamicForm.submit();
console.log(state);
/**
{
"field1_row1": "1a",
"field1_row2": "2a",
"field1_row3": "3a",
"field2_row4": "4b",
"field2_row5": "5b",
}
**/
console.log(groupByRows);
/**
{
"row1": {
"field1_row1": "1a",
},
"row2": {
"field1_row2": "2a",
},
"row3": {
"field1_row3": "3a",
},
"row4": {
"field2_row4": "4b",
},
"row5": {
"field2_row5": "5b"
}
}
**/
console.log(groupByRowsGroupIn);
/**
{
"row1": {
"field1_row1": "1a",
"field2_row1": "1b"
},
"rowsToGroupAsArray": [
{
"field1": "2a",
},
{
"field1": "3a",
}
],
"rowsToGroupAsArray2": [
{
"field2": "4b"
},
{
"field2": "5b"
}
]
}
**/
Think now to add to the above configuration a new row:
configuration.push({
name: "row6",
tag: "row",
rowOptions: { // <--- Add rowOptions to the row container and use the property groupIn
groupIn: "rowsToGroupAsArray"
},
fields: [
{
name: "field1_row6",
label: "field1_row6",
helperText: "field1_row6",
tag: "notRow",
rowOptions: { // <--- Add rowOptions to the child and use the property alternativeName
alternativeName: "field1",
}
},
]
});
At the submit we will have (considering to have written 6a
inside the new input):
// Other stuff...
const { state, stateGroupedByRows, stateGroupedByRowsGroupIn } = dynamicForm.submit();
console.log(state);
/**
{
"field1_row1": "1a",
"field1_row2": "2a",
"field1_row3": "3a",
"field2_row4": "4b",
"field2_row5": "5b",
"field1_row6": "6a",
}
**/
console.log(groupByRows);
/**
{
"row1": {
"field1_row1": "1a",
},
"row2": {
"field1_row2": "2a",
},
"row3": {
"field1_row3": "3a",
},
"row4": {
"field2_row4": "4b",
},
"row5": {
"field2_row5": "5b"
},
"row6": {
"field1_row6": "6a"
}
}
**/
console.log(groupByRowsGroupIn);
/**
{
"row1": {
"field1_row1": "1a",
"field2_row1": "1b"
},
"rowsToGroupAsArray": [
{
"field1": "2a",
},
{
"field1": "3a",
},
{
"field1": "6a",
}
],
"rowsToGroupAsArray2": [
{
"field2": "4b"
},
{
"field2": "5b"
}
]
}
**/
1. (WIP) Create a custom component that implement the repeater logic and it update the form values.
See the open issues for a list of proposed features (and known issues).
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.
Read our contributing guide to learn about our development process, how to propose bugfixes and improvements, and how to build and test your changes.
Distributed under the MIT License. See LICENSE
for more information.
Matteo Granzotto - @wavelop - [email protected]
Project Link: https://github.com/Wavelop/dynamic-form