3.0.2 • Published 6 years ago

redux-form-manager v3.0.2

Weekly downloads
23
License
MIT
Repository
github
Last release
6 years ago

Redux Form Manager

A Form control built with and for React with Redux. Initially built for use in Redux Project

Validatation in form is easy to go...

If you liked, gimme a star, Thanks.

Release Issues

Latest version is v3.0.0

  • v3.0.0
  • v2.16.0
    • Fixed bugs rules equalLength, maxLength, minLength cannot validate and show message properly.
    • Update rules usage in README.md
  • v2.15.0
    • Add lodash to peerDependencies for features updateNestedFieldData
  • v2.14.0
    • Add feature - add props afterUpdateWhenValid (default = false) (thanks for KIRAN H)
  • v2.13.0
    • Fixed bugs Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the FormValidation component. (thanks for KIRAN H)
  • v2.12.0
    • When errorMessage is not empty, afterFieldChange won't trigger. (thanks for KIRAN H)
    • errorMessage is assigned to '' (empty String) when value is valid. (#issue2 closed thanks for GA-MO)
  • v2.10.0
    • Update React to version 15.6.0
    • Using PropTypes from 'prop-types'
  • v2.9.0
    • Add feature - props in formData formData: (state, props) => {}

Special Thanks to 'GA-MO'

alt text

This Component Repository created by React Component Boilerplate

React Component boilerplate for creating new React Compoment and everything you need to get started.

I recommend you to use it if you wanna create some awesome component for this world !

Prerequisite

This project uses library React-Redux-Gamo-boilerplate, React, Redux, React-Redux and ES2015 syntax, so make sure that you are capable with it.

Fast date with Demo & Examples

Live demo: https://hlex.github.io/redux-form-manager/demo

The live demo is still running redux-form-manager v3.0.0

Welcome to clone or fork and give me some pull request.

you can run this repository in your local machine by this command

$ npm run dev

it will serve at localhost:9000

Getting Started

$ npm install redux-form-manager --save

or if you prefer yarn..

$ yarn add redux-form-manager

WARNING !

Basically, we are using loganfsmyth/babel-plugin-transform-decorators-legacy (@ symbol) in any tutorials so make sure that you have added it in your .babelrc

Read more about loganfsmyth/babel-plugin-transform-decorators-legacy

if you don't want to, let's using this format to activate instead.

Stand Alone

export default bindFormValidation(core, afterFieldChange, mapStateToValidationPriority)(YourContainer)

With Connect (React-Redux)

const connectedComponent = connect(mapStateToProps, mapDispatchToProps)(YourContainer)
export default bindFormValidation(core, afterFieldChange, mapStateToValidationPriority)(
  connectedComponent
)

Advanced Usage: Reveal Key Features

There are many features we have provided

Basic Usage: Just copy paste

Create new js file and then copy following codes

import React, { Component } from 'react'
import { bindFormValidation } from 'redux-form-manager'

class TextInputField extends Component {
  handleChange = (e) => {
    const { onChange } = this.props
    onChange(e.target.value)
  }
  render = () => {
    const {
      label,
      value,
      disable,
      placeholder,
      hidden,
      errorMessage,
    } = this.props
    return (
      <div className={`box-form-input ${hidden && 'hidden'}`}>
        <label>{label}</label>
        <input
          type='text',
          value={value}
          disabled={disabled}
          placeholder={placeholder}
          onChange={this.handleChange}
        />
        <div className='error-message'>{errorMessage}</div>
      </div>
    )
  }
}

const createForm = (state) => {
  return {
    firstname: {
      name: 'firstname',
      type: 'input',
      label: 'Firstname',
      value: '',
      placeholder: 'write down your firstname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your firstname.'
      },
    },
    lastname: {
      name: 'lastname',
      type: 'input',
      label: 'Lastname',
      value: '',
      placeholder: 'write down your lastname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your lastname.'
      },
    }
  }
}

