@langleyfoxall/react-dynamic-form-builder

1.2.0-rc.8 • Public • Published



Form Builder


form-builder aims to help make dynamic react forms easier.



Contents

Installation

form-builder can be installed with NPM or Yarn.

# Installing with NPM
npm i --save @langleyfoxall/react-dynamic-form-builder
# Installing with Yarn
yarn add @langleyfoxall/react-dynamic-form-builder


Basic Example

Check out the demo.

// ./forms/create-user.js
export default [
    {
        name: 'first_name',
        label: 'First Name'
    },
    {
        name: 'last_name',
        label: 'Last Name'
    },
    {
        name: 'email_address',
        label: 'Email Address',
        type: 'email'
    },
    {
        name: 'password',
        label: 'Password',
        type: 'password'
    },
    {
        name: 'confirmation_password',
        label: 'Confirm Password',
        type: 'password'
    },
];
// ./components/create-user-modal.jsx
import React from 'react';
import axios from 'axios';

import FormBuilder from '@langleyfoxall/react-dynamic-form-builder';

import Modal from './modal';
import Form from '../forms/create-user';

class CreateUserModal extends React.Component {
    onSubmit(submission) {
        return new Promise(resolve => (
            axios
                .post('/api/register', submission.data.form)
                .then(() => console.log('Successfully signed up'))
                .catch(() => console.log('Unable to sign up'))
                .finally(resolve)
        ))
    }

    render() {
        return (
            <Modal>
                <FormBuilder
                    form={Form}
                    onSubmit={this.onSubmit}
                    submitButton={{
                        text: 'Sign Up'
                    }}
                />
            </Modal>
        )
    }
}

export default CreateUserModal;


Usage

form-builder makes it easier to create dynamic react forms by handling most of the logic involved.

Props

The following props can be passed:

  • defaultInputClass (string, default: input)
  • defaultLabelClass (string, default: label)
  • defaultContainerClass (string, default: container)
  • defaultValidationErrorClass (string, default: error-label)
  • defaultSubmitClass (string, default submit)
  • defaultValues (object, default: {})
  • values (object, default: null)
  • classPrefix (string, default: rdf)
  • invalidInputClass (string, default: invalid)
  • validInputClass (string, default: valid)
  • validationTimeout (number, default: 1000)
  • submitButton (object, { text, className? })
  • onSubmit (function)
  • loading (boolean, default false)
  • loadingElement (element, default null)
  • formErrors (object, default: {})
  • form (array)

defaultInputClass

defaultInputClass is appended to classPrefix on inputs.

// With default value
'rdf-input'

defaultLabelClass

defaultLabelClass is appended to classPrefix on labels.

// With default value
'rdf-label'

defaultContainerClass

defaultContainerClass is appended to classPrefix on input containers.

// With default value
'rdf-container'

defaultValidationErrorClass

defaultValidationErrorClass is appended to classPrefix on error texts.

// With default value
'rdf-error-label'

defaultSubmitClass

defaultSubmitClass is appended to classPrefix on the managed submit button.

// With default value
'rdf-submit'

defaultValues

defaultValues is used to pre-populate the inputs. It matches the property name against an input name.

// With default value
{}

// With custom value
{
    first_name: 'John',
    last_name: 'Doe',
}

values

values is used to overwrite the state of the form and set values from outside the form. This should be used in conjunction with onChange.

// With default value
null

// With custom value
{
    first_name: 'John',
    last_name: 'Doe',
}

classPrefix

classPrefix is used to prefix the majority of the class names.

// With default value
'rdf'

invalidInputClass

invalidInputClass is appended to classPrefix on invalid inputs.

// With default value
'rdf-invalid'

validInputClass

validInputClass is appended to classPrefix on valid inputs.

// With default value
'rdf-valid'

submitButton

submitButton can be used to pass a managed submit button into the form. className is optional and gets appended to classPrefix.

