Use the second argument (boolean) if you want to check for nested fields too.
+
.check('isValid',true);
+
+
+
Programmatically Focus a Field
+
To focus a field:
+
field.focus();
+
+
To use focus() you have to use bind() on the input. A React ref will be attached to the field to focus it.
+
<input {...field.bind())}/>
+
+
Otherwise you will have to set the ref manually:
+
<input ref={(ref)=> field.set('ref', ref)}/>
+
+
+
Get Fields Properties
+
+
Return an object with fields key:val pairs (with nested fields).
+
+
This will get all fields prop (with nested fields as fields objects):
+
.get();
+
+
or filtering by a prop (with nested fields as collections):
+
.get('label');
+
+
You can get these editable props: value, label, placeholder, initial, default, disabled, related, bindings, type, disabled, options, extra, autoFocus, inputMode.
+
Or these computed props: hasError, isValid, isDirty, isPristine, isDefault, isEmpty, focused, touched, changed, error, and the validation props as well (rules and validators).
+
If you want to get nested fields as fields objects instead of collections pass the prop as array:
+
.get(['label']);
+
+
or if you need to filter multiple props:
+
.get(['value','label']);
+
+
+
Set Fields Properties
+
The set() method is intended to be used to change the properties of existent/selected fields.
+
+
It takes in input the prop name string and an object with fields key:val pairs.
+
+
If you need to recreate the fields tree (for example add/del fields array) and provide new values, consider to use the update() method instead.
+
You can pass the editable props: value, label, placeholder, initial, default, type,disabled, related, bindings, hooks, handlers, observers, interceptors, extra, autoFocus, inputMode as well the validation props (rules and validators).
You can add or remove normal Fields & Nested Fields or Array of Fields as well.
+
Add fields or nested fields:
+
.$('hobbies').add();
+
+
+
If you have specified an Array of Fields ([]) into the field struct you can call add() without input arguments to create a new empty field with its incremental array index as key/name.
The Template is useful if you need to change how the properties are obtained, for example we want to reimplement an Event Handler one time for all the same kind of fields or we want to swap their properties priorities and use those passed to the bind() method as fallbacks.
+
In the Form Class implement a bindings() methods which will return an object with our Template function.
+
In the following example some props passed to the bind() method will get priority over the fields ones. The new bindings will enable validation on onBlur handler (it is reimplemented by providing a custom function), and ErrorText & ErrorStyle are henanched to display a custom loading indicator for async calls.
When passing properties to the bind() method, the field properties which are defined on form initialization will be treated as fallbacks (until you implement a new Template).
+
+
IMPORTANT!
+
The props passed to the bind() method will not mutate the package's store but only your component.
+
Do this only for handling edge cases, as it's not the default behavior to handle field props, define fields normally instead.
+
+
+
+
BUILT-IN default Template & Rewriter
+
Here you can see the structure of the default Template & Rewriter.
+
The default rewriter define which component properties has assigned to the field property key
REWRITER: an object which assigns the component props names to the fields props names.
+
TEMPLATE: a function which assigns the fields props values to the component props names.
+
+
Use the Rewrite Mode if you need a simple a synthetic way to map custom components properties and you are ok using the defaults props priorities and fallbacks.
+
Use the Template Mode if you need to redefine your properties priorities/fallbacks, customize the Event Handlers or reimplement the bindings from scratch.
+
More info on how to implement custom rewriters/templates can be found in the Custom Bindings section, otherwise if you are using default html inputs you don't need them, see the Default Bindings section.
import MobxReactFormDevTools from'mobx-react-form-devtools';
+
+// register forms
+MobxReactFormDevTools.register({
+ loginForm,
+ registerForm,
+ supportForm,
+});
+
+// select form to show into the devtools
+MobxReactFormDevTools.select('registerForm');
+
+// open the devtools (closed by default)
+MobxReactFormDevTools.open(true);
+
+// render the component
+<MobxReactFormDevTools.UI/>
+
The onDrop(e) Event Handler will retrive the files into the files Field prop and exeute the onDrop Hook function.
+
Define the field type property as file and then use bind() on your input:
+
<inputmultiple=true{...field.bind()}/>
+
+
Otherwise, (without defining the type prop) delegate the input onChange Handler with the onDrop(e) Handler on the bind() method (or create a custom bindings).
These methods are called when the form validation is done.
+
+
They can return promises to wait on submit.
+
+
Define an hooks object with onSuccess(form) or onError(form) Validation Hooks and pass them to the Second Argument of the Form Constructor:
+
const hooks ={
+ onSuccess(form){
+ alert('Form is valid! Send the request here.');
+ // get field values
+ console.log('Form Values!', form.values());
+ // can return a promise here!
+ },
+ onError(form){
+ // get all form errors
+ console.log('All form errors', form.errors());
+ // invalidate the form with a custom error message
+ form.invalidate('This is a generic error message!');
+ // can return a promise here!
+ },
+};
+
+newForm({...},{ hooks });<---
+
These methods are called when the form validation is done.
+
+
They can return promises to wait on submit.
+
+
Extend the Form or Field class with an hooks() method which will return the onSuccess(form) or onError(form) Validation Hooks.
+
import MobxReactForm from'mobx-react-form';
+
+classMyFormextendsMobxReactForm{
+
+ hooks(){
+ return{
+ onSuccess(){
+ alert('Form is valid! Send the request here.');
+ // get field values
+ console.log('Form Values!',this.values());
+ // can return a promise here!
+ },
+ onError(){
+ // get all form errors
+ console.log('All form errors',this.errors());
+ // invalidate the form with a custom error message
+ this.invalidate('This is a generic error message!');
+ // can return a promise here!
+ },
+ };
+ }
+}
+
These methods are called when the form validation is done.
+
+
They can return promises to wait on submit.
+
+
Define an object with onSuccess(form) or onError(form) Validation Hooks.
+
const hooks ={
+ onSuccess(form){
+ alert('Form is valid! Send the request here.');
+ // get field values
+ console.log('Form Values!', form.values());
+ },
+ onError(form){
+ // get all form errors
+ console.log('All form errors', form.errors());
+ // invalidate the form with a custom error message
+ form.invalidate('This is a generic error message!');
+ },
+};
+
+
+
They takes the form instance as parameter in input.
+
+
Then pass the Validation Hooks as first argument to the submit({ ... }) Action:
Forms composer is an useful helper that can be used to manage a group of related Froms instances.
+For example we have multiple forms and each of them is a part of a multi-step application.
+With the composer you can execute some actions on all forms at same time.
Before version < 6.3, to implement computed props you had to extend a Form or Field class.
+Form the version 6.3 and above, computed props can be defined providing functions in Fields Definitions.
+
+
The computed function will get an object with form and field instances in input.
+
+
Avaliable Computed Field Props
+
computed: special field prop to handle computed values (defined as function).
+
or functions can be defined on: value, label, placeholder, disabled, rules, related, deleted, validatedWith, validators, bindings, extra, options, autoFocus, inputMode.
+
How to implement Computed Props
+
An assumption has to be made before using computed props: the function gets the form instance that can be used to acess other form fields before they are created. For this reason, to access a field before its creation, we need to set strictSelect: false as form option, otherwise an error will be thrown when trying to access an undefined field.
+
const fields =[
+ 'myComputedField',// will be computed
+ 'mySwitch',// assume it is a boolean
+];
+
+const types ={
+ mySwitch:'checkbox',
+};
+
+const values ={
+ // we define the value of the field as a function which can return a computed value
+ myComputedField:({ form, field })=> form.$('mySwitch')?.value ?'a':'b';
+};
+
+const form =newForm({ fields, types, values,...},{
+ options:{ strictSelect:false}
+});
+
+
+
Example using Separated Mode Definition. Unified Mode also supported.
+
+
Handle Computed Nested Array of fields value
+
If we want to handle computed props for nested array of fields we can use the special computed field prop which accepts a full field path and will be applied when using the add() action.
If you need to observe or intercept on the fly the Field Props or the Fields Map you can use the observe() / intercept() methods on the form instance:
+
// observe value of password
+
+form.observe({
+ path:'password'
+ key:'value',// can be any field property
+ call:({ form, field, change })=>{...},
+});
+
+
// intercept value of password
+
+form.intercept({
+ path:'username'
+ key:'value',// only some field property allowed
+ call:({ form, field, change })=>{...},
+});
+
+
The call function will receive the Form instance, the Field instance and the mobx event object (change).
+
+
Specify the Field path, the prop key to observe and the function (call) to fire when the event occurs.
+
Specify fields as key and the nested fields map will be observed or intercepted (add/del).
+
The intercept function must return a new mobx change event object.
+
For more info on the mobx change event object take a look at the mobx Event Overview Table.
+
+
Eventually you can use observe() / intercept() also on a selected Field:
+
You can pass a function or an object with key and call props.
+
// observe value of password
+
+form.$('password')
+ .observe(({ form, field, change })=>{...});
+
+
// intercept value of password
+
+form.$('password')
+ .intercept(({ form, field, change })=>{...});
+
+
+
Passing only a function the default key will be value.
+
The path is omitted. It's defined by the selector.
+
Specify fields as key and the nested fields map will be observed (add/del).
+
The intercept function must return a new mobx change event object.
If you need to initialize fields without initial state you have to define a fields object as an array with the additional fields, otherwise the field will not be created:
If you need to create complex forms, I suggest to use the Separated Properties method, as it is more flexible and can be easly extended to manage complex nested fields.
+
+
Fields Props Lifecycle:
+
Field Definitions>Constructor>Mutate Store>Component.
+
User Input>Event Handler / Action>Mutate Store>Event Hook.
import MobxReactForm,{ Field }from'mobx-react-form';
+
+
or you can also import the base Form like this:
+
import{ Form, Field }from'mobx-react-form';
+
+
In this example, you can see how to extend a specific field:
+
classCustomSelectFieldextendsField{
+
+ // for example we want to provide options values for the select input
+ dropDownOptions =['Poor','Average','Excellent','Unsure'];
+
+ constructor(props){
+ super(props);
+
+ // ...
+ }
+}
+
+
Into makeField() we have to match the field.key property with our sepcific field key/name.
The first argument represent the fields data with their props.
+
Provide an object which expects the following properties:
+
Fields Definition
+
+
+
+
Property
+
Description
+
Help
+
+
+
+
+
struct
+
Define fields structure as an array of strings representig the fields (dot notation ad array notation can be used)
+
-
+
+
+
fields
+
Using Unified Properties Definition mode: an object which represents the fields with all their properties. Using Separated Properties Definition mode: an array of strings which represents the fields structure.
Normally you have to pass the fields properties to the constructor, otherwise you can implement one of these methods above inside your extended Form Class.
+
For example, using the setup() method you can define the fields properties:
+
import Form from'mobx-react-form';
+
+classMyFormextendsMobxReactForm{
+
+ setup(){
+ // same of: new MyForm({ fields, values, labels, ... });
+ return{ fields, values, labels,...};
+ }
+}
+
+
+
The methods have to return an object with all needed props/data.
+
+
This can be done with options, plugins, bindings, handlers and hooks as well.
+
+
The object returned from the methods will be merged to the object provieded to the constructor when initializing the instance.
All options can also be used on a single instance of a Field.
+
+
+
+
+
Option
+
Type
+
Default
+
Info
+
+
+
+
+
fallback
+
boolean
+
true
+
Fields props definition fallback when using mixed definition mode (unified + separated).
+
+
+
fallbackValue
+
any
+
""
+
This is the default fallback field value applied by defaultValue() internal funciton when the field is created, cleared or resetted. It is defaulted as an empty string but can be anything if you need.
+
+
+
defaultGenericError
+
string
+
null
+
Set e default message to show when a generic error occurs.
+
+
+
submitThrowsError
+
boolean
+
true
+
If true and defaultGenericError is defined throws error and invalidate if validation fails on submit.
+
+
+
showErrorsOnInit
+
boolean
+
false
+
Show or hide error messages on init for validateOnInit.
+
+
+
showErrorsOnSubmit
+
boolean
+
true
+
Show or hide error messages on submit.
+
+
+
showErrorsOnBlur
+
boolean
+
true
+
Show or hide error messages on blur.
+
+
+
showErrorsOnChange
+
boolean
+
true
+
Show or hide errors on change.
+
+
+
showErrorsOnClear
+
boolean
+
false
+
Show or hide errors on clear.
+
+
+
showErrorsOnReset
+
boolean
+
true
+
Show or hide errors on reset.
+
+
+
validateOnInit
+
boolean
+
true
+
Validate of the whole form on init.
+
+
+
validateOnSubmit
+
boolean
+
true
+
Validate fieldset on submit. If disabled, Validation Hooks will not be triggered (onSuccess/onError)
+
+
+
validateOnBlur
+
boolean
+
true
+
Validate fields value on blur.
+
+
+
validateOnChange
+
boolean
+
false
+
Validate fields value on change.
+
+
+
validateOnChangeAfterSubmit
+
boolean
+
false
+
Validate fields value on change after form submit.
+
+
+
validateOnChangeAfterInitialBlur
+
boolean
+
false
+
Validate fields value on blur and then also on change only if already blurred.
+
+
+
validateDeletedFields
+
boolean
+
false
+
Enable or disable field validation based on their deleted property.
+
+
+
validateDisabledFields
+
boolean
+
false
+
Enable or disable field validation based on their disabled property.
+
+
+
validatePristineFields
+
boolean
+
true
+
Enable or disable field validation based on their isPristine property.
+
+
+
validateTrimmedValue
+
boolean
+
false
+
If enabled, it applies trim() to the field value before validate
+
+
+
strictSelect
+
boolean
+
true
+
Throw an error if trying to select an undefined field when using select() or the helper $().
+
+
+
strictSet
+
boolean
+
false
+
Throw an error if trying to update an undefined field when using set().
+
+
+
strictUpdate
+
boolean
+
false
+
Throw an error if trying to update an undefined field when using update().
+
+
+
strictDelete
+
boolean
+
true
+
Throw an error if trying to delete an undefined field.
+
+
+
softDelete
+
boolean
+
false
+
When using del() the field will not be deleted, instead its deleted prop will be switched to true.
+
+
+
retrieveOnlyEnabledFieldsErrors
+
boolean
+
false
+
Get only Enabled Fields Errors when using get('error') or the errors() helper.
+
+
+
retrieveOnlyEnabledFieldsValues
+
boolean
+
false
+
Get only Enabled Fields Values when using get('value') or the values() helper.
+
+
+
retrieveOnlyDirtyFieldsValues
+
boolean
+
false
+
Get only Dirty Fields Values when using get('value') or the values() helper.
+
+
+
removeNullishValuesInArrays
+
boolean
+
false
+
Remove nullish values from arrays when using get('value') or the values() helper.
+
+
+
retrieveNullifiedEmptyStrings
+
boolean
+
false
+
Convert empty strings to null when using get('value') or the values() helper.
+
+
+
preserveDeletedFieldsValues
+
boolean
+
false
+
After deleting and adding same field, the defined initial values will be preserverd if this option is activated.
+
+
+
autoTrimValue
+
boolean
+
false
+
Trim field value if is a string.
+
+
+
autoParseNumbers
+
boolean
+
false
+
Try to parse strings to numbers automatically if the initial value of the field is a number.
+
+
+
stopValidationOnError
+
boolean
+
false
+
If enabled, the validation stops to validate the field with new validation driver (and its functions) if has alredy marked invalid.
+
+
+
resetValidationBeforeValidate
+
boolean
+
true
+
If disabled, the validation state will not be resetted to its initials before validate (experimental)
+
+
+
validationPluginsOrder
+
string[]
+
undefined
+
Specify an array of strings with the validation plugins order. Accepted Plugins: vjf, dvr, svk, yup.
If enabled, apply input converter on field initialization
+
+
+
applyInputConverterOnSet
+
boolean
+
true
+
If enabled, apply input converter on field set()
+
+
+
applyInputConverterOnUpdate
+
boolean
+
true
+
If enabled, apply input converter on field update()
+
+
+
uniqueId
+
function
+
-
+
Implement a function to create custom Fields IDs. Useful for SSR. Takes the fields instance in input.
+
+
+
+
VERSION < 1.37
+
All the AJV options are moved into the plugin initialization.
+
For the previous version < 1.37 you can use these in the constructor:
+
+
+
+
Option
+
Type
+
Default
+
Info
+
+
+
+
+
ajv
+
object
+
-
+
Additional options for AJV. See all the details of ajv options on the official github page of AJV.
+
+
+
allowRequired
+
boolean
+
false
+
The AJV json-schema required property can work only if the object does not contain the field key/value pair, allowRequired can remove it when needed to make required work properly. Be careful because enabling it will make minLength uneffective when the string is empty.
const hooks ={
+ onSuccess(form){
+ alert('Form is valid! Send the request here.');
+ // get field values
+ console.log('Form Values!', form.values());
+ },
+ onError(form){
+ alert('Form has errors!');
+ // get all form errors
+ console.log('All form errors', form.errors());
+ }
+}
+
+
Initialize the Form
+
Simply pass the fields, plugins and hooks objects to the constructor
The validation functionalities are optional and you can choose which kind of library to import to achieve it, based on your own style preferences or needs. You can even mix plugins to achieve more flexibility.
+
All package listed below are not included in the mobx-react-form package and must be installed and passed to the constructor for the Form Initialization using the plugins object.
const asyncRules ={
+ checkUser:(value, attr, key, passes)=>{
+ const msg =`Hey! The username ${value} is already taken.`;
+ // show error if the call does not returns entries
+ simulateAsyncFindUserCall({ user: value })
+ .then((items)=>(items.length ===0)?passes():passes(false, msg));
+ },
+};
+
+
Implement the extend callback using registerAsync()
+
import dvr from'mobx-react-form/lib/validators/DVR';
+import validatorjs from'validatorjs';
+
+const plugins ={
+ dvr:dvr({
+ package: validatorjs,
+ extend:({ plugin })=>{
+ // here we can access the `validatorjs` instance (plugin) and we
+ // can add the rules using the `registerAsyncRule()` method.
+ Object.keys(asyncRules).forEach((key)=>
+ plugin.registerAsync(key, asyncRules[key]));
+ };
+ }),
+};
+
+// create the form using extended plugins
+newForm({...},{ plugins });
+
+
+
Read more about Asynchronous Validation on the official skaterdav85/validatorjs documentation.
Below we see how to implement it in mobx-react-form:
+
Define a rules object with the custom rules
+
const rules ={
+ telephone:{
+ function:(value)=> value.match(/^\d{3}-\d{3}-\d{4}$/),
+ message:'The :attribute phone number is not in the format XXX-XXX-XXXX.',
+ },
+};
+
+
Implement the extend callback for the plugins object
+
The extend function takes in input an object with the following props:
+
+
the form instance
+
the validator instance
+
+
import dvr from'mobx-react-form/lib/validators/DVR';
+import validatorjs from'validatorjs';
+
+const plugins ={
+ dvr:dvr({
+ package: validatorjs,
+ extend:({ validator, form })=>{
+ // here we can access the `validatorjs` instance (validator)
+ // and we can add the rules using the `register()` method.
+ Object.keys(rules).forEach((key)=>
+ validator.register(key, rules[key].function, rules[key].message));
+ };
+ }),
+};
+
+// create the form using the extended `plugins` object
+newForm({...},{ plugins });
+
The json-schema required property can work only if the object does not contain the field key/value pair, allowRequired can remove it when needed to make required work properly. Be careful because enabling it will make minLength uneffective when the string is empty.
After the promise is done, we get the result and pass them to a function which returns an array with two elements: the first element is the validation condition, the second is a string with the error message.
+
exportfunctioncheckUser({ field }){
+ const msg =`Hey! The username ${field.value} is already taken.`;
+ // show error if the call does not returns entries
+ returnsimulateAsyncFindUserCall({ user: field.value })
+ .then((items)=>[(items.length ===0), msg]);
+}
+
+
+
Tips
+
The async functions can be also written using arrow functions:
+
exportconstcheckUser=({ field })=>
+ simulateAsyncFindUserCall({ user: field.value })
+ .then(items =>[
+ (items.length ===0),
+ `Hey! The username ${field.value} is already taken.`,
+ ]);
+