const core = {
  actionType: 'FORM/CHANGE/CUSTOMER',
  formData: (state, props) => createForm(state),
  renderUIInputField: (fieldData, updateValue) => {
    return <TextInputField {...fieldData} onChange={updateValue} />
  }
}

@bindFormValidation(core)
export default class Form extends Component {
  render() {
    const { formData, renderInputField, firstError } = this.props
    return (
      <div>
        <h1>Form</h1>
        {renderInputField(formData.firstname)}
        {renderInputField(formData.lastname)}
        <h4>error: {firstError}</h4>
      </div>
    )
  }
}

Boom! you got a form with field that could be validated, your page also. Look at your console that

Documentation

Table of Contents

Concept

Coming soon.

Setup

install npm packages

$ npm install redux-form-manager --save

or if you prefer yarn..

$ yarn add redux-form-manager --save

import library at the start of your js file

import { bindFormValidation } from 'redux-form-manager'

InputField

InputField is a UI component that receive event from user. You can create any JSX UI as you want. You just reminded that binding function props with renderUIInputField updateValue.

import React, { Component } from 'react'
class TextInputField extends Component {
  handleChange = (e) => {
    const { onUpdateValue } = this.props
    onUpdateValue(e.target.value)
  }
  render = () => {
    const {
      label,
      value,
      disable,
      placeholder,
      hidden,
      errorMessage,
    } = this.props
    return (
      <div className={`box-form-input ${hidden && 'hidden'}`}>
        <label>{label}</label>
        <input
          type='text',
          value={value}
          disabled={disabled}
          placeholder={placeholder}
          onChange={this.handleChange}
        />
        <div className='error-message'>{errorMessage}</div>
      </div>
    )
  }
}

Tips for InputField

You can create InputField Component that can morph to other inputs by defining props 'type' such as text, select, checkbox, radio etc.

import React, { Component } from 'react'

import TextInput from 'your/component/path'
import SelectInput from 'your/component/path'

class InputField extends Component {
  render() {
    switch (type) {
      case 'text':
        return <TextInput {...this.props}></TextInput>
      case 'select':
        return <SelectInput {...this.props}></SelectInput>
      default:
        return <TextInput {...this.props}></TextInput>
    }
  }
}

export default InputField

bindFormValidation()

bindFormValidation is a higher order function that return function which grant component to have form manager modules which are 'formData', 'renderInputField()', 'firstError'

Core

core is an object to assign variables to bindFormValidation()

all of these keys are required. (Please copy them)

const core = {
  actionType: 'FORM/CHANGE/CUSTOMER',
  formData: (state, props) => createForm(state),
  renderUIInputField: (fieldData, updateValue) => {
    return <InputField {...fieldData} onChange={updateValue} />
  }
}
@bindFormValidation(core)

actionType (defaultActionType in action)

As you know, redux's store has dispatch function which it is a process that fire action to reducer contains actionType and any variables. defaultActionType is a default actionType of store.dispatch when you didn't send fieldData's actionType (we'll talk about this later).

Working Example

Create new js file and then copy following codes

import React, { Component } from 'react'
import InputField, { bindFormValidation } from 'redux-form-manager'

const createForm = (state) => {
  return {
    firstname: {
      name: 'firstname',
      type: 'input',
      label: 'Firstname',
      value: '',
      placeholder: 'write down your firstname',
      disabled: false,
      hidden: false,
      rules: [
        required: 'Please fill in your firstname.'
      ],
    },
    lastname: {
      name: 'lastname',
      type: 'input',
      label: 'Lastname',
      value: '',
      placeholder: 'write down your lastname',
      disabled: false,
      hidden: false,
      rules: [
        required: 'Please fill in your lastname.'
      ],
    }
  }
}

const core = {
  actionType: 'FORM/CHANGE/CUSTOMER',
  formData: (state, props) => createForm(state),
  renderUIInputField: (fieldData, updateValue) => {
    switch (fieldData.type)
    return <InputField {...fieldData} onChange={updateValue} />
  }
}

