0.1.5 • Published 6 years ago

@praneshravi/react-forms v0.1.5

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

Logo

Build Status npm version

A simple, super-flexiable, extensible config based form generator for React.

Features

  • Super-flexible
  • Config based form element creation
  • Take super control over all the form elements
  • Use third party components as form element

Install

  npm i @praneshravi/react-forms

  # or

  yarn add @praneshravi/react-forms

Usage

import '@praneshravi/react-forms/css/index.css'
import React, { Component } from 'react'
import Form from '@praneshravi/react-forms'

class Example extends Component {
  constructor() {
    super()
    this.state = {}
    this.onChange = this.onChange.bind(this)
  }

  onChange(newState) {
    this.setState(newState)
  }

  render() {
    const config = [
      {
        id: 'firstName',
        type: 'text',
        displayName: 'First Name',
        resultPath: 'name.firstName',
        placeholder: 'Enter your first name',
      },
    ]

    return <Form config={config} store={this.state} onChange={this.onChange} />
  }
}

React Forms Props

PropertyTypeDefaultDescription
configarray[]Config to populate form elements.
storeobject | array{}The data store to read the values from.
onChangefunctionundefinedCallback for onChange event
onBlurfunctionundefinedCallback for onBlur event
onFocusfunctionundefinedCallback fro onFocus event
customComponentResolversarrayundefinedArray of resolvers to resolve custom form elements
customValueResolversarrayundefinedArray of resolvers to resolve the value of the custom form elements
useNativeEventbooleanfalseWhether to return the new state or native JS event object on events
primaryButtonstring | false | undefined'Submit'Title for the primary button. false to remove button
secondaryButtonstring | false | undefined'Cancel'Title for the secondary button. false to remove button
onSecondaryButtonClickfunction()=> {}onClick event handler for secondary button

Configuration File Options

PropertyTypeDefaultDescription
idstringundefinedID for each form field. This should be unique.
typestringundefinedType of the form field to be generated. The native package supports text, color, date, email, month, number, tel, time, url, week, toggle, radio, checkbox, range, textarea, dropdown types. New types can be added via Custom Form Elements.
resultPathstringundefinedA dot-prop-immutable compatible path to store the form field value.
displayNamestringundefinedDisplay text for the form field.
classNamestringundefinedClassName for the root form field element.
isHiddenfunctionundefinedMethod to hide form field element in runtime. (store) => boolean
optionalbooleanundefinedSays if the form field is optional.
placeholderstringundefinedPlaceholder text for the form elements
helpTextstringundefinedHelp text for a form element
helpTextOptionsobjectundefinedSee rc-tooltip props
optionsarray[]Array of options. ({ value: any, label: any })[]
separatorstring','Separator to join/separate multiple values. Used by checkbox, multi-dropdown, etc.
topComponentfunctionundefinedMethod to render any additional elements to the top of the form field element. (store) => JSX.Element
simpleValuesbooleanfalseHandle multi values as string. Works along with separator.
bottomComponentfunctionundefinedMethod to render any additional elements to the bottom of the form field element. (store) => JSX.Element
componentPropsobjectundefinedAny additional props that should be passed to the underlying form field element. For example, to make the dropdown multi-select, pass componentProps: { multiple: true }.
instantValidationbooleanfalseDo validation on user input.
requiredbooleanfalseMake the field required.
validationfunctionundefinedMethod to perform validation. (value) => errorMessage|null
modifyStoreBeforeChangefunctionundefinedMethod to modify store before onChange handler is called. (config, value, store) => store.

Available componentProps

type: toggle

PropertyTypeDefaultDescription
infoTextstringundefinedInfo text to be displayed to the right of the toggle switch

type: range

PropertyTypeDefaultDescription
showRangebooleantrueShows the min and max value of the slider
showValuebooleantrueShows the current range value explicitly

Form Groups

It is possible to group form elements. Take a look at the following example.

import '@praneshravi/react-forms/css/index.css'
import React, { Component } from 'react'
import Form from '@praneshravi/react-forms'

class Example extends Component {
  constructor() {
    super()
    this.state = {}
    this.onChange = this.onChange.bind(this)
  }

  onChange(newState) {
    this.setState(newState)
  }

  render() {
    const config = [
      {
        id: 'group-1',
        type: 'group',
        displayName: 'Group 1',
        description: 'This is group 1',
        elements: [
          {
            id: 'firstName',
            type: 'text',
            displayName: 'First Name',
            resultPath: 'name.firstName',
            placeholder: 'Enter your first name',
          },
          {
            id: 'LastName',
            type: 'text',
            displayName: 'Last Name',
            resultPath: 'name.LastName',
            placeholder: 'Enter your last name',
          },
        ],
      },
      {
        id: 'group-2',
        type: 'group',
        displayName: 'Group 2',
        description: 'This is group 1',
        elements: [
          {
            id: 'country',
            type: 'text',
            displayName: 'First Name',
            resultPath: 'name.country',
            placeholder: 'Enter your country',
          },
          {
            id: 'state',
            type: 'text',
            displayName: 'Last Name',
            resultPath: 'name.state',
            placeholder: 'Enter your state',
          },
        ],
      },
    ]

    return <Form config={config} store={this.state} onChange={this.onChange} />
  }
}

