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

@maxima/a-form

v0.0.27

Published

Form library to use in React form components based on fields schema and react hooks.

Downloads

121

Readme

AForm

Build statically-typed forms using React and TypeScript based on form schemas.

How to install

yarn install a-form

How to use

For creating a form with a-form follow steps described below.

Define form schema

import { Input, InputArray, InputGroup } from 'a-form';

const aSchema = new InputGroup({
  name: new Input<string>(),                       // <- string input
  age: new Input<number>(),                        // <- number input
  address: new InputGroup({                        // <- nested inputs
    city: new Input<string>(),
    zip: new Input<number>()
  }),
  phoneNumbers: new InputArray(new Input<string>()), // <- array of string inputs
  ids: new InputArray(new Input<number>()),          // <- array of number inputs
  guests: new InputArray(                            // <- array of nested inputs
    new InputGroup({
      name: new Input<string>(),
      age: new Input<number>()
    })
  )
});

You can also use helper functions for denining form schemas:

import { input, inputArray, inputGroup } from 'a-form';

const aSchema = inputGroup({
  name: input<string>(),                       // <- string input
  age: input<number>(),                        // <- number input
  address: inputGroup({                        // <- nested inputs
    city: input<string>(),
    zip: input<number>()
  }),
  phoneNumbers: inputArray(input<string>()),    // <- array of string inputs
  ids: inputArray(input<number>()),             // <- array of number inputs
  guests: inputArray(                           // <- array of nested inputs
    inputGroup({
      name: input<string>(),
      age: input<number>()
    })
  )
});

Using useForm React hook

import { useForm } from 'a-form';

const AForm: React.SFC<{}> = (props) => {
  const validate = (values: typeof initialValues) => ({}); // form always valid
  const submit = (values: typeof initialValues) => console.log(values);

  const form = useForm({ aSchema, initialValues, validate, submit });

  // use form to access properties for rendering form
  return (
    <form onSubmit={form.handleSubmit}>
      { // ... }
    </form>
  )
};

Using Form component to render your form with render props

const AForm: React.SFC<{}> = (props) => {
  const validate = (values: typeof initialValues) => ({}); // form always valid
  const submit = (values: typeof initialValues) => console.log(values);

  return (
    <Form schema={aSchema} validate={validate} submit={submit} initialValues={}>
      {
        (formProps) =>
          (
            <form onSubmit={formProps.handleSubmit}>
              <div>
                <label htmlFor="input-name">Name</label>
                <input id="input-name" {...formProps.name} />

                {
                  formProps.name.touched && formProps.name.invalid &&
                  <span className="error">{formProps.name.error}</span>
                }
              </div>

              <div>
                <label htmlFor="input-age">Age</label>
                <input id="input-age" {...formProps.age} />

                {
                  formProps.age.touched && formProps.age.invalid &&
                  <span className="error">{formProps.age.error}</span>
                }
              </div>

              <div>
                <label htmlFor="input-address-city">City</label>
                <input id="input-address-city" {...formProps.address.city} />
              </div>

              <div>
                <label htmlFor="input-address-zip">Postal code</label>
                <input id="input-address-zip" {...formProps.address.zip} />
              </div>

              {
                formProps.phoneNumbers.items.map((phoneNumberProps, index) => {
                  <div>
                    <label htmlFor={`input-phone-number-${index}`}>Phone {index}</label>
                    <input id={`input-phone-number-${index}`} {...phoneNumberProps} />
                    <button type="button" onClick={() => formProps.phoneNumbers.remove(index)}>&times</button>
                  </div>
                })
              }
              <button type="button" onClick={() => formProps.phoneNumbers.push('')}>Add phone number</button>

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

API

Form props / useForm hook config

  • schema: InputGroup - form schema, which defines available form inputs, for which later field-level props will be available
  • validate(values) - validation function which returns an object with validation errors for each field.
  • submit(values) - function which handles data submission
  • initialValues - values of the form, with which the form will be initialized

Form state

  • values: Values<T> - form values
  • errors: Errors<T> - per-input validation errors
  • active: Flags<T> - per-input active flags, indicating whether input is focused or not
  • touched: Flags<T>- per-input touched flags, indicating whether input is touched or not
  • invalid: boolean - indicates that form has validation errors
  • validating: boolean - indicates that form is currently running validations
  • submitting: boolean - indicates that form is currently submitting
  • submitted: boolean - indicates that the form was submitted
  • submitResult: boolean | undefined - indicates whether the form submission was successfull or failed
  • error: string | undefined - global form-level error
  • dirty: boolean - global dirty flag, indicates that current form values are not deeply equal to initialValues

Form handlers

  • handleSubmit(event: React.FormEvent): void; - form submit handler, which internally marks all fields as touched, validates and submits form values
  • reset(): void; - reset form values to form's initialValues
  • setValues(values: Values<T>): void; - set form values
  • setErrors(errors: Errors<T>): void; - set form errors

Input props

  • value: T - field value
  • name: string - field name
  • error: string | undefined - validation error
  • active: boolean - active flag (indicates that field is currently focused)
  • touched: boolean - touched flag (indicates that field is touched)
  • dirty: boolean - field value was changed and is different from value, specified in initialValues prop of the form component
  • invalid: boolean - field has validation errors
  • onBlur(event: React.FocusEvent<HTMLElement>): void - blur event handler
  • onChange(eventOrValue: React.ChangeEvent<HTMLInputElement> | T): void - change event handler
  • onFocus(event: React.FocusEvent<HTMLElement>): void - focus event handler

InputArray props

  • items: array of field props for each value in the list
  • touched: boolean
  • pop(): void - remove last value from the list
  • push(value: T): void - add value specified as agrument to the end of the list
  • shift(): void - remove first value from the list
  • unshift(value: T): void - add value specified as agrument to the beginning of the list
  • insert(index: number, value: T): void - insert value specified as agrument at a given index into the list
  • replace(index: number, value: T): void - replace value by existing index with a new value
  • remove(index: number): void - remove value from the list at index specified as an argument
  • move(from: number, to: number): void - move value from one index to another
  • swap(indexA: number, indexB: number): void - swap positions of two values in the list, specified by arguments

InputGroup props

  • touched: boolean
  • change(values: T) - change form group values

For each of the input defined in particular input group, it's props are available by the name of the input.

Example:

const groupSchema = new InputGroup({
  name: new Input<string>(),
  tags: new InputArray(Input<string>)
});

// ...

// usage later in form component
formProps.name // <= Input props for name input
formProps.tags // <= InputArray props for tags input

Licence

GPLv3

Copyright hck, 2019