// With custom value
{
    text: 'Sign up'
    // className: 'secondary-button'
    // > 'rdf-secondary-button'
}

onSubmit

onSubmit should be called when the form is ready to be submitted, it is also triggered when the submitButton is pressed.

When onSubmit is triggered the callback will recieve an object containing:

{
    valid, // Boolean for valid state of inputs
    data: {
        form, // Data from inputs
        validation_errors // An object of errors for each input
    }
}

loading

loading is used to trigger a loading state on the form which is used to show the loading state on the managed submit button when a loadingElement has been passed.

// With default value
false

loadingElement

loadingElement is shown when loading is true and a submitButton has been passed.

// With default value
null

// With custom value
<p>Loading...</p>

formErrors

formErrors is used to display extra errors that cannot be managed internally by the form builder.

// With default value
{}

// With custom value
{
    first_name: '\'John\' is an invalid first name',
}

form

form is used to pass the schema used to build the form. This will be explained in more detail here.

// With custom value
[
    {
        name: 'first_name',
    },
]


Schema

A form schema can be passed into the form prop. This is used to build the form and display the inputs correctly. The schema consists of an array and child elements. A child can be an array or object. If an array is found then any objects inside will be put on the same row as each other (or wrapped in the same parent container).

Each object child needs at least a name, but can also become more complex and custom:

  • name (string)
  • placeholder (string)
  • label (string, function, string{})
  • type (string, default string)
  • render (function/node)
  • options (object[])
  • radioContainerClass (string)
  • containerClass (string)
  • inputClass (string)
  • defaultValue (mixed)
  • defaultOptionText (string)
  • validationRules (string, string[], object, object[], RegExp, RegExp[], function, function[])
  • transformer (function{})
  • filter (string, function, RegExp)
  • autocomplete (boolean)
  • renderIf (function)

name

name is used for when data is submitted and passed back to the onSubmit callback.

// With custom value
{
    name: 'first_name',
}

placeholder

placeholder is used to add placeholder text on empty text inputs.

// With custom value
{
    name: 'first_name',
    placeholder: 'Enter a first name',
}

label

label is used to add a label above the input. If an object is passed then at least text is required. className is optional.

// With custom value
{
    name: 'fist_name',
    label: 'First Name',
}

{
    name: 'first_name',
    label: {
        text: 'First Name',
        className: 'first-name-label'
    }
}

{
    name: 'first_name',
    label: props => (
        <label {...props}>
            First Name
        </label>
    )
}

type

type is used to change what type of input is rendered. Valid types input:

  • text
  • custom
  • password
  • date
  • email
  • month
  • number
  • range
  • color
  • search
  • time
  • url
  • week
  • textarea
  • checkbox
  • select
  • radio
// With default value
{
    name: 'first_name',
    type: 'string',
}

If custom is passed then it is recommended that render is also set.

render

render is used when a normal input is not enough. This can be used to completely customize an input.

When using a function it recieves the following parameters:

  • input (current input object)
  • value (current input value)
  • onChange (onChange handler)
  • onBlur (onBlur handler)
  • errors (current input errors)
  • state (form state)

When using a node it recieves the following props:

  • name (current input name)
  • placeholder (current input placeholder)
  • onChange (onChange handler)
  • onBlur (onBlur handler)
  • invalid (invalid boolean)
// With custom value
{
    name: 'first_name',
    render: () => (
        <h1>Custom Render</h1>
    ),
}

{
    name: 'first_name',
    render: <h1>Custom Render</h1>,
}

It works great with community addons, such as form-select.

// With form select
{
    name: 'custom',
    label: 'custom',
    render: (
        <Select
            options={[
                { label: 'a', value: 'a' },
                { label: 'b', value: 'b' },
            ]}
        />
    ),
}

