0.0.27 • Published 1 year ago

@maxima/a-form v0.0.27

Weekly downloads
14
License
GPL-3.0-only
Repository
-
Last release
1 year ago

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

0.0.26

1 year ago

0.0.27

1 year ago

0.0.25

2 years ago

0.0.24

3 years ago

0.0.23

3 years ago

0.0.22

3 years ago

0.0.21

3 years ago

0.0.20

3 years ago

0.0.19

3 years ago

0.0.18

3 years ago

0.0.17

4 years ago

0.0.16

4 years ago

0.0.15

4 years ago

0.0.14

4 years ago

0.0.13

4 years ago

0.0.12

4 years ago

0.0.10

4 years ago

0.0.9

4 years ago

0.0.8

4 years ago

0.0.7

5 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago