Home

Awesome

MobX FormStore

FormStore is part of a collection of loosely-coupled components for managing, rendering and validating forms in MobX-based apps.

Detailed Documentation:

https://alexhisen.gitbooks.io/mobx-forms/

FormStore Overview

Instances of FormStore (models) store the data entered by the user into form fields and provide observables for managing validation error messages. They also track changes and provide facilities for (auto-)saving the (changed) data.

Features

Breaking change in Version 2.0

Previously, server.create() was called (instead of server.set()) only when the property defined as the idProperty in store.data was falsy. This worked well if the idProperty was only returned by the server and was not user-enterable. Now whether server.create() is called is driven by a new store.status.mustCreate property which is true only when the idProperty has not yet been returned by the server / saved even if it already has a value in store.data. Note that MobxSchemaForm v.1.14+ supports a readOnlyCondition property that can be set to "!model.status.mustCreate" to allow an id property to be entered but not modified.

Breaking changes in Version 3.0

Requirements

FormStore only requires MobX 2.2+, 3.x, 4.x or 5.x. MobX strict mode is currently not supported. FormStore does not implement the actual server requests, it only calls methods that you provide with the data to be sent to the server.

Installation

npm install --save mobx-form-store

Minimal Usage Example

myStore.js (a Singleton):

import FormStore from 'mobx-form-store';

const model = new FormStore({
  server: {
    // Example uses ES5 with https://github.com/github/fetch API and Promises
    get: function() {
      return fetch('myServerRefreshUrl').then(function(result) { return result.json() });
    },

    // Example uses ES6, fetch and async await
    set: async (info) => {
      const result = await fetch('myServerSaveUrl', {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(info),
      });
      return await result.json() || {}; // MUST return an object
    }
  },
});

export default model;

IMPORTANT: Your server.get method MUST return an object with ALL properties that need to be rendered in the form. If the model does not yet exist on the server, each property should have a null value but it must exist in the object or it cannot be observed with MobX.

Example of using FormStore in a React form

myForm.jsx (this is without MobxSchemaForm (with it there is even less code)).

import React from 'react';
import { observer } from 'mobx-react';
import model from './myStore.js'

@observer class MyForm extends React.Component {
  componentDidMount() {
    model.refresh();
  }

  onChange = (e) => {
    model.data[e.target.name] = e.target.value;
    model.dataErrors[e.target.name] = myCustomValidationPassed ? null : "error message";
  }

  onSaveClick = () => {
    if (!model.status.canSave || !model.status.hasChanges) return;
    if (myCustomValidationPassed) model.save();
  }

  render() {
    return (
      {/* ... more fields / labels ... */}

      <label className={model.dataErrors.myProperty ? 'error' : ''}>My Property</label>
      <input
        type="text"
        name="myProperty"
        className={model.dataErrors.myProperty ? 'error' : ''}
        value={model.data.myProperty || ''}
        readonly={model.status.isReadOnly}
        onChange={this.onChange}
      />
      <p>{model.dataErrors.myProperty}</p>

      <button
        className={(!model.status.canSave || !model.status.hasChanges) ? 'gray' : ''}
        onClick={this.onSaveClick}
      >
        Save
      </button>
    );
  }
}