All Projects → seeden → React Form Controlled

seeden / React Form Controlled

Licence: mit
Intuitive react forms for building powerful applications.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to React Form Controlled

react-use-hubspot-form
Embed HubSpot forms into your React components using hooks! Works with Create React App, Gatsby and other platforms.
Stars: ✭ 41 (-22.64%)
Mutual labels:  react-components, form
Jafar
🌟!(Just another form application renderer)
Stars: ✭ 107 (+101.89%)
Mutual labels:  react-components, form
React Atlas
Composable React components with CSS Modules.
Stars: ✭ 36 (-32.08%)
Mutual labels:  react-components
Vanilla Autokana
A Vanilla-JavaScript library to complete furigana automatically.
Stars: ✭ 48 (-9.43%)
Mutual labels:  form
Axiom React
Axiom - Brandwatch design system and React pattern library
Stars: ✭ 41 (-22.64%)
Mutual labels:  react-components
Vuelidation
simple, powerful, vuejs validation.
Stars: ✭ 38 (-28.3%)
Mutual labels:  form
Vue Formular
a comprehensive vue.js form component
Stars: ✭ 45 (-15.09%)
Mutual labels:  form
Ok
✔️ A tiny TypeScript library for form validation
Stars: ✭ 34 (-35.85%)
Mutual labels:  form
Vue Form Wizard
Vue.js 2 wizard
Stars: ✭ 1,053 (+1886.79%)
Mutual labels:  form
Ncform
🍻 ncform, a very nice configuration generation way to develop forms ( vue, json-schema, form, generator )
Stars: ✭ 1,009 (+1803.77%)
Mutual labels:  form
Formik Alicante
Formik slides & demos from React Alicante
Stars: ✭ 47 (-11.32%)
Mutual labels:  form
Should Enzyme
Useful functions for testing React Components with Enzyme.
Stars: ✭ 41 (-22.64%)
Mutual labels:  react-components
Smashing Form
MobX powered forms in React
Stars: ✭ 39 (-26.42%)
Mutual labels:  form
Mobx React Form
Reactive MobX Form State Management
Stars: ✭ 1,031 (+1845.28%)
Mutual labels:  form
Hellobooks
A Single-Page Library Management App built with nodejs, express and react and redux
Stars: ✭ 37 (-30.19%)
Mutual labels:  react-components
Insert Text At Cursor
Fast crossbrowser insertion of text at cursor position in a textarea / input
Stars: ✭ 49 (-7.55%)
Mutual labels:  form
Country Fns
🌏 Useful country data for forms and stuff.
Stars: ✭ 35 (-33.96%)
Mutual labels:  form
Usetheform
React library for composing declarative forms, manage their state, handling their validation and much more.
Stars: ✭ 40 (-24.53%)
Mutual labels:  form
React Bulma Components
React components for Bulma framework
Stars: ✭ 1,015 (+1815.09%)
Mutual labels:  react-components
Paragon
💎 Accessible components done right.
Stars: ✭ 52 (-1.89%)
Mutual labels:  react-components

React controlled form

Intuitive react forms for building powerful applications.

All components are controlled That means form is always showing the current state and data are immutable. Each form has own internal state that means you can skip onChange event. If you will change the value prop of the form component it will change the state of the form immediately.

NPM version build status Test coverage

Features

  • Immutable data
  • Controlled behavior (support for "uncontrolled" behaviour)
  • Build on latest standards ES6 and promises
  • Support for isomorphic application
  • You are able to use forms without special components
  • Support for arrays/lists and indexes
  • Standard html elements like an input, select, textarea and fieldset (arrays)
  • Custom components and support for 3rd party libraries
  • Validation
  • Tests and coverage

Support us

Star this project on GitHub.

Examples

Simple usage

import React, { Component } from 'react';
import Form from 'react-form-controlled';

export default class Example extends Component {
  constructor(props, context) {
    super(props, context);

    this.formData = {
      firstName: null,
      lastName: null
    };
  }

  onSubmit = (data) => {
    alert(`Hi ${data.firstName} ${data.lastName}`);
  }

  render() {
    return (
      <Form
        value={this.formData}
        onSubmit={this.onSubmit}
      >
        <label>
          <input name="firstName" />
        </label>

        <label>
          <input name="lastName" />
        </label>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Where is the input value?

Value is automatically added as prop to the inputs. When you will change it it will reload whole form (controlled form, but this is the work for React).

Arrays and controlled state

import React, { Component } from 'react';
import Form from 'react-form-controlled';

export default class Example extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      users: [{
        firstName: 'Zlatko'
      }, {
        firstName: 'Livia'
      }]
    };
  }

