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

ro-form

v2.1.4

Published

Minimalistic Form utility library for React

Downloads

36

Readme

ro-form

Build Status

ro-form is a minimalistic Form utility library for React that helps you build forms faster. It handles the data flow in forms and does not feature any UI. As examples below show, it is extremely simple to use. It can be used both with regular stateful React components and redux;

Install

yarn: yarn add ro-form

npm: npm install --save ro-form

Examples

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

class LoginScreen extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: {
        username: '',
        password: ''
      }
    };
  }

  changeData = newData => this.setState({ data: newData });

  submit = () => {
    const { data } = this.state;

    console.log('Perform login with data:', data);
  }

  render() {
    const { data } = this.state;

    return (
      <Form value={data} onChange={this.changeData} onSubmit={this.submit}>
        <div>
          Username:
          <FormControl 
            control={TextInput}
            path={'username'}
          />
        </div>

        <div>
          Password:
          <FormControl 
            control={TextInput}
            controlProps={{ type: 'password' }}
            path={'password'}
          />
        </div>

        <button 
          type={'submit'} 
          disabled={data.password.length === 0 && data.username.length === 0}
        >
          Login
        </button>
      </Form>
    );
  }
}

const TextInput = ({ onChange, type, value }) => (
  <input type={type || 'text'} onChange={e => onChange(e.target.value)} value={value}>
);

Want to keep your form state in Redux? No problem!

import React, { Component } from 'react';
import { Form, FormControl } from 'ro-form';
import { connect } from 'react-redux';

const ReduxLoginScreen = ({ formData, changeFormData, onSubmit }) => (
  <Form value={data} onChange={changeFormData} onSubmit={onSubmit}>
    <div>
      Username:
      <FormControl 
        control={TextInput}
        path={'username'}
      />
    </div>

    <div>
      Password:
      <FormControl 
        control={TextInput}
        controlProps={{ type: 'password' }}
        path={'password'}
      />
    </div>

    <button 
      type={'submit'} 
      disabled={data.password.length === 0 && data.username.length === 0}
    >
      Login
    </button>
  </Form>
);

const TextInput = ({ onChange, type, value }) => (
  <input type={type || 'text'} onChange={e => onChange(e.target.value)} value={value}>
);

const mapStateToProps = state => {
  formData: state.myFormData,
};
const mapDispatchToProps = dispatch => {
  changeFormData: (newFormData) => dispatch(changeMyFormDataAction(newFormData)),
  onSubmit: () => dispatch(performLoginAction()),
};
ReduxLoginScreen = connect(mapStateToProps, mapDispatchToProps)(ReduxLoginScreen);

API

ro-form is a really simple library that contains only two components: Form and FormControl.

Form

Form component's purpose is to bind your component's data to underlying FormControls.

Props:

  • Required: value(Object): Object that contains data that needs to be provided to underlying FormControls
  • Optional: onChange(newValue)(Function): Function that is called every time data in any of the FormControls changes. It receives one argument, which is the new value object.
  • Optional: onFieldChange(fieldName, newFieldValue)(Function): Function that is called every time data in any of the FormControls changes. The difference with onChange prop is that this one is called with just single field's new value.
  • Optional: onSubmit(Function): It is called once Form is submitted (eg. when user presses Return key on keyboard while one of form's inputs is focused). If you don't want to allow this behaviour, you do not have to provide this parameter.

FormControl

FormControl handles updates of parts of the value object provided to parent Form.

Props:

  • Required: control(Component): Any component that has value(Any) prop and onChange(Function) prop. Control's onChange should be passed one argument, which is the new value.
  • Optional: controlProps(Object): Any additional props that should be provided to control.

Besides control, it requires either:

  • path(String): Name of component's data part in the Form's value object. FormControl will then automatically provide value and onChange to your input control.

Or:

  • value(Any): Manually provide value to underlying input
  • onChange(newValue)(Function): Manually handle input data changes

These two examples are identical:

<Form value={data} onChange={this.changeData}>
  {/* This is the same */}
  <FormControl
    control={TextInput}
    path={'username'}
  />

  {/* as this */}
  <FormControl
    control={TextInput}
    value={data.username}
    onChange={newUsername => this.changeData({ data: { ...data, username: newUsername } })}
  />
</Form>

Any component that receives onChange and value props can be used as control in FormControl:

const TextInput = ({ onChange, type, value }) => (
  <input type={type || 'text'} onChange={e => onChange(e.target.value)} value={value}>
);

<FormControl
  control={TextInput}
  path={'some_field'}
/>

const BabyNamePicker = ({ onChange, value, names }) => (
  <ul>
    {names.map(name => (
      <li 
        key={name} 
        onClick={() => onChange(name)}
        className={value === name ? 'active' : 'inactive'}
      >
        {name}
      </li>
    ))}
  </ul>
);

<FormControl
  control={BabyNamePicker}
  controlProps={{ names: ['Edwin', 'Stephanie', 'Angela', 'Robert'] }}
  path={'name'}
/>