@bindFormValidation(core)
export default class Form extends Component {
  render() {
    const { formData, renderInputField, firstError } = this.props
    return (
      <div>
        <h1>Form</h1>
        {
          renderInputField(formData.firstname)
        }
        {
          renderInputField(formData.lastname)
        }
        <h4>error: {firstError}</h4>
      </div>
    )
  }
}

Form Data

The common variable of this package is 'formData'

formData is a metadata of the form which it's type is Object. you can describe properties of your form in this variable. In any formData, it contains many fieldDatas.

Example

const formData = {
  firstname: {
    name: 'firstname',
    type: 'input',
    label: 'Firstname',
    value: '',
    placeholder: 'write down your firstname',
    disabled: false,
    hidden: false,
    rules: [
      required: 'Please fill in your firstname.'
    ],
  },
}

Field Data

Another variable of this package, 'fieldData'

fieldData is an Object that define properties of the field. For example, firstname field would have properties like this

Field Data Schema (Recommended)

PropertyType
nameString (*)
valueString, Object (*)
rulesObject (*)
typeString
labelString
placeholderString
disabledBoolean
hiddenBoolean

(*) is required

You can add any keys as your Component need.

we can define fieldData as follow.

const firstname = {
  name: 'firstname',
  type: 'input',
  label: 'Firstname',
  value: '',
  placeholder: 'write down your firstname',
  disabled: false,
  hidden: false,
  rules: {
    required: 'Please fill in your firstname.'
  },
},

Switch UI

In ordinary form, we know that there are many input types such as 'text', 'select', 'radio', 'checkbox' etc. In redux-form-manager we also provide you to config your input type.

just switch (case) in renderUIInputField

import React, { Component } from 'react'
import { bindFormValidation } from 'redux-form-manager'

import TextInput from 'your/component/path'
import SelectInput from 'your/component/path'

const createForm = (state) => {
  return {
    firstname: {
      name: 'firstname',
      type: 'text',
      label: 'Firstname',
      value: '',
      placeholder: 'write down your firstname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your firstname.'
      },
    },
    age: {
      name: 'age',
      type: 'select',
      label: 'Age',
      value: '',
      placeholder: '',
      disabled: false,
      hidden: false,
      options: [
        {
          label: '15 years old',
          value: '15',
        },
        {
          label: '20 years old',
          value: '20',
        }
      ]
      rules: {
        required: 'Please select your age.'
      },
    }
  }
}

const core = {
  actionType: 'FORM/CHANGE/CUSTOMER',
  formData: (state, props) => createForm(state),
  renderUIInputField: (fieldData, updateValue) => {
    switch (fieldData.type) {
      case 'text':
        return <TextInput {...fieldData} onChange={updateValue} />
      case 'select':
        return <SelectInput {...fieldData} onChange={updateValue} />
      default:
        return <InputField {...fieldData} onChange={updateValue} />
    }
  }
}

@bindFormValidation(core)
export default class Form extends Component {
  render() {
    const { formData, renderInputField, firstError } = this.props
    return (
      <div>
        <h1>Form</h1>
        { renderInputField(formData.firstname) }
        { renderInputField(formData.age) }
        <h4>error: {firstError}</h4>
      </div>
    )
  }
}

Custom UI

Building your own custom UI, we are going to use 2nd parameter of renderInputField.

import React, { Component } from 'react'
import { bindFormValidation } from 'redux-form-manager'

const createForm = (state) => {
  return {
    firstname: {
      name: 'firstname',
      type: 'input',
      label: 'Firstname',
      value: '',
      placeholder: 'write down your firstname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your firstname.'
      },
    },
    lastname: {
      name: 'lastname',
      type: 'input',
      label: 'Lastname',
      value: '',
      placeholder: 'write down your lastname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your lastname.'
      },
    }
  }
}

const core = {
  actionType: 'FORM/CHANGE/CUSTOMER',
  formData: (state, props) => createForm(state),
  renderUIInputField: (fieldData, updateValue) => {
    return <InputField {...fieldData} onChange={updateValue} />
  }
}