  onChange = (data) => {
    this.setState(data);
  }

  onSubmit = (data) => {
    alert(`Hi ${data.users[0].firstName}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onChange={this.onChange}
        onSubmit={this.onSubmit}
      >
        <fieldset name="users">
          <label>
            <input name="firstName" />
          </label>
        </fieldset>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

You can do what do you want with value.

import React, { Component } from 'react';
import Form from 'react-form-controlled';

export default class Example extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      users: [{
        firstName: 'Zlatko'
      }, {
        firstName: 'Livia'
      }]
    };
  }

  onChange = (data) => {
    this.setState(data);
  }

  onSubmit = (data) => {
    alert(`Hi ${data.users[0].firstName}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onChange={this.onChange}
        onSubmit={this.onSubmit}
      >
        <Row>
          <fieldset 
            name="users"
            render={({ value }) => value.map((user, index) => (
              <Column>
                <fieldset name={index}>
                  <label>
                    <input name="firstName" />
                  </label>
                </fieldset>
              </Column>
            ))}
          />
          </fieldset>
        </Row>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Simple arrays

If you are using fieldset with simple array do not enter the name attribute.

import React, { Component } from 'react';
import Form from 'react-form-controlled';

export default class Example extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      items: [123, 222]
    };
  }

  onSubmit = (data) => {
    alert(`Hi ${data.users[0].firstName}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onSubmit={this.onSubmit}
      >
        <fieldset name="items">
          <input type="text" />
        </fieldset>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Complex objects

If you want to use complex names you can use dot or array notation.

import React, { Component } from 'react';
import Form from 'react-form-controlled';

export default class Example extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      users: [{
        firstName: 'Zlatko',
        stats: {
          followers: 10,
        },
      }, {
        firstName: 'Livia',
        stats: {
          followers: 22,
        },
      }]
    };
  }

  onSubmit = (data) => {
    alert(`Hi ${data.users[0].firstName}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onSubmit={this.onSubmit}
      >
        <fieldset name="users">
          <label>
            <input name="firstName" />
          </label>
          <label>
            <input name="stats.followers" />
          </label>
        </fieldset>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

or you can use one more fieldset

import React, { Component } from 'react';
import Form from 'react-form-controlled';

export default class Example extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      users: [{
        firstName: 'Zlatko',
        stats: {
          followers: 10,
        },
      }, {
        firstName: 'Livia',
        stats: {
          followers: 22,
        },
      }]
    };
  }

  onSubmit = (data) => {
    alert(`Hi ${data.users[0].firstName}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onSubmit={this.onSubmit}
      >
        <fieldset name="users">
          <label>
            <input type="text" name="firstName" placeholder="First name" />
          </label>
          <fieldset name="stats">
            <label>
              <input type="text" name="followers" placeholder="Followers" />
            </label>
          </fieldset>
        </fieldset>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Indexes

If you are using arrays with fieldset you want to use indexes.

Props

render: function

Instead of having a component rendered for you, you can pass in a function. Your render function will be called with the same props that are passed to the component.

import React, { Component } from 'react';
import Form, { Index } from 'react-form-controlled';

export default class Component extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      users: [{
        firstName: 'Zlatko',
      }, {
        firstName: 'Livia',
      }]
    };
  }

  onSubmit = (data) => {
    alert(`Hi ${data.users[0].firstName}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onSubmit={this.onSubmit}
      >
        <fieldset name="users">
          <label>
            <Index 
              render={({ index }) => (
                <span>{index}.</span>
              )} 
            />
            <input name="firstName" />
          </label>
        </fieldset>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Parent values

You can use value from parent with dot notation. Example ".selected"

import React, { Component } from 'react';
import Form, { Index } from 'react-form-controlled';

export default class Component extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      options: ['dog', 'mouse', 'cat'],
      selected: 1,
    };
  }

