Forms library for React+MobX application. Under the hood it uses efficient MobX observable mechanizm, that allows tracking changes in form fields and rerender only things that have changed. This makes developer a feeling of working with 2-way databinding and reduces much boilerplate code needed to handle input events in 1-way data flow environment.
The library is inspired by Angular Reactive Forms and Redux Form. It has simalar syntax to Redux Form, because of concept that are neutural to React world. So if you previously had experience with it, it will be easy for you to start using reactive-mobx-form
. But still one of the goals of this library is to be simple in usage for everyone.
Examples can be found here. Documentation is under development, but you already can see some code and usage
Library is on its initial development stage, is unstable and may contain bugs. Most of all API will change.
If considering a software development as next steps:
- Make it work <-- we are here
- Make it right
- Make it fast
Starting of version 0.2.10
library contains all basic functionallity for handling simple and complex(nested) forms. For now I will focus on its documentation and differnt improvements(performace and code organization). API should left stable for some time. If you are using a library and require any help, please create an issue.
Working with forms was always a pain in web development. This library is an attempt to solve it for MobX and React users.
Goals:
- Minimal configuration
- Easy to learn and start with
- Preferable over own solutions(I hope it to be)
Its now possible:
- Render simple one level forms
- Validate fields, see validatorjs docs
- Render multi-level fields with
ControlSection
Component - Render filed, that contains array of data. Both singe item array, or array of objects.
- Submit a form
reactive-mobx-forms depends directly on:
- validatorjs library for validation. It is small, effective and scalable.
- prop-types
reactive-mobx-forms peer dependencies are:
- There is a problem when using preact. For some reason, if inside of componentWillMount any state change is executed(form.refisterField => changes form.values => changes form.validation => changes form.errors, that are observed by Control Component), all lifecicle methods of Component are executed twice. Which then tries to register filed twice. Possible ways of solving can be:
- Register field in componentDidMount
- Get rid of componentWillMount and do stuff in constructor This requires more investigation....
npm install reactive-mobx-form --save // you can omit --save flag if using npm > 5
Create and expose to all your application a formStore
via Provider from mobx-react
import { Provider } from 'mobx-react';
import { FormStore } from 'reactive-mobx-form';
const formStore = new FormStore();
render(
<Provider appStore={appStore} formStore={formStore}> //appStore - is any other store in your application
<App />
</Provider>,
document.getElementById('root')
);
Create a form
import {reactivMobxForm, Control} from 'reactive-mobx-form';
class ContactForm extends Component {
render() {
const { submit } = this.props;
return (
<form onSubmit={submit}>
<div>
<label htmlFor="name">Name</label>
<Control name="name" component="input" type="text" />
</div>
<div>
<label htmlFor="age">Age</label>
<Control name="age" component="input" type="number"/>
</div>
<button type="submit">Submit</button>
</form>
);
}
}
const ContactFormReactive = reactiveMobxForm('contacts' [, formDefinition])(ContactForm); // 2nd parameter (formDefinition) is optional.
export default ContactFormReactive;
Detailed explanation of formDefinition object
Use your form and enjoy
import ContactForm from './ContactForm';
export default Page extends Component {
handleSubmit(form) {
console.log(form)
}
render() {
<div>
<ContactForm onSubmit={this.handleSubmit.bind(this)} /> // schema={{fieldName: [initialValue, rules]}} optional parameter
</div>
}
}
When you call props.submit
function that is passed to your form - submission is started. Inside it calls your submit
function (those you have passed into onSubmit
parameter) will be called inside of promise(so it may be async).
props.submitis also async function, that returns a promise, so you can add any required callbacks in
.thenand
.catchmethods. If your
submitfunction returns a
resolved Promise-
result will be passed to props.submit.then
method.
If your submit
function returns rejectedPromise
than form.submitionError
flag is raised and error will be passed to props.submit.catch
method.
By default error messages are in English. But you can change them. reactive-mobx-form
provides you with interface for this. Under the hood it uses Validatorjs Language Support
In the index.js
or other entry point of your app.
import { configureValidator } from 'reactive-mobx-form';
configureValidator({
language: 'ru'
});
You can use MobX autorun funtion in order to execute this code each time app language change. Be carefull as changing the language happens on Validator
class and effects all forms, even created before language switch.
When display error messages, you may want to modify how field name is displayed in error message. For example if field name is 'user.name' and this field is required. You'd like to see it in error message like 'The user name field is required.'. This may be done via setting custom attribute names(locally) or attribute names formatter function(globally). Same as language support, the functionallity relays on Validatorjs Custom attribute names.
In the index.js
or other entry point of your app.
import { configureValidator } from 'reactive-mobx-form';
configureValidator({
setAttributeFormatter: (attribute) => attribute.replace(/\./g, ' ')
});
setAttributeFormatter
property should be a function, that accepts 1 parmenter field name, processes and returns it. In this example if we had a field name like 'user.name' it will be 'user name' in error message.
Here we will benefit from other optional parameter to reactiveMobxForm
creation function called validator
.In place where you initialize form
const ContactFormReactive = reactiveMobxForm('contacts', {
validator: {
attributeNames: { // this option is available per form only
'users[0]' : 'First User'
}
// local setAttributeFormatter is not implemented yet
}
})(ContactForm)
attributeNames
is an object that maps field name to attribute in error message. So if we had a field name like 'user.[0]' it will be 'First user' in error message.
With custom error messages it is possible to completely modify error message for some rule or combination of rule and field
const ContactFormReactive = reactiveMobxForm('contacts', {
validator: {
errorMessages: {
'required': 'You forgot to give a :attribute' // this format will be userd for all required fields
'required.email': 'Without an :attribute we can\'t reach you!' // format for required email field
}
}
})(ContactForm)
##FAQ