# Mobx React Form Validation

> Validation for mobx-react-form — DVR, VJF, SVK, YUP, JOI, ZOD plugins, async validation, cross-validation, related fields, validation hooks.

- **Type:** Skill
- **Install:** `agentstack add skill-foxhound87-skills-mobx-react-form-validation`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [foxhound87](https://agentstack.voostack.com/s/foxhound87)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [foxhound87](https://github.com/foxhound87)
- **Source:** https://github.com/foxhound87/skills/tree/main/mobx-react-form-validation

## Install

```sh
agentstack add skill-foxhound87-skills-mobx-react-form-validation
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Skill: mobx-react-form-validation

## Mission

Guide the user through setting up and using **validation plugins** in mobx-react-form.

Use this skill when the user needs to:
- Set up a validation plugin (DVR, VJF, SVK, YUP, JOI, ZOD)
- Define validation rules/functions
- Handle async validation
- Implement cross-field validation (related fields)
- Use validation hooks (onSuccess, onError)
- Configure validation options (timing, debounce, strictness)

## Available Validation Plugins

| Driver | Package | Description |
|--------|---------|-------------|
| **DVR** | `validatorjs` | Declarative Validation Rules (string rules) |
| **VJF** | `validator` (optional) | Vanilla JavaScript Functions |
| **SVK** | `ajv` | JSON Schema Validation Keywords |
| **YUP** | `yup` | Object Schema Validator |
| **JOI** | `joi` | Object Schema Validator |
| **ZOD** | `zod` | TypeScript-first schema validation |

You can mix multiple plugins on the same form.

## DVR — Declarative Validation Rules

### Setup

```bash
npm install validatorjs
```

```javascript
import dvr from 'mobx-react-form/lib/validators/DVR';
import validatorjs from 'validatorjs';

const plugins = {
  dvr: dvr({ package: validatorjs }),
};
```

### Field Rules

```javascript
const fields = {
  email:    { rules: 'required|email' },
  password: { rules: 'required|string|between:5,25' },
  age:      { rules: 'required|numeric|between:18,99' },
  website:  { rules: 'url' },
};
```

Rule format: `'rule1|rule2:param1,param2'`

### Extending DVR

```javascript
const plugins = {
  dvr: dvr({
    package: validatorjs,
    extend: ({ validator }) => {
      validator.register('uppercase', (value) => value === value.toUpperCase());
    },
  }),
};
```

### Async DVR

```javascript
const plugins = {
  dvr: dvr({
    package: validatorjs,
    async: true,
  }),
};
```

Then define async rules:

```javascript
const rules = {
  username: 'required|asyncCheckUsername',
};
```

And register async validators:

```javascript
const plugins = {
  dvr: dvr({
    package: validatorjs,
    extend: ({ validator }) => {
      validator.registerAsync('asyncCheckUsername', (value, _, done) => {
        setTimeout(() => done(value === 'admin' ? 'Username taken' : undefined), 1000);
      });
    },
  }),
};
```

### Field-level async validation

```javascript
const fields = {
  email: {
    rules: 'required|email',
    hooks: {
      async onChange(field) {
        if (!field.isValid) return;
        const res = await fetch(`/api/check-email?email=${field.value}`);
        const data = await res.json();
        if (!data.available) {
          field.invalidate('Email already registered');
        }
      },
    },
  },
};
```

## VJF — Vanilla JavaScript Functions

### Setup

```bash
npm install validator   # optional
```

```javascript
import vjf from 'mobx-react-form/lib/validators/VJF';

const plugins = {
  vjf: vjf(),
};
```

### Field Validators

```javascript
import isEmail from 'validator/lib/isEmail';

const validators = {
  email: isEmail,
  password: [(val) => val.length >= 6, 'Password must be at least 6 characters'],
  age: [
    (val) => !isNaN(val) && Number(val) >= 18,
    'Must be at least 18 years old',
  ],
};
```

Validator format: `function` or `[function, errorMessage]` or `[function1, function2, errorMessage]`.

### Extending VJF

```javascript
const plugins = {
  vjf: vjf({
    extend: ({ validatorjs, validator }) => {
      // Add custom validation functions
    },
  }),
};
```

### Async VJF

Return a Promise from the validator function:

```javascript
const validators = {
  username: [
    async (value) => {
      const res = await fetch(`/api/check-username?value=${value}`);
      return res.json().then(data => data.available);
    },
    'Username is already taken',
  ],
};
```

## SVK — Schema Validation Keywords

### Setup

```bash
npm install ajv
```

```javascript
import svk from 'mobx-react-form/lib/validators/SVK';
import Ajv from 'ajv';

const plugins = {
  svk: svk({
    package: Ajv,
    config: {
      schema: {
        type: 'object',
        properties: {
          email:    { type: 'string', format: 'email' },
          password: { type: 'string', minLength: 6 },
          age:      { type: 'number', minimum: 18 },
        },
        required: ['email', 'password'],
      },
    },
  }),
};
```

Fields are auto-created from the JSON Schema properties when no explicit fields are defined.

### Extending SVK

```javascript
const plugins = {
  svk: svk({
    package: Ajv,
    config: {
      schema: { ... },
      extend: (ajv) => {
        ajv.addKeyword('myKeyword', { validate: (schema, data) => data.length > 0 });
      },
    },
  }),
};
```

### Async SVK

```javascript
const plugins = {
  svk: svk({
    package: Ajv,
    config: {
      schema: { ... },
      async: true,
      extend: (ajv) => {
        ajv.addKeyword('asyncCheck', {
          async: true,
          validate: (schema, data) => fetch(`/api/check?val=${data}`).then(r => r.json()),
        });
      },
    },
  }),
};
```

## YUP — Object Schema Validator

### Setup

```bash
npm install yup
```

```javascript
import yupValidator from 'mobx-react-form/lib/validators/YUP';
import * as yup from 'yup';

const schema = yup.object({
  email: yup.string().email().required(),
  password: yup.string().min(6).required(),
  age: yup.number().min(18),
});

const plugins = {
  yup: yupValidator({ package: yup, config: { schema } }),
};
```

## JOI — Object Schema Validator

### Setup

```bash
npm install joi
```

```javascript
import joiValidator from 'mobx-react-form/lib/validators/JOI';
import Joi from 'joi';

const schema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(6).required(),
});