  onSubmit = (data) => {
    alert(`Selected option is ${data.options[data.selected]}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onSubmit={this.onSubmit}
      >
        <fieldset name="options">
          <Index
            render={({ index }) => (
              <input type="radio" name="..selected" value={index} />
            )}
          />
          <input name="." />
        </fieldset>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Integrate with 3rd party libraries

Integration is very easy you can use Integrate component. Here is example with react-select library.

Props

value: string

Name of the integrated value property.

onChange: function

OnChange callback of the integrated component.

name: string

Name of the state property. You can use standard dot notation as always :)

import React, { Component } from 'react';
import Form, { Integrate } from 'react-form-controlled';
import Select from 'react-select';

export default class Component extends Component {
  onSubmit = (data) => {
    alert(`Selected option is ${data.selected}`);
  }

  render() {
    const options = [
      { value: 'one', label: 'One' },
      { value: 'two', label: 'Two' }
    ];

    return (
      <Form
        onSubmit={this.onSubmit}
      >
        <Integrate 
          name="selected" 
          render={({ value, onChange }) => (
            <Select options={options} value={value} onChange={onChange} />
          )}
        />

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Remove item from array

import React, { Component } from 'react';
import Form, { Remove } from 'react-form-controlled';

export default class Component extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      users: [{
        firstName: 'Zlatko',
      }, {
        firstName: 'Livia',
      }]
    };
  }

  onSubmit = (data) => {
    alert(`Hi ${data.users[0].firstName}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onSubmit={this.onSubmit}
      >
        <fieldset name="users">
          <label>
            <input name="firstName" />
            <Remove 
              render={({ onClick }) => (
                <button type="button" onClick={onClick}>Remove</button>
              )} 
            />
          </label>
        </fieldset>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Remove, Up and Down components has same properties like index. You can use render and component property as well.

Move item up/down in array

import React, { Component } from 'react';
import Form, { Up, Down } from 'react-form-controlled';

export default class Component extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      users: [{
        firstName: 'Zlatko',
      }, {
        firstName: 'Livia',
      }]
    };
  }

  onSubmit = (data) => {
    alert(`Hi ${data.users[0].firstName}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onSubmit={this.onSubmit}
      >
        <fieldset name="users">
          <input name="firstName" />
          <Up 
            render={({ onClick }) => (
              <button type="button" onClick={onClick}>Up</button>
            )} 
          />
          <Down 
            render={({ onClick }) => (
              <button type="button" onClick={onClick}>Down</button>
            )} 
          />
        </fieldset>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Working state

You can simply handle working state and show loading indicator. Form property onSubmit is based on promises. During you processing of this callback is form in the "isWorking" state. If the form is in the isWorking state you are not able to submit form again.

import React, { Component } from 'react';
import Form, { Working } from 'react-form-controlled';

export default class Component extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      users: [{
        firstName: 'Zlatko',
      }, {
        firstName: 'Livia',
      }]
    };
  }

  onSubmit = async (data) => {
    return new Promise((resolve) => {
      alert(`Hi ${data.users[0].firstName}`);

      setTimeout(resolve, 3000);
    });
  }

  render() {
    return (
      <Form
        value={this.state}
        onSubmit={this.onSubmit}
      >
        <fieldset name="users">
          <input name="firstName" />
        </fieldset>

        <Working 
          render={({ isWorking }) => isWorking ? 'isWorking' : 'idle'} 
        />
        <button type="submit">Submit</button>
      </Form>
    );
  }
}

So far so good (more complex form)

Try to image simple quiz with questions and answers. Y

Combination with other components

If you want to disable autoreplace of the standard components like an input, select, textarea etc... You can disable this behavior with the form parameter skipReplace. This feature is great if you want to use this library with other 3rd libraries. You will be able to use Input, Select, Textarea and Fieldset.

import Form, { Input, Select, Textarea, Fieldset } from from 'react-form-controlled';

export default class Component extends Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      users: [{
        firstName: 'Zlatko',
      }, {
        firstName: 'Livia',
      }]
    };
  }

  onSubmit(data) {
    alert(`Hi ${data.users[0].firstName}`);
  }

  render() {
    return (
      <Form
        value={this.state}
        onSubmit={this.onSubmit}
        skipReplace
      >
        <Fieldset name="users">
          <label>
            <Index render={({ index }) => index} />
            <Input type="text" name="firstName" placeholder="First name" />
          </label>
        </Fieldset>

        <button type="submit">Submit</button>
      </Form>
    );
  }
}

Support for schemas and validation?

This part is moved to another library named react-form-controlled-validate

Yes, you can use JSON schema as property to the form. Why JSON schema? Because it is a standard.

const schema = {
  type: "object",
  properties: {
    firstName: {
      type: "string"
    },
    lastName: {
      type: "string"
    }
  }
};

<Form schema={schema} ref="form">

const hasError = form.hasError('firstName'); //true
const isValid = from.isValid('firstName'); //false
const errors = form.getErrors(); //[{path: 'firstName', error: '...'}]

Support us

Star this project on GitHub.

Try our other React components

License

The MIT License (MIT)

Copyright (c) 2017 Zlatko Fedor

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].