Skip to content

eleven-labs/react-formbuilder

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React Form Builder

This package is built around Formik and inspired by the Symfony FormBuilder.

Summary

Requirements

Get started

Installation

npm i @elevenlabs/react-formbuilder --save
# or
yarn add @elevenlabs/react-formbuilder

Before you start, you need to create a theme and a translation function or use I18next.

Creating theme

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;

Creating translation function

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;

Configure theme and 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;
}

Creating a Simple 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;

Building and render the Form

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.

Custom render Formik

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;

Set initials values

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"
  });

Add validators and write custom

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'],
    ]
  });

API Reference

Global static

setTranslate: (translate: void) => this

setTheme: (theme: Theme) => this

setValidations: (validations: [Validation]) => this

Instance

setTranslate: (translate: void) => this

setTheme: (theme: Theme) => this

setValidations: (validations: [Validation]) => this

createForm: () => this

add: (name: string, fieldType: String, props: Props) => this

Formik: ReactNode

Fields: Array[ReactNode]

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published