Giter VIP home page Giter VIP logo

uninformed's Introduction

Uninformed

Nostalgically simple forms for React and Preact.

npm install uninformed

You’ll also need either React >= 16 or Preact >= 8.

Why?

Forms in Rails do two useful things by default:

  • Send data to the server without refreshing the page
  • Prevent accidental double-submissions

Uninformed is a tiny library that brings these defaults to the React/Preact ecosystem.

Getting Started

import { Form } from 'uninformed';
import React from 'react';

export const SignupForm = () => (
  <Form action="/api/signups">
    <input type="email" name="email" required />
    <input type="submit" value="Sign Up" />
  </Form>
)

That’s it! No onChange handlers, no render props, just a lightly-enhanced HTML form that disables itself on submit, sends data to a server via AJAX, and re-enables itself after the server responds.

Basic Props

action

string | any valid URI

The URI of the service that will process your form, e.g. /api/signups

method

string | any valid HTTP verb | defaults to POST

The HTTP method to use when sending the form data, e.g. POST, PATCH, etc

enctype / encType

string | defaults to application/x-www-form-urlencoded

The encoding of the Form. Like the standard HTML enctype attribute, you can set this prop to multipart/form-data to support file uploads. Unlike the HTML enctype attribute, you can also set this prop to application/json to send JSON. Note that React expects form elements to have a camelCase encType prop instead of enctype. Uninformed supports either style and converts to camelCase internally.

onSubmit

function(event, payload) | optional

Called when a form is submitted. Use onSubmit to perform client-side validation, trigger updates to your UI, etc. You can return false from this function to prevent your Form from submitting.

beforeSend

function(xhr) | optional

Manipulate your form's XMLHttpRequest instance before sending. Use this prop set auth headers, configure CORS, etc:

const SignupForm = () => (
  <Form
    action="/api/signups"
    beforeSend={xhr => {
      // include auth credentials
      xhr.setRequestHeader("Authorization", `Bearer ${USER_AUTH_TOKEN}`);
      // parse response as JSON automatically
      xhr.responseType = "json";
      // add a pogress meter?
      xhr.addEventListener("progress", this.props.onProgressUpdate);
    }}
  >
    <input type="email" name="email" required />
    <input type="submit" value="Sign Up" />
  </Form>
);

onSuccess

function(xhr) | optional

Handle a successful form response.

const AuthForm = props => (
  <Form
    action="/login"
    onSuccess={xhr => {
      const user = JSON.parse(xhr.responseText);
      props.onLogin(user);
    }}
  >
    <input type="email" name="email" required />
    <input type="password" name="password" required />
    <input type="submit" value="Log In" />
  </Form>
);

onError

function(xhr) | optional

Handle a failed form response.

const AuthForm = () => (
  <Form
    action="/login"
    onError={xhr => {
      const error = JSON.parse(xhr.responseText);
      alert(`Error ${xhr.status}: ${error.message}`);
    }}
  >
    <input type="email" name="email" required />
    <input type="password" name="password" required />
    <input type="submit" value="Log In" />
  </Form>
);

Advanced Props

serialize

function(HTMLFormElement)

Use a custom serializer. The built-in serializers for url-encoded and multipart encodings follow the qs/Rails standard for nested object support, but the built-in JSON serializer doesn't support nested objects. Here's how you could serialize nested JSON with help from form-serialize.

import { Form } from "uninformed";
import serialize from "form-serialize";

const SignupForm = () => (
  <Form
    action="/signup"
    serialize={formElement => {
      const data = serialize(formElement, { hash: true });
      // data looks like this:
      //  {
      //    user: {
      //      name: 'abc',
      //      email: '[email protected]',
      //      interests: ['Ethics', 'Food'],
      //    },
      //  }
      return JSON.stringify(data);
    }}
  >
    <input type="user[name]" name="text" required />
    <input type="user[email]" name="email" required />
    <select multiple name="interests[]">
      <option value="Ethics">Ethics</option>
      <option value="Food">Food</option>
    </select>
    <input type="submit" value="Sign Up" />
  </Form>
);

send

function(payload, formInstance) => promise

Use a custom function to send your form data, instead of the XMLHttpRequest Uninformed uses by default. This function must return a Promise. Here's an example that uses the Fetch API:

const SignupForm = props => (
  <Form
    action="/api/signups"
    enctype="application/json"
    send={(payload, formInstance) => {
      const { method, action } = formInstance.props;
      return fetch(action, {
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${props.authToken}`
        },
        method,
        body: payload
      }).then(res => res.json());
    }}
  >
    <input type="email" name="email" required />
    <input type="submit" value="Sign Up" />
  </Form>
);

Use In Preact

Uninformed is built as a library-agnostic factory function. To use it in Preact without a preact-compat, import the factory directly:

import { createForm } from 'uninformed/dist/factory';
import { h, Component } from 'preact';
const Form = createForm({ h, Component });

export default const SignupForm = () => (
  <Form action="/api/signups">
    <input type="email" name="email" required />
    <input type="submit" value="Sign Up" />
  </Form>
)

Browser Support

Uninformed supports modern browsers and IE11. If you use a custom send function, you will need to polyfill Promise support in IE.

Prior Art

None of these libraries handle submitting data or preventing double-submissions, but they do handle client-side validation.

Contributing

Bugs

Please open an issue on Github.

Pull Requests

PRs are welcome, and I'll do my best to review them promptly.

uninformed's People

Contributors

chrisfrank avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.