const plugins = {
  joi: joiValidator({ package: Joi, config: { schema } }),
};
```

## ZOD — TypeScript-first schema validation

### Setup

```bash
npm install zod
```

```javascript
import zodValidator from 'mobx-react-form/lib/validators/ZOD';
import { z } from 'zod';

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(6),
});

const plugins = {
  zod: zodValidator({ package: z, config: { schema } }),
};
```

## Validation Hooks

```javascript
const hooks = {
  onSuccess(form) {
    alert('Form is valid!');
    console.log('Values:', form.values());
    // Send to API...
  },
  onError(form) {
    alert('Form has errors!');
    console.log('Errors:', form.errors());
  },
};
```

Hooks can return a Promise for async submission:

```javascript
const hooks = {
  async onSuccess(form) {
    await fetch('/api/submit', {
      method: 'POST',
      body: JSON.stringify(form.values()),
    });
  },
};
```

## Validation Options (Form & Field level)

| Option | Default | Description |
|--------|---------|-------------|
| `validateOnInit` | true | Validate on form initialization |
| `validateOnSubmit` | true | Validate on submit |
| `validateOnBlur` | true | Validate on field blur |
| `validateOnChange` | false | Validate on every keystroke |
| `validateOnChangeAfterInitialBlur` | false | Validate on change after first blur |
| `validateOnChangeAfterSubmit` | false | Validate on change after first submit |
| `validateOnClear` | false | Validate on clear |
| `validateOnReset` | true | Validate on reset |
| `showErrorsOnInit` | false | Show errors on init |
| `showErrorsOnSubmit` | true | Show errors on submit |
| `showErrorsOnBlur` | true | Show errors on blur |
| `showErrorsOnChange` | true | Show errors on change |
| `stopValidationOnError` | false | Stop validating after first driver error |
| `validationDebounceWait` | 250 | Debounce wait in ms |
| `validationPluginsOrder` | undefined | Array: `['vjf', 'dvr', 'svk', 'yup', 'zod', 'joi']` |
| `validateDisabledFields` | false | Validate disabled fields |
| `validateDeletedFields` | false | Validate soft-deleted fields |
| `validatePristineFields` | true | Validate pristine (unchanged) fields |
| `validateTrimmedValue` | false | Trim value before validation |
| `resetValidationBeforeValidate` | true | Reset validation state before re-validating |

## Cross-Field Validation (related fields)

Use the `related` property to validate other fields when a field changes:

```javascript
const fields = {
  password: {
    label: 'Password',
    rules: 'required|min:6',
    related: ['passwordConfirm'], // re-validate confirm when password changes
  },
  passwordConfirm: {
    label: 'Confirm Password',
    rules: 'required|same:password',
  },
};
```

Or validate related fields programmatically:

```javascript
form.$('password').validate({ related: true, showErrors: true });
```

## Field-Level Validation Hooks

```javascript
const fields = {
  email: {
    hooks: {
      onInit(field) { /* after field creation */ },
      onChange(field) { /* after value change */ },
      onFocus(field) { /* after focus */ },
      onBlur(field) { /* after blur */ },
    },
  },
};
```

## Manual Validation

```javascript
// Validate entire form
form.validate({ showErrors: true })
  .then(({ isValid }) => { /* ... */ });

