This package is built around Formik and inspired by the Symfony FormBuilder.
- React 15 or greater.
npm i @elevenlabs/react-formbuilder --save
# or
yarn add @elevenlabs/react-formbuilderBefore you start, you need to create a theme and a translation function or use I18next.
import React from "react";
import Form from "../components/Form";
import Button from "../components/Button";
const theme = {
Form: ({ children, onSubmit, className }) => <form onSubmit={onSubmit} className={className}>{children}</form>,
Row: ({ Label, Field, Errors, fieldType, errors, required }) => (
<Form.Row hasErrors={errors && errors.length > 0 ? true : false} required={required}>
{!['Button', 'CheckboxField'].includes(fieldType) && Label && <Label />}
<Field />
<Errors />
</Form.Row>
),
Label: ({ label, ...props }) => <Form.Label {...props}>{label}</Form.Label>,
Errors: ({ errors }) => <Form.Helper>{errors}</Form.Helper>,
TextField: (props) => <Form.Fields.Text {...props} />,
CheckboxField: (props) => <Form.Fields.Checkbox {...props} />,
CheckboxGroupField: (props) => <Form.Fields.Checkbox.Group {...props} />,
RadioField: (props) => <Form.Fields.Radio.Group {...props} />,
SelectField: (props) => <Form.Fields.Select {...props} />,
Button: (props) => <Button {...props} />
};
export default theme;const translate = (key, args) => {
const translations = {
"formbuilder.validators.required": ({ label }) =>
`Please input your ${label.toLowerCase()}!`,
"formbuilder.validators.email": () => `Email is invalid!`,
"formbuilder.validators.is_greater_than": ({ label, length }) =>
`${label} has to be longer than ${length} characters!`
};
return translations[key] ? translations[key](args) : key;
};
export default translate;Globally
import FormBuilder from "@elevenlabs/react-formbuilder";
import theme from "./theme";
import translate from "./translate";
export const initConfigFormBuilder = () => {
FormBuilder.translate = translate;
FormBuilder.theme = theme;
}Or instance formbuilder
const LoginForm = () => {
const form = new FormBuilder();
form
.setTranslate(translate)
.setTheme(theme)
.createForm();
return form;
}We will take as an example a login form.
import FormBuilder from "@elevenlabs/react-formbuilder";
import theme from "../theme";
import translate from "../translate";
const LoginForm = () => {
const form = new FormBuilder();
form
.createForm()
.add("email", "TextField", {
label: "Email",
required: true,
validators: ["Required", "Email"],
initialValue: "[email protected]",
})
.add("password", "TextField", {
type: "password",
label: "Password",
required: true,
validators: [
"Required",
["IsGreaterThan", { length: 6 }]
],
})
.add("rememberMe", "CheckboxField", {
label: "Remember me",
})
.add("submit", "Button", {
type: "submit",
label: "Login"
});
return form;
};
export default LoginForm;import React, { Component, Fragment } from "react";
import PropTypes from "prop-types";
import LoginFormBuilder from "../formBuilder/login";
class LoginScreen extends Component {
state = {
LoginForm: null
};
componentWillMount() {
const LoginForm = LoginFormBuilder();
this.setState({ LoginForm });
}
onSubmit = (payload, formikProps) => {};
render() {
const { LoginForm } = this.state;
return (
<div className="screen-login">
{LoginForm ? (
<LoginForm.Formik
className="screen-login__form"
onSubmit={this.onSubmit}
/>
) : (
<p>Loading ...</p>
)}
</div>
);
}
}
export default LoginScreen;You can find the following code here.
If you want to completely customize the form this is possible, here is an example:
import React, { Component } from "react";
import LoginFormBuilder from "../formBuilder/login";
class LoginScreen extends Component {
state = {
LoginForm: null
};
componentWillMount() {
const LoginForm = LoginFormBuilder();
this.setState({ LoginForm });
}
onSubmit = (payload, formikProps) => {};
formikRender = (formikProps) => {
const { LoginForm } = this.state;
const { Fields } = LoginForm;
return (
<LoginForm.Form formikProps={formikProps}>
<LoginForm.Form {...formikProps}>
<Fields.Email.Row />
{/* or */}
{/* LoginForm.Row('email') */}
<div className="form__row">
<Fields.Password.Label />
<Fields.Password.Field />
<Fields.Password.Errors />
</div>
{/* or */}
{/* {LoginForm.Label('password')}
{LoginForm.Field('password')}
{LoginForm.Errors('password')} */}
<Fields.Submit.Row />
</LoginForm.Form>
);
};
render() {
const { LoginForm } = this.state;
return (
<div className="screen-login">
{LoginForm ? (
<LoginForm.Formik
className="screen-login__form"
onSubmit={this.onSubmit}
render={this.formikRender}
/>
) : (
<p>Loading ...</p>
)}
</div>
);
}
}
export default LoginScreen;To hydrate the form with data.
From the component:
<LoginForm.Formik
className="screen-login__form"
onSubmit={this.onSubmit}
initialValues={{username: 'john', password: 'doe'}}
render={this.formikRender}
/>From the formBuilder:
const form = new FormBuilder();
form
.createForm()
.add("email", "TextField", {
label: "Email",
required: true,
initialValue: '[email protected]',
validators: ["Required", "Email"]
})
.add("password", "TextField", {
type: "password",
label: "Password",
required: true,
validators: ["Required", ["IsGreaterThan", { length: 6 }]]
})
.add("submit", "Button", {
type: "submit",
label: "Login"
});List of available validators:
- Required
Apply a validator with this default key. The translation key is created automatically generated in relation to the validator name, it is always in snakeCase. Example for Required this will be validators.required.
const form = new FormBuilder();
form
.createForm()
.add("name", "TextField", {
label: "Name",
validators: ["Required"]
});If you want to change the default generate key:
const form = new FormBuilder();
form
.createForm()
.add("name", "TextField", {
label: "Name",
validators: [
['Required', 'validators.required_custom'],
]
});A completely custom validator:
const form = new FormBuilder();
form
.createForm()
.add("name", "TextField", {
label: "Name",
validators: [
[v => !empty(v), 'validators.required_custom'],
]
});And examples with arguments:
const form = new FormBuilder();
form
.createForm()
.add("name", "TextField", {
label: "Name",
validators: [
['IsGreaterThan', { length: 6 }],
]
});const form = new FormBuilder();
form
.createForm()
.add("name", "TextField", {
label: "Name",
validators: [
['IsGreaterThan', { length: 6 }, 'validators.is_greater_than_custom'],
]
});const form = new FormBuilder();
form
.createForm()
.add("name", "TextField", {
label: "Name",
validators: [
[(v, { length }) => v.length >= length, { length: 6 }, 'validators.is_greater_than_custom'],
]
});Global static
Instance