1.0.0 • Published 6 years ago

react-form-mobx v1.0.0

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

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

PropertyDescriptionTypeDefault
valueForm dataObject{}
onSubmitDefines a function will be called when form submitFunction
onValidDefines a function will be called when form is validFunction
onInvalidDefines a function will be called when form is invalidFunction
onValidChangeDefines a function will be called when form valid status changedFunction
onChangeDefines a function will be called when form data changedFunction
inputFilterDefines a filter function will be called when providing a new valueFunction
outputFilterDefines a filter function will be called when getting output valueFunction

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

PropertyDescriptionTypeDefault
nameField nameString Required
defaultValueDefault value when value is emptyAny
defaultCheckedDefault checked, only work in checkable components (eg: Checkbox, Radio)Boolean
formatData format"integer", "number", "string", "boolean", "date", "time", "dateTime"
requiredIndicates whether field is requiredBooleanfalse
enumValidate a value from a list of possible valuesArray of String[]
patternValidate from a regular expressionRegExp
maxLengthValidate a max length of the fieldNumber
minLengthValidate a min length of the fieldNumber
maximumValidate if the field is less than or exactly equal to "maximum"Number
exclusiveMaximumValidate if the field is less than (not equal to) "exclusiveMaximum"Number
minimumValidate if the field is greater than or exactly equal to "minimum"Number
exclusiveMinimumValidate if the field is greater than or exactly equal to "exclusiveMinimum"Number
validationDefines a validator function, should throw error if invalidFunction
inputFilterDefines a filter function will be called when providing a new value to formFunction
outputFilterDefines a filter function will be called when getting output value from formFunction
withEmptyIndicates 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

PropertyDescriptionTypeDefault
nameField nameString Required
childrenNested input nodesNode Required
onChangeDefines a function will be called when data changedFunction
inputFilterDefines a filter function will be called when providing a new value to formFunction
outputFilterDefines a filter function will be called when getting output value from formFunction

ArrayOf Component

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

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

Props

PropertyDescriptionTypeDefault
nameField nameString Required
childrenNested input nodes or function child that should return a nodeNode or Function Required
onChangeDefines a function will be called when data changedFunction
inputFilterDefines a filter function will be called when providing a new value to formFunction
outputFilterDefines a filter function will be called when getting output value from formFunction

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

PropertyDescriptionTypeDefault
childrenchildrenNode

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

PropertyDescriptionTypeDefault
nameField nameString Required
childrenFunction child that should return a nodeFunction Required
forwardedPropsForward props, Demon will decide to handle or forward themObject{}
checkableIndicates whether the component is checkableBooleanfalse
getValueFromChangeEventDefines a function to get value in onChange argumentsFunction(ev) => ev.currentTarget.value
getCheckedFromChangeEventDefines a function to get checked in onChange argumentsFunction(ev) => ev.currentTarget.checked
getKeyFromKeyPressEventDefines a function to get key in onPress argumentsFunction(ev) => ev.key
propOnChangeDefines the prop name of change eventString"onChange"
propOnKeyPressDefines the prop name of key press eventString"onKeyPress"
propOnBlurDefines the prop name of blur eventString"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

PropertyDescriptionTypeDefault
childrenFunction child that should return a nodeFunction Required
typeButton type"submit", "reset", "clear""submit"
forwardedPropsForward props, DemonButton will decide to handle or forward themObject{}
getKeyFromKeyPressEventDefines a function to get key in onPress argumentsFunction(ev) => ev.key
propOnKeyPressDefines the prop name of key press eventString"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

1.0.0

6 years ago

1.0.0-1

6 years ago

0.6.1

6 years ago

0.6.0

6 years ago

0.5.0

6 years ago

0.4.0

6 years ago

0.3.0

6 years ago

0.2.1

6 years ago

0.2.0

6 years ago

0.1.0

6 years ago

0.0.0

6 years ago

0.0.0-alpha.2

6 years ago