Skip to content

cantonjs/react-form-mobx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

react-form-mobx

CircleCI Build Status Coverage Status PRs Welcome License

Declarative Form components for React, built on top of MobX

screenshot

Table of Contents

Philosophy

Declarative, just like React and HTML

Features Included

  • Support nested objects and arrays
  • Easy to create custom Input (or Select, Checkbox, Radio, etc) components
  • Easy to push, update or remove array items
  • Built-in validations (eg required, pattern, enum, etc)
  • Built-in formats (eg integer, number, boolean, etc)
  • Support data transformers / filters

Features NOT Included

  • No styles, just the original appearance, but you could add style easily
  • No HTTP requests, but you could choose any HTTP request library you like

Live Demo

Live demo on codesandbox

Getting Started

Installing

yarn add react-form-mobx

You may also need to install react, mobx and mobx-react

yarn add react mobx mobx-react react-form-mobx

Usage

import React, { Component } from 'react';
import { Form, Input, ObjectOf } from 'react-form-mobx';

export default class MyFriend extends Component {
  myData = {
    name: 'Luke Skywalker',
    height: 172,
    colors: {
      hair: 'blond',
      skin: 'fair',
    },
  },

  handleSubmit = (data) => {
    console.log('data', data);
  };

  render() {
    return (
      <Form value={this.myData} onSubmit={this.handleSubmit}>
        <Input name="name" />
        <Input name="height" format="number" />
        <ObjectOf name="colors">
          <Input name="hair" />
          <Input name="skin" />
        </ObjectOf>
      </Form>
    );
  }
}

Advanced Guides

Dynamic Array Items

import React, { Component } from 'react';
import { Form, Input, ArrayOf } from 'react-form-mobx';

export default class MyFriend extends Component {
  myData = {
    name: 'Luke Skywalker',
    starships: ['X-wing', 'Imperial shuttle'],
  },

  handleSubmit = (data) => {
    console.log('data', data);
  };

  render() {
    return (
      <Form value={this.myData} onSubmit={this.handleSubmit}>
        <Input name="name" />
        <ArrayOf name="starships">
          {(starships, { push, removeBy }) =>
            <div>
              {starships.map((starship) =>
                <span key={starship}>
                  <Input name={starship} />
                  <button type="button" onClick={removeBy(starship)}>Remove</button>
                </span>
              )}
              <button type="button" onClick={push}>Add Starship</button>
            </div>
          }
        </ArrayOf>
      </Form>
    );
  }
}

Creating Custom Input Component

MyInput.js

import React, { Component } from "react";
import { Demon } from "react-form-mobx";

export default class MyInput extends Component {
  render() {
    return (
      <Demon forwardedProps={this.props}>
        {(props, { isInvalid, errorMessage }) => (
          <label>
            <input
              style={{ borderColor: isInvalid ? "red" : "green" }}
              {...props}
            />
            {isInvalid && <span style={{ color: "red" }}>{errorMessage}</span>}
          </label>
        )}
      </Demon>
    );
  }
}

MyApp.js

import React, { Component } from "react";
import { Form } from "react-form-mobx";
import MyInput from "./MyInput";

export default class MyApp extends Component {
  render() {
    return (
      <Form value={this.myData}>
        <MyInput name="name" />
        {/* ... */}
      </Form>
    );
  }
}

References

Form Component

import { Form } from 'react-form-mobx';

Form component, just like HTML form component.

Props

Property Description Type Default
value Form data Object {}
onSubmit Defines a function will be called when form submit Function
onValid Defines a function will be called when form is valid Function
onInvalid Defines a function will be called when form is invalid Function
onValidChange Defines a function will be called when form valid status changed Function
onChange Defines a function will be called when form data changed Function
inputFilter Defines a filter function will be called when providing a new value Function
outputFilter Defines a filter function will be called when getting output value Function

Input Components

import { Input, Checkbox, Radio, Select, TextArea } from 'react-form-mobx';

These Input Components mean Input, Checkbox, Radio, Select, TextArea or other custom input components created by Demon.

Props

Property Description Type Default
name Field name String Required
defaultValue Default value when value is empty Any
defaultChecked Default checked, only work in checkable components (eg: Checkbox, Radio) Boolean
format Data format "integer", "number", "string", "boolean", "date", "time", "dateTime"
required Indicates whether field is required Boolean false
enum Validate a value from a list of possible values Array of String []
pattern Validate from a regular expression RegExp
maxLength Validate a max length of the field Number
minLength Validate a min length of the field Number
maximum Validate if the field is less than or exactly equal to "maximum" Number
exclusiveMaximum Validate if the field is less than (not equal to) "exclusiveMaximum" Number
minimum Validate if the field is greater than or exactly equal to "minimum" Number
exclusiveMinimum Validate if the field is greater than or exactly equal to "exclusiveMinimum" Number
validation Defines a validator function, should throw error if invalid Function
inputFilter Defines a filter function will be called when providing a new value to form Function
outputFilter Defines a filter function will be called when getting output value from form Function
withEmpty Indicates whether submit empty value or not "auto", true, false "auto"

