state-forms
A computed form - originally @cerebral/forms
Migrating from @cerebral/forms? See the migration guide at the bottom of this readme.
Install
NPM
npm install state-forms
Description
Forms are one of the most complex state management challenges out there. Before Cerebral was created I spent a lot of time developing formsy-react, which is a library that tries to solve forms with internal state. With the release of Cerebral we got a chance to explore the space of solving forms complexity with external state instead. To this day I have a hard time recommending a solution and you should not see this lib as "the official way of managing forms with Cerebral". There is nothing wrong thinking of a form as a very complex input where you only pass data into Cerebral on the submit of the form.
Instantiate
const controller =
compute
To use a form you use the form function to generate computed form state. Typically:
form: { // Value of some field formsomeFieldvalue // A true/false if field has a value formsomeFieldhasValue // A true/false if field has been changed formsomeFieldisPristine // A true/false if field is valid formsomeFieldisValid // The name of the rule that failed formsomeFieldfailedRulename // Any arg you passed to the failing rule formsomeFieldfailedRulearg // If you have defined global error messages and field is invalid formsomeFielderrorMessage // Get all invalid fields form // Get all fields form }
You can also use the field computed, pointing to the field. This will optimize rendering as only the field will render on change.
field: { // Value of some field fieldvalue // A true/false if field has a value fieldhasValue // A true/false if field has been changed fieldisPristine // A true/false if field is valid fieldisValid }
defaultValue
You can define a default value for your fields. When the form is reset, it will put back the default value:
myForm: firstName: value: '' defaultValue: 'Ben'
field
A field is just an object with a value
property:
myForm: myField: value: ''
form
A form is just an object in the state tree:
myForm:
isRequired
Define field as required. This will make the field invalid if there is no value. By default forms identifies a value or not using the isValue rule. You can change this rule if you want, look below.
myForm: firstName: value: '' isRequired: true
isValueRules
You can change what defines a field as having a value. For example if your value is an array, you can use the minLength rule to define a required minimum of 3 items in the array.
myForm: interests: value: isRequired: true isValueRules: 'minLength:3'
nesting
You can nest this however you want, even with array:
myForm: firstName: value: '' lastName: value: '' address: street: value: '' zipCode: value: '' interests: books: value: false films: value: false
helpers
toJSON
Typically you want to convert your forms to a plain value structure.
const form =
This form will now have the structure of:
myField: 'theValue' address: street: 'street value' zipCode: 'zip code value'
resetForm
Reset a form to to the default values
const form =
updateErrorMessages
Dynamically update global error messages:
{ forms}
updateRules
Dynamically update available rules:
{ forms}
validationRules
You add validation rules on the field:
myForm: firstName: value: '' validationRules: 'minLength:3'
equals:Value
field1: value: 123 // valid validationRules: 'equals:123' field2: value: '123' // valid validationRules: 'equals:"123"' field3: value: // not valid validationRules: 'equals:[]'
equalsField:Field
field1: value: 'foo' // valid validationRules: 'equalsField:full.path.to.form.field2' field2: value: 'foo' // valid validationRules: 'equalsField:full.path.to.form.field1' field3: value: 'bar' // not valid validationRules: 'equalsField:full.path.to.form.field2'
isAlpha
field1: value: 'abc' // valid validationRules: 'isAlpha' field2: value: 'AbC' // valid validationRules: 'isAlpha' field3: value: '123abc' // not valid validationRules: 'isAlpha'
isAlphanumeric
field1: value: '123abc' // valid validationRules: 'isAlphanumeric' field2: value: '123' // valid validationRules: 'isAlphanumeric' field3: value: '123+abc' // not valid validationRules: 'isAlphanumeric'
isEmail
field1: value: 'ho@hep.co' // valid validationRules: 'isEmail' field2: value: 'hello@' // not valid validationRules: 'isEmail' field3: value: 'hel.co' // not valid validationRules: 'isEmail'
isEmpty
field1: value: '' // valid validationRules: 'isEmpty' field2: value: 'hello' // not valid validationRules: 'isEmpty' field3: value: 123 // not valid validationRules: 'isEmpty'
isExisty
field1: value: 0 // valid validationRules: 'isExisty' field2: value: // valid validationRules: 'isExisty' field3: value: null // not valid validationRules: 'isExisty'
isFalse
field1: value: false // valid validationRules: 'isFalse' field2: value: 'false' // not valid validationRules: 'isFalse' field3: value: true // not valid validationRules: 'isFalse'
isFloat
field1: value: '22.5' // valid validationRules: 'isFloat' field2: value: 225 // valid validationRules: 'isFloat' field3: value: '22' // not valid validationRules: 'isFloat'
isInt
field1: value: '123' // valid validationRules: 'isInt' field2: value: 123 // valid validationRules: 'isInt' field3: value: '22.5' // not valid validationRules: 'isInt'
isLength:Number
field1: value: 'hey' // valid validationRules: 'isLength:3' field2: value: 'foo' 'bar' // valid validationRules: 'isLength:2' field3: value: 'hm 123' // not valid validationRules: 'isLength:3'
isNumeric
field1: value: '123' // valid validationRules: 'isNumeric' field2: value: 123 // valid validationRules: 'isNumeric' field3: value: '123abc' // not valid validationRules: 'isNumeric'
isSpecialWords
field1: value: 'hey there' // valid validationRules: 'isSpecialWords' field2: value: 'some åäö' // valid validationRules: 'isSpecialWords' field3: value: 'hm 123' // not valid validationRules: 'isSpecialWords'
isTrue
field1: value: true // valid validationRules: 'isTrue' field2: value: 'true' // not valid validationRules: 'isTrue' field3: value: false // not valid validationRules: 'isTrue'
isUndefined
field1: value: undefined // valid validationRules: 'isUndefined' field2: value: 'hello' // not valid validationRules: 'isUndefined' field3: value: 123 // not valid validationRules: 'isUndefined'
isUrl
field1: value: 'http://www.test.com' // valid validationRules: 'isUrl' field2: value: 'http://www' // not valid validationRules: 'isUrl' field3: value: 'http//www' // not valid validationRules: 'isUrl'
isWords
field1: value: 'hey there' // valid validationRules: 'isWords' field2: value: 'wut åäö' // not valid validationRules: 'isWords' field3: value: 'hm 123' // not valid validationRules: 'isWords'
isValue
field1: value: 'test' // valid validationRules: 'isValue' field2: value: // not valid validationRules: 'isValue' field3: value: null // not valid validationRules: 'isValue' field3: value: false // not valid validationRules: 'isValue'
maxLength:Number
field1: value: '123' // valid validationRules: 'maxLength:3' field2: value: 'fo' // valid validationRules: 'maxLength:3' field3: value: 'foo' 'bar' 'baz' 'mip' // not valid validationRules: 'maxLength:3'
minLength:Number
field1: value: '123' // valid validationRules: 'minLength:3' field2: value: 'fo' // not valid validationRules: 'minLength:3' field3: value: 'foo' 'bar' 'baz' 'mip' // valid validationRules: 'minLength:3'
regexp
field1: value: 'foo' // valid validationRules: /foo/ field2: value: 'bar' // not valid validationRules: /foo/
Migrating from @cerebral/forms
since state-forms does not depend on Cerebral it does not use Providers or Computes, but you can wrap state-forms functions in Providers and Computes for the same effect.
An example Cerebral controller:
// import { Controller, Module } from 'cerebral' // before// import FormsProvider from '@cerebral/forms' // before
An example connected component:
// import { form } from '@cerebral/forms' // before // myForm: form(state`myForm`) // before myForm: // after MyComponent
state-forms does not contain any Cerebral operators, but it does has the helpers that are needed to create your own.
isValidForm.js
{ const formValue = return formValueisValid ? path : path }
resetForm.js
{ const path = resolve state }
setField.js
{ { state }