npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-distributed-forms

v1.1.10

Published

react-distributed-forms React component

Downloads

140

Readme

react-distributed-forms

Travis npm package Coveralls

Forms are central in modern web-apps, react-distributed-forms let you write them in the easiest way. HTML is cleaner, changes control is centralized.

  • No CSS inside, you can use yours!
  • 2-ways data-binding included
  • You can granularly customize behaviors with context
  • You can put Forms in some files and fields in other files
  • ...without pass props or wiring them.
  • You can simply replace your HTML components
  • It just works!

Write less, do more

This 20 rows are a Form with data-binding with the state of the Component, that save changes when click on Submit and when user stop editing fields.

import React from "react";
import { Form, Input, Selext, Textarea, Button } from "react-distributed-forms";

class Story extends React.Component {
  state = {};

  saveData() {
    const formData = this.state; // send formData to backend
  }

  render() {
    return (
      <Form
        binding={this}
        onFieldDidChanged={this.saveData}
        onSubmit={this.saveData}
      >
        <Input name="author" />
        <Input name="private" type="checkbox" />
        <Textarea name="story" />
      </Form>
    );
  }
}

Live Demo of this example: https://codesandbox.io/s/k0n810zymo;

Live Demo

Install

Add react-distributed-forms to your project.

npm i react-distributed-forms --save

Includes

import { Form, Input, Selext, Textarea, Button } from "react-distributed-forms";

Getting Started

Basic <Input>

<Input />

// <input type="text"></input>

<Input> with values

<Form values={{ username: "Hero2018" }}>
  <Input name="username" />
</Form>

// <input type="text" name="username" value="Hero2018"></input>

<Input> with onChange listener

<Form onFieldChange={({ name, value }) => {}}>
  <Input name="username" />
</Form>

// <input type="text" name="username"></input>

Get notified when user remove focus from field, if the field value is changed

<Form onFieldDidChanged={({ name, value }) => {}}>
  <Input name="username" />
  <Select name="genre">
    <option value="m">Male</option>
    <option value="f">Female</option>
  </Select>
</Form>

// <input type="text" name="username"></input>
// <select name="genre">
//   <option value="m">Male</option>
//   <option value="f">Female</option>
// </select>

Data Binding

With react-distributed-forms you can pass a React Component to <Form>, this will be used to write every fields'change into the component state.

This is the simplest scenario, when you bind the state of the component:

class SomeComponent extends React.Component {
  state = {
    first_name: "George"
  };

  render() {
    return (
      <Form binding={this}>
        <Input name="first_name" />
      </Form>
    );
  }
}

You can also bind Form values to a different key in the state object:

class SomeComponent extends React.Component {
  state = {
    formdata: {
      first_name: "George"
    }
  };

  render() {
    return (
      <Form binding={[this, "formdata"]}>
        <Input name="first_name" />
      </Form>
    );
  }
}

Live Demo of Data Binding

Nested Forms

You can have a <Form> inside another <Form>, in this case the Forms will receive changes from all the fields contained in the Form itself or in a Form down in the hierarchy.

In the example Form with id="parent" will receive changes from all the fields inside: username, genre, and also "privacy". The Form with id="child" will receive only the changes of the field "privacy".

<Form id="parent" onFieldChange={({ name, value }) => {}}>
  <Input name="username" />
  <Select name="genre">
    <option value="m">Male</option>
    <option value="f">Female</option>
  </Select>
  <Form id="child" onFieldChange={({ name, value }) => {}}>
    <label>Privacy Agreement</label>
    <Input type="checkbox" name="privacy" />
  </Form>
</Form>

If you don't want that a Form propagate changes to upper levels, use the prop "stopPropagation" prop. In the example the Form with id="parent" will receive changes only from "username" and "genre" because the nested Form has "stopPropagation" set

<Form id="parent" onFieldChange={({ name, value }) => {}}>
  <Input name="username" />
  <Select name="genre">
    <option value="m">Male</option>
    <option value="f">Female</option>
  </Select>

  <Form onFieldChange={({ name, value }) => {}} stopPropagation>
    <label>Privacy Agreement</label>
    <Input type="checkbox" name="privacy" />
  </Form>
</Form>

Unlock the power of React context API

react-distributed-forms is built on top of react-distributed-context that implements React context API.

From React Context page:

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