The rest of the props are exactly the same as the original DOM attributes.

Notes
  • withEmpty: If value is empty (saying "", undefined, null, {} or []):
    • "auto" (Default): Will submit empty value only if pristine value is NOT empty
    • true: Will submit empty value
    • false: Will not submit empty value

ObjectOf Component

import { ObjectOf } from 'react-form-mobx';

ObjectOf component provides nested fields.

Props

Property Description Type Default
name Field name String Required
children Nested input nodes Node Required
onChange Defines a function will be called when data changed Function
inputFilter Defines a filter function will be called when providing a new value to form Function
outputFilter Defines a filter function will be called when getting output value from form Function

ArrayOf Component

import { ArrayOf } from 'react-form-mobx';

ArrayOf component provides array fields, and could be push, update or remove easily.

Props

Property Description Type Default
name Field name String Required
children Nested input nodes or function child that should return a node Node or Function Required
onChange Defines a function will be called when data changed Function
inputFilter Defines a filter function will be called when providing a new value to form Function
outputFilter Defines a filter function will be called when getting output value from form Function

Function Child

If children prop is a callback renderer function, it will provide two arguments:

  • names <Array>: An array of unique names that could be used as the key and name props of chidren components
  • helper <Object>: A helper object to manipulate the array:
    • push() <Function>: To push a new item
    • remove(name) <Function>: To remove a item by name
    • removeBy(name) <Function>: To create and return a remove(name) currying function

Please checkout Dynamic Array Items for usage example.

Submit, Reset, Clear Component

import { Submit, Reset, Clear } from 'react-form-mobx';
  • Submit: Just like HTML button component. Will emit onSubmit() in Form when click.
  • Reset: Just like HTML button component. Will reset all input values to pristine values in Form when click
  • Clear: Just like HTML button component. Will clear all input values in Form when click.

Props

Property Description Type Default
children children Node

The rest of the props are exactly the same as the original DOM attributes.

Demon Component

import { Demon } from 'react-form-mobx';

Demon component is the core of creating custom input components.

Props

Property Description Type Default
name Field name String Required
children Function child that should return a node Function Required
forwardedProps Forward props, Demon will decide to handle or forward them Object {}
checkable Indicates whether the component is checkable Boolean false
getValueFromChangeEvent Defines a function to get value in onChange arguments Function (ev) => ev.currentTarget.value
getCheckedFromChangeEvent Defines a function to get checked in onChange arguments Function (ev) => ev.currentTarget.checked
getKeyFromKeyPressEvent Defines a function to get key in onPress arguments Function (ev) => ev.key
propOnChange Defines the prop name of change event String "onChange"
propOnKeyPress Defines the prop name of key press event String "onKeyPress"
propOnBlur Defines the prop name of blur event String "onBlur"

Function Child

children prop provides two arguments:

  • proxyProps <Object>: Forwarded props object including value or checked, but excluding name, format, enum and other props only work in Demon component. Can be directly pass to child component (like <input {...proxyProps} />)

  • validState <Object>: Valid state helper object, including:

    • errorMessage <String>: Error message. Would be empty if the status is valid
    • isValid <Boolean>: Would be true if the status is valid
    • isInvalid <Boolean>: Would be true if the status is invalid
    • isTouched <Boolean>: Is touched or not. Useful if you don't want to show errorMessage when field is not touched

Proxied Props

By default, onChange, onKeyPress, onBlur props will be proxied.

  • onChange: Demon need to get the changed value or checked from the change event object to update value. You can change the getting function by setting getValueFromChangeEvent or getCheckedFromChangeEvent prop to Demon component.
  • onKeyPress: Demon need to get the key from the keyPress event object to decide to submit. You can change the getting function by settting propOnKeyPress prop to Demon component
  • onBlur: Demon need to listen to the blur event to set isTouched to true

Please checkout Creating Custom Input Component for usage example.

DemonButton Component

import { DemonButton } from 'react-form-mobx';

DemonButton component is the core of creating custom button (Submit, Reset or Clear) components.

Props

Property Description Type Default
children Function child that should return a node Function Required
type Button type "submit", "reset", "clear" "submit"
forwardedProps Forward props, DemonButton will decide to handle or forward them Object {}
getKeyFromKeyPressEvent Defines a function to get key in onPress arguments Function (ev) => ev.key
propOnKeyPress Defines the prop name of key press event String "onKeyPress"

Function Child

children prop provides one argument:

  • proxyProps <Object>: Forwarded props object. Can be directly pass to child component (like <button {...proxyProps} type="button" />)

License

MIT