{
    name: 'custom',
    label: 'custom',
    render: ({ name, placeholder }, value, onChange) => (
        <Select
            name={name}
            placeholder={placeholder}
            value={value}
            onChange={onChange}
            options={[
                { label: 'a', value: 'a' },
                { label: 'b', value: 'b' },
            ]}
        />
    ),
}

options

options are used for types select or radio. It should be an array of objects containing: text and value.

{
    name: 'gender',
    type: 'select',
    options: [
        { text: 'Male', value: 'male' },
        { text: 'Female', value: 'female' },
        { text: 'Other', value: 'other' },
    ],
}

radioContainerClass

radioContainerClass is appended to classPrefix on the container when type is radio.

// With default value
'rdf-'

conatinerClass

containerClass is appended to classPrefix on the container when type is not radio.

// With default value
'rdf-container'

inputClass

inputClass is appended to classPrefix on the input.

// With default value
'rdf-input'

defaultValue

defaultValue is inserted as the default value when the input has text, if type is checkbox then a truthy/falsey should be passed.

// With custom value
{
    name: 'first_name',
    defaultValue: 'John',
}

defaultOptionText

defaultOptionText is used to select a placeholder option for when type is select.

// With custom value
{
    name: 'gender',
    defaultOptionText: 'Select a gender...',
}

validationRules

validationRules is used when wanting to validate the content of the input. Valid validation rules:

  • required (not empty)
  • email (valid email)
  • decimal (numeric with optional decimal points)
// With custom value
{
    name: 'first_name',
    validationRules: 'required',
}

{
    name: 'age',
    validationRule: /^\d+$/,
}

{
    name: 'age',
    validationRule: '/^\d+$/',
}

{
    name: 'color',
    validationRule: this.isValidColor
}

{
    name: 'email_address',
    validationRules: [
        'required', 'email',
    ],
}

Note: Validation rule types can also be mixed.

transformer

tranformer is used to tranform the data before it gets validated/stored. It should be an object with the keys which define functions:

  • onChange
  • onBlur
// With custom value
{
    name: 'first_name',
    transformer: {
        onChange: this.uppercaseWords
    }
}

filter

filter is used can specific characters should never get stored as a value. It can be a string, function or RegExp. The character will be ignored if false is returned from the filter. There are some pre-defined filters:

  • numeric
  • decimal
// With pre-defined filter
{
    name: 'currency',
    filter: 'decimal'
}

// With function
{
    name: 'currency',
    filter: event => event.target.value === 'a' 
}

// With RegExp
{
    name: 'currency',
    filter: /[A-Ba-b]/
}

autocomplete

autocomplete can be used in an attempt to counter user agent autofill. By setting autocomplete to false a random input name is generated, rather than using the name of the input object.

// With custom value
{
    name: 'username',
    autocomplete: false
}

renderIf

renderIf can be used to render inputs based on the state of the form. When an input is hidden from the form the validationErrors and form value is reset.

// With custom value
{
    name: 'last_name',

    // Render if `first_name` has a truthy value
    renderIf: ({ form }) => (
        !!form.first_name
    )
}


Addons

A list of community addons, designed to work flawlessly with form-builder.

Make your own

Check out schema.render on how to format your component to work well with form-builder. When creating your component be mindful of what props are passed.

When using a function it recieves the following parameters:

  • input (current input object)
  • value (current input value)
  • onChange (onChange handler)
  • onBlur (onBlur handler)
  • errors (current input errors)
  • state (form state)

When using a node it recieves the following props:

  • name (current input name)
  • placeholder (current input placeholder)
  • onChange (onChange handler)
  • onBlur (onBlur handler)
  • invalid (invalid boolean)




Similar Packages

Readme

Keywords

Package Sidebar

Install

npm i @langleyfoxall/react-dynamic-form-builder

Weekly Downloads

16

Version

1.2.0-rc.8

License

LGPL-3.0

Unpacked Size

169 kB

Total Files

8

Last publish

Collaborators

  • alexcatch
  • dextermb
  • divineomega
  • nilesb
  • wheatleyjj