Validation

Validations are done per form element. Add a validation() method in the form element config. Validations can be done in two ways.

  • Set instantValidation: true in the form element config. Now, the validation method will be called each time on user input.

  • Use validate() method of the form instance. This returns an array of errors, if any. Useful for conditional based approach.

import '@praneshravi/react-forms/css/index.css'
import React, { Component } from 'react'
import Form from '@praneshravi/react-forms'

class Example extends Component {
  constructor() {
    super()
    this.state = {}
    this.onChange = this.onChange.bind(this)
  }

  onChange(newState) {
    this.setState(newState)
  }

  onSubmit() {
    const errors = this.form.validate()
    console.log(errors)
  }

  render() {
    const config = [
      {
        id: 'answer',
        type: 'text',
        displayName: 'What is 4 + 5',
        resultPath: 'answer',
        placeholder: 'Answer',
        validation: value => value !== '9' && 'Wrong Answer',
      },
    ]

    return (
      <Form
        ref={el => (this.form = el)}
        config={config}
        store={this.state}
        onChange={this.onChange}
      />
    )
  }
}

Modify store value directly from config

You can access the store and change any store value directly from the config using modifyStoreBeforeChange method. This method will be called before onChange event. You can return a modified state and it will be passed to the onChange handler. The primary use case for this will be, to change a form value based on another form value.

import '@praneshravi/react-forms/css/index.css'
import React, { Component } from 'react'
import Form from '@praneshravi/react-forms'

class Example extends Component {
  constructor() {
    super()
    this.state = {}
    this.onChange = this.onChange.bind(this)
  }

  onChange(newState) {
    this.setState(newState)
  }

  render() {
    const config = [
      {
        id: 'firstName',
        type: 'text',
        displayName: 'First Name',
        resultPath: 'name.firstName',
        placeholder: 'Enter your first name',
        modifyStoreBeforeChange: (config, value, store) => {
          store.readonly = value
          return store
        },
      },
      {
        id: 'readyonly',
        type: 'text',
        displayName: 'Output',
        resultPath: 'readonly',
        componentProps: {
          disabled: true,
        },
      },
    ]

    return <Form config={config} store={this.state} onChange={this.onChange} />
  }
}

Custom Buttons

It is possible to add custom buttons. Just wrap your buttons with <Form>.

<Form
  ref={el => (this.form = el)}
  config={config}
  store={this.state}
  onChange={this.onChange}
>
  <button type="submit">Custom Button</button>
</Form>

Custom Form Elements

Custom form elements can be added to any instance of react-forms via customComponentResolvers and customValueResolvers props.

  • customComponentResolvers(type: string) => ({ config: IReactFormConfig, value: any, callbacks: any }) => JSX.Element

Returns a valid React stateless function based on the custom type.

  • customValueResolvers(config: IReactFormConfig, value: any) => any

Returns a resolved value based on the custom type.

See the following example to understand how it works.

import '@praneshravi/react-forms/css/index.css'
import React, { Component } from 'react'
import Select from 'react-select'
import Form, { getNewState } from '@praneshravi/react-forms'

const customComponentsResolver = (type) => {
  switch(type) {
    case 'custom-dropdown':
      return ({ config, value = '', callbacks= {}}) =>
        <Select
          value={value}
          options={config.options}
          { ...callbacks }
          { ...config.componentProps } />
    default:
      return <span/>
  }
}

const customValueResolver = (config: any, value: any) => {
  switch (config.type) {
    case 'react-select':
      return value ? value.value : ''
  }
}

class Example extends Component {
  constructor() {
    super()
    this.state = {}
    this.onChange = this.onChange.bind(this)
  }

  onChange(newState) {
    this.setState(newState)
  }

  render() {
    const config = [
      {
        id: 'firstName',
        type: 'custom-dropdown',
        resultPath: 'country'
        displayName: 'Shipping Country',
        placeholder: 'Select a country',
        options: [
          {
            value: 'india',
            label: 'India',
          },
          {
            value: 'usa',
            label: 'The United States',
          },
          {
            value: 'china',
            label: 'China',
          }
        ],
      },
    ]

    return <Form
      customComponentResolvers={[customComponentsResolver]}
      customValueResolvers={[customValueResolver]}
      config={config}
      store={this.state}
      onChange={this.onChange} />
  }
}

Development

yarn install
yarn build
yarn start:examples

Refer package.json for more commands

License

MIT

0.1.5

6 years ago

0.1.4

6 years ago

0.1.3

6 years ago

0.1.2

6 years ago

0.1.1

6 years ago

0.1.0-alpha

6 years ago

0.0.0-alpha

6 years ago