This means that even if the Fields or the Nested Form you put inside a Form is elsewhere in your code, you don't have to wire it passing props, or building it in the same component.

You just create an <Input>, or <Select>, or <Textarea>, or <Button>, or a <Form> itself, wherever you need in your code, and if it has a <Form>as an ancestor in the tree, it will start to talk with him.

Demo:

Context

Context + Data Binding

Example:

Animal.js

const Animal = () => (
  <Form onFieldChange={({ name, value }) => {}}>
    <Select name="type">
      <option>Cat</option>
      <option>Fish</option>
      <option>Bird</option>
    </Select>

    {/* render the right animal component */}
  </Form>
);

Cat.js

// you don't need a <Form>,
// because you will render <Cat>
// inside a component that already has a <Form>
// and it will receive this component fields changes
const Cat = () => (
  <div className="Cat">
    <Input type="number" name="number_of_legs" />

    <label>
      {`Is registered by law to cats'registry?`}
      <Input type="checkbox" name="cat_registration" />
    </label>
  </div>
);

Fish.js

// same as Cat you don't need a <Form>,
const Fish = () => (
  <div className="Fish">
    <Input type="number" name="number_of_fins" />
  </div>
);

Bird.js

// same as Cat you don't need a <Form>,
// but if you want you can have a Nested Form,
// in this case the Animal <Form> will receive all the changes,
// and the Bird <Form> only the changes of "number_of_legs" and "number_of_wings"
const Bird = () => (
  <div className="Bird">
    <Form onFieldChange={({ name, value }) => {}}>
      <Input type="number" name="number_of_legs" />
      <Input type="number" name="number_of_wings" />
    </Form>
  </div>
);

Props

onFieldChange({name, value})

Triggered every time a field changes its value

  • you can use it to update your state.

onFieldFocus({name, value})

Triggered every time a field is focused

  • you can use for changing styles of focused input

onFieldBlur({name, value})

Triggered every time a field lose focused

  • you can use for removing styles of focuesd input

onFieldDidChanged({name, value})

Triggered every time a field has changed its value and user has finished editing it, for example when a <Select> changes value or an <Input type="text"> lose focus after editing

  • you can use it to call your backend automatically on form editing.

onSubmit({name, value})

Triggered every time a Button inside a from is clicked

values

A Key-Value object to automatically set the value of the fields, based on their "name" attributes.

binding

A React Component to bind state with, you can pass only the component like binding={this} or if you want to bind an internal key of state you can pass an array binding={[this, 'the_state_key_to_bind']}

stopPropagation

if set <Form stopPropagation> the forms that are upper in the hierarchy won't receive data from fields inside this Form.

Example

With binding set to this, every change in the Form will be written to the Component state.

import React from 'react';
import { render } from "react-dom";
import { Form, Input, Selext, Textarea, Button } from 'react-distributed-forms';

// You can set a variable and check it if you want to auto-save when user finished editing a field
const AUTO_SAVE_ON_CHANGE_ENABLED = true;

class UserInfoForm extends React.Component {

  state = {
    first_name: 'John',
    last_name: 'Doe'
  };

  /**
   * onFieldDidChanged
   * called from Form's fields to indicate user has finished editing the input
   */
  onFieldDidChanged({name, value}) {
    if (AUTO_SAVE_ON_CHANGE_ENABLED) {
      this.setState({
        [name]: value
      }, () => {
        // after state's updated, send new data to your API endpoint.
        ajaxPOST(YOUR_API_ENDPOINT, this.state);
      });
    }
  },

  /**
   * onSubmit
   * called from Form's fields when form has to be submitted
   */
  onSubmit({name, value}) {
    if (name === 'submit') {
      ajaxPOST(YOUR_API_ENDPOINT, this.state);
    }
  },

  render () {
    return (
      <Form
        binding={this}
        onFieldDidChanged={this.onFieldDidChanged}
        onSubmit={this.onSubmit}
      >
        <div>
          <label for="first_name">First Name:</label>
          <Input type="text" id="first_name" name="first_name" />
        </div>
        <div>
          <label for="last_name">Last Name:</label>
          <Input type="text" id="last_name" name="last_name" />
        </div>
        <Button name="submit">Save</Button>
      </Form>
    );
  }
}

render(<UserInfoForm />, document.querySelector("#root"));