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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@marvinh/mobx-form-reactions

v5.0.0

Published

MobX form state classes

Downloads

18

Readme

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.