immutable-react-form
Immutable form state management for ReactJS

npm i --save @trioxis/immutable-react-form
Usage
Immutable form is a Higher Order Component (HOC), used like so:
import React from 'react';
import { LocalStateForm } from '@trioxis/immutable-react-form';
import { Map } from 'immutable';
function MyForm(props){
const {
form
} = props;
return <form onSubmit={form.submission.submit}>
<input
type='text'
value={form.model.get('name')}
onChange={(e)=>update(form.model.set('name',e.target.value))}
/>
</form>
}
LocalStateForm(
props => ({name: ''}),
() => new Map({}),
(model, props) => Promise.resolve()
)(
MyForm
)
Full props are as follows:
const {
form:{
model,
update,
meta:{
dirty
},
validation:{
get,
isValid,
},
submission:{
submit,
loading,
lastSubmission: {
success,
error
}
}
}
} = props;
Validation
Validation function must return an (Immutable JS) Map where each key is a path to the validation object.
If a path is not defined, it is assumed valid.
Example:
function validateForm(model){
return new Map({
...(model.get('name').split(' ').length !== 2)
&& { name: { valid:false, message:'Apparently you should only have 2 names' } },
...!model.get('name')
&& { name: { valid:false, message:'Name is required' } },
...(model.get('experience').size < 3)
&& { experience : { valid:false, message:'Please write 3 or more things' } },
...(
model.get('experience')
.map((exp,i)=>new Map({item:exp,index:i}))
.filter(exp=>!(['Education','Job'].includes(exp.getIn(['item','type']))))
.reduce((acc,curr,i)=>({
...acc,
[`experience.${curr.get('index')}.type`]: { valid:false, message:'Can be "Education" or "Job"'}
}),{})
)
})
}
Recipies
Smart submit button
(props)=>
<input
type='submit'
value={props.form.submission.loading ? 'Submitting...' : 'Submit'}
disabled={(
!props.form.meta.dirty ||
!props.form.validation.isValid ||
props.form.submission.loading
)}
/>