Nanoseconds Produce Minutes

    @marvinh/mobx-form-reactions
    TypeScript icon, indicating that this package has built-in type declarations

    5.0.0 • Public • Published

    MobX form reactions

    @marvinh/mobx-form-reactions is an advanced form library for mobx. It was written for complex form needs, such as support for nested fields, field dependencies, field dependencies across different forms and first class support for asynchronous validators.

    Installation

    npm install @marvinh/mobx-form-reactions
    # or
    yarn add @marvinh/mobx-form-reactions

    Usage

    There are 3 basic modesl which are the building blocks for any form:

    • Field - A simple input field
    • FormGroup - A group of fields stored as an object
    • FieldArray - Holds a list of fields/groups where the order is important or children can be dynamically added/removed.

    Additional classes:

    • BooleanField- Abstraction for toggles/checkboxes

    API

    // Each class implements this interface
    interface AbstractControl {
      /**
       * Incremented each time a field is changed. Useful for dirty-checking or
       * syncing requirements
       */
      revision: number;
      /**
       * Control is marked as being pristine. This is usually used to customize
       * the behaviour when errors should be shown the first time
       */
      initial: boolean;
      /** Marks control as being disabled */
      disabled: boolean;
      /** The current state of the field */
      status: "valid" | "pending" | "invalid";
      setDisabled(disabled: boolean): void;
      /** Reset the field */
      reset(): Promise<void>;
      /** Validates the field value and mutates the current instance */
      validate(): Promise<void>;
    }
    
    interface Field extends AbstractControl {
      /** The value of a field. `null` means empty */
      value: boolean | string | number | null;
      /** Note: setting a value doesn't trigger validation automatically */
      setValue(value: boolean | string | number | null): void;
    }
    
    interface FormGroup extends AbstractControl {
      /**
       * Get all child field values. Example:
       *
       * {
       *   name: "John Doe",
       *   age: 25,
       * }
       */
      value: Record<string, any>;
    }
    
    interface FieldArray extends AbstractControl {
      /**
       * Get all child field values. Example:
       *
       * [
       *   { name: "Jon Doe" },
       *   { name: "Peter" },
       * ]
       */
      value: any[];
    }

    Validators

    Each class can have it's own validators. These functions can be sync or async. They return either a string if the field is invalid or undefinedin case if valid.

    import { Validator, Field } from "@marvinh/mobx-form-reactions";
    
    // Create a validation functions
    const isHello = (field: Field) => field.value !== "hello" ? "hello" : undefined;
    
    const validator = new Validator({
      bailFirstError: true,
      // synchronous validators are run before async for performance reasons
      sync: [isHello]
      // async functions are automatically cancelled when something changed.
      // This means that race conditions can't happen
      async: [somethingAsync]
    })
    
    // Create a field and assign our validator
    const field = new Field({ validator });

    Examples

    Simple form:

    import {
      Field,
      FormGroup,
      Validator,
      required,
    } from "@marvinh/mobx-form-reactions";
    
    const nameValidator = new Validator({ sync: [required] });
    
    const name = new Field({ validator: nameValidator });
    const note = new Field();
    const form = new FormGroup({ name, note });
    
    note.value = "my user input";
    
    // Form is still marked as invalid, because name isn't set
    console.log(form.status); // invalid
    console.log(name.status); // invalid
    
    name.value = "John Doe";
    console.log(form.status); // valid

    Fields with a default value:

    import { Field, required } from "@marvinh/mobx-form-reactions";
    
    const nameValidator = new Validator({ sync: [required] });
    
    const name = new Field({ value: "John Doe", validator: nameValidator });
    console.log(name.value); // Logs: "John Doe"

    Examples

    FieldArrays (dynamic fields)

    When dealing with complex forms you'll usually come across a form where the inputs have to be added dynamically. Think of a form where you can add an abritary number of persons. The FieldArray class is made for this exact purpose.

    import { Field, FormGroup, FieldArray } from "@marvinh/mobx-form-reactions";
    
    const createPerson = () =>
      new FormGroup({
        name: new Field(),
        surname: new Field(),
      });
    
    const form = new FieldArray();
    
    const onBtnClick = form => form.push(createPerson());
    
    // Let's pretend that the user clicked on a button labeld "add person"
    onBtnClick(form);
    
    console.log(form.fields.length); // Logs: 2

    License

    MIT, see the license file.

    Keywords

    none

    Install

    npm i @marvinh/mobx-form-reactions

    DownloadsWeekly Downloads

    16

    Version

    5.0.0

    License

    MIT

    Unpacked Size

    209 kB

    Total Files

    51

    Last publish

    Collaborators

    • marvinhagemeister