@bindFormValidation(core)
export default class Form extends Component {

  renderMyInputComponent = (fieldData, updateValue) => {
    return (
      <MyInputComponent
        {...fieldData}
        onUpdateValue={(value) => updateValue(fieldData.key, value)}
      />
    )
  }

  render() {
    const { formData, renderInputField, firstError } = this.props
    return (
      <div>
        <h1>Form</h1>
        { renderInputField(formData.firstname, this.renderMyInputComponent) }
        { renderInputField(formData.lastname) }
        <h4>error: {firstError}</h4>
      </div>
    )
  }
}

class MyInputComponent extends Component {

  handleChange = (e) => {
    const { onUpdateValue } = this.props
    onUpdateValue(e.target.value)
  }

  render() {
    return (
      const {
        label,
        value,
        disable,
        placeholder,
        hidden,
        errorMessage,
      } = this.props
      <div className={`box-form-input ${hidden && 'hidden'}`}>
        <label>{label}</label>
        <input
          type='text',
          value={value}
          disabled={disabled}
          placeholder={placeholder}
          onChange={this.handleChange}
        />
        <div className='error-message'>{errorMessage}</div>
      </div>
    )
  }
}

mapStateToValidationPriority

Validating each field by priority.

import React, { Component } from 'react'
import InputField, { bindFormValidation } from 'redux-form-manager'

const createForm = (state) => {
  return {
    firstname: {
      name: 'firstname',
      type: 'input',
      label: 'Firstname',
      value: '',
      placeholder: 'write down your firstname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your firstname.'
      },
    },
    lastname: {
      name: 'lastname',
      type: 'input',
      label: 'Lastname',
      value: '',
      placeholder: 'write down your lastname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your lastname.'
      },
    }
  }
}

const mapStateToValidationPriority = state => {
  return ['lastname', 'firstname']
}

const core = {
  actionType: 'FORM/CHANGE/CUSTOMER',
  formData: (state, props) => createForm(state),
  renderUIInputField: (fieldData, updateValue) => {
    return <InputField {...fieldData} onChange={updateValue} />
  }
}

@bindFormValidation(core, null, mapStateToValidationPriority)

afterFieldChange

Doing after update function when any field dispatch.

import React, { Component } from 'react'
import InputField, { bindFormValidation } from 'redux-form-manager'

const createForm = (state) => {
  return {
    firstname: {
      name: 'firstname',
      type: 'input',
      label: 'Firstname',
      value: '',
      placeholder: 'write down your firstname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your firstname.'
      },
    },
    lastname: {
      name: 'lastname',
      type: 'input',
      label: 'Lastname',
      value: '',
      placeholder: 'write down your lastname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your lastname.'
      },
    }
  }
}

const mapStateToValidationPriority = state => {
  return []
}

const afterFieldChange = (dispatch, state) => {
  return {
    firstname: (value, key) => {
      dispatch({
        type: 'FORM/CHANGE/CUSTOMER',
        key: 'lastname',
        value: value
      })
    },
  }
}

const core = {
  actionType: 'FORM/CHANGE/CUSTOMER',
  formData: (state, props) => createForm(state),
  renderUIInputField: (fieldData, updateValue) => {
    return <InputField {...fieldData} onChange={updateValue} />
  }
}

@bindFormValidation(core, afterFieldChange, mapStateToValidationPriority)

actionType

Customizing action type of each field.

import React, { Component } from 'react'
import InputField, { bindFormValidation } from 'redux-form-manager'

const createForm = (state) => {
  return {
    firstname: {
      actionType: 'MY_ACTION_FIRSTNAME',
      name: 'firstname',
      type: 'input',
      label: 'Firstname',
      value: '',
      placeholder: 'write down your firstname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your firstname.'
      },
    },
    lastname: {
      actionType: 'MY_ACTION_LASTNAME',
      name: 'lastname',
      type: 'input',
      label: 'Lastname',
      value: '',
      placeholder: 'write down your lastname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your lastname.'
      },
    }
  }
}