// Validate single field
form.$('email').validate({ showErrors: true })
  .then(({ isValid }) => { /* ... */ });

// Validate with related fields
form.validate({ showErrors: true, related: true });

// Manual submit with validation overrides
form.submit({}, {
  validate: true,
  execOnSubmitHook: false,
  execValidationHooks: true,
});
```

## Invalidate Programmatically

```javascript
// Mark field as invalid
form.$('email').invalidate('Custom error message');

// Mark form as invalid
form.invalidate('Form-level error');

// Async invalidation
field.invalidate('Already taken', true, true); // (message, deep, async)
```

## Validation Plugin Order

When using multiple plugins, control execution order:

```javascript
const options = {
  validationPluginsOrder: ['vjf', 'dvr'], // VJF runs first, then DVR
  stopValidationOnError: true,            // stop after first failure
};
```

## Key Takeaways

1. **6 plugins available**: DVR, VJF, SVK, YUP, JOI, ZOD — mix and match.
2. **Related fields**: Use `related: ['fieldPath']` for cross-field validation.
3. **Async validation**: Return Promises from validators or use async hooks.
4. **Validation hooks**: `onSuccess` / `onError` trigger after submit/validate.
5. **Debounced**: Validation is debounced at 250ms by default.
6. **Per-field options**: Each field can override form-level validation options.
7. **Programmatic invalidation**: `field.invalidate(msg)` for custom errors.

## Related Skills

- [mobx-react-form-api](../mobx-react-form-api/SKILL.md) — Core API prerequisite
- [mobx-react-form-flat](../mobx-react-form-flat/SKILL.md) — Field definitions with rules
- [mobx-react-form-nested](../mobx-react-form-nested/SKILL.md) — Validation with nested fields
- [mobx-react-form-events](../mobx-react-form-events/SKILL.md) — Event hooks
- [mobx-react-form-options](../mobx-react-form-options/SKILL.md) — Validation timing options

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [foxhound87](https://github.com/foxhound87)
- **Source:** [foxhound87/skills](https://github.com/foxhound87/skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-foxhound87-skills-mobx-react-form-validation
- Seller: https://agentstack.voostack.com/s/foxhound87
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