const afterFieldChange = (dispatch, state) => {
  return {
    firstname: (value, key) => {
      dispatch({
        type: 'FORM/CHANGE/CUSTOMER',
        key: 'lastname',
        value: value
      })
    },
  }
}

const core = {
  actionType: 'FORM/CHANGE/CUSTOMER',
  formData: (state, props) => createForm(state),
  renderUIInputField: (fieldData, updateValue) => {
    return <InputField {...fieldData} onChange={updateValue} />
  }
}

@bindFormValidation(core, afterFieldChange)

Custom Validation Rules

Rules build-in list

rules: {
  'required': `${message}`,
  'require': `${message}`,
  'email': `${message}`,
  'thaiMobile': `${message}`,
  'thaiPhone': `${message}`,
  'thaiId': `${message}`,
  'thaiFullname': `${message}`,
  'equalLength': {
    length: `${length}`,
    message: `${message}`
  },
  'maxLength': {
    maxLength: `${length}`,
    message: `${message}`
  },
  'minLength': {
    minLength: `${length}`,
    message: `${message}`
  },
  'alphabet': `${message}`,
  'number': `${message}`,
  'correctBracket': `${message}`,
  'notStartWithSpacing': `${message}`,
  'notContainDoubleSpacing': `${message}`,
  'notEndWithSpacing': `${message}`,
  'notContainSpecialChar': `${message}`,
}

Creating custom validation rules.

import React, { Component } from 'react'
import InputField, { bindFormValidation } from 'redux-form-manager'

const createForm = (state) => {
  return {
    firstname: {
      name: 'firstname',
      type: 'input',
      label: 'Firstname',
      value: '',
      placeholder: 'write down your firstname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your firstname.'
        customValidate: [
          {
            message: 'ชื่อต้องขึ้นต้นด้วยตัวเลข',
            valid: value => {
              return /^\d/.test(value)
            }
          }
        ]
      },
    },
    lastname: {
      name: 'lastname',
      type: 'input',
      label: 'Lastname',
      value: '',
      placeholder: 'write down your lastname',
      disabled: false,
      hidden: false,
      rules: {
        required: 'Please fill in your lastname.'
      },
    }
  }
}

const core = {
  actionType: 'FORM/CHANGE/CUSTOMER',
  formData: (state, props) => createForm(state),
  renderUIInputField: (fieldData, updateValue) => {
    return <InputField {...fieldData} onChange={updateValue} />
  }
}

@bindFormValidation(core)

Nested Field Data

Using Nested field data such as array of object.

Dynamic Field Data properties

Handling dynamic field properties.

Dispatch firsterror

Dispatch firstError to outside container.

Other Dispatchs

Using other event to dispatch.

Contribution

just clone and pull request.

Please open any issues, I will solve it as fast as possible.

Contact me mondit.thum@gmail.com

Thank you for your support !

3.0.2

6 years ago

3.0.1

6 years ago

3.0.0

6 years ago

2.16.0

6 years ago

2.15.0

6 years ago

2.14.0

7 years ago

2.13.0

7 years ago

2.12.12

7 years ago

2.12.11

7 years ago

2.12.10

7 years ago

2.12.9

7 years ago

2.12.8

7 years ago

2.12.7

7 years ago

2.12.6

7 years ago

2.12.5

7 years ago

2.12.4

7 years ago

2.12.3

7 years ago

2.12.2

7 years ago

2.12.1

7 years ago

2.12.0

7 years ago

2.11.1

7 years ago

2.11.0

7 years ago

2.10.0

7 years ago

2.9.0

7 years ago

2.8.0

7 years ago

2.7.0

7 years ago

2.6.0

7 years ago

2.5.0

7 years ago

2.4.0

7 years ago

2.3.0

7 years ago

2.2.0

7 years ago

2.1.0

7 years ago