Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
@cerebral/forms
Advanced tools
NPM
npm install @cerebral/forms
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 addon 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.
import { Controller } from 'cerebral'
import FormsProvider from '@cerebral/forms'
const controller = Controller({
providers: [
FormsProvider({
// Add additional rules
rules: {
myAddedRule(value, arg, get) {
// value of the field
value
// arg passed to the rule
arg
// The "get" argument from computed. Use it to grab
// state or props passed to component. The component
// will track use of these dependencies for rerender
get
return true
}
},
// errorMessage property added to field when invalid with the following rules
errorMessages: {
minLength(value, minLength) {
return `The length is ${
value.length
}, should be equal or more than ${minLength}`
}
}
})
]
})
To use a form you use the form computed, pointing to the form. Typically:
import React from 'react'
import { connect } from '@cerebral/react'
import { form } from '@cerebral/forms'
export default connect(
{
form: form(state`path.to.form`)
},
function MyForm({ form }) {
// Value of some field
form.someField.value
// A true/false if field has a value
form.someField.hasValue
// A true/false if field has been changed
form.someField.isPristine
// A true/false if field is valid
form.someField.isValid
// The name of the rule that failed
form.someField.failedRule.name
// Any arg you passed to the failing rule
form.someField.failedRule.arg
// If you have defined global error messages and field is invalid
form.someField.errorMessage
// Get all invalid fields
form.getInvalidFields()
// Get all fields
form.getFields()
}
)
You can also use the field computed, pointing to the field. This will optimize rendering as only the field will render on change.
import React from 'react'
import { connect } from '@cerebral/react'
import { field } from '@cerebral/forms'
export default connect(
{
field: field(state`path.to.form.name`)
},
function MyField({ field }) {
// Value of some field
field.value
// A true/false if field has a value
field.hasValue
// A true/false if field has been changed
field.isPristine
// A true/false if field is valid
field.isValid
}
)
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'
}
}
}
A field is just an object with a value
property:
{
myForm: {
myField: {
value: ''
}
}
}
A form is just an object in the state tree:
{
myForm: {
}
}
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
}
}
}
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']
}
}
}
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}
}
}
}
Diverge execution based on validity of a form.
import { state } from 'cerebral/tags'
import { isValidForm } from '@cerebral/forms/operators'
export default [
isValidForm(state`my.form`),
{
true: [],
false: []
}
]
Reset a form.
import { state } from 'cerebral/tags'
import { resetForm } from '@cerebral/forms/operators'
export default [resetForm(state`my.form`)]
When you change the value of a field you will need to use this operator. Note that you point to the field, not the field value.
import { state, props } from 'cerebral/tags'
import { setField } from '@cerebral/forms/operators'
export default [setField(state`my.form.field`, props`value`)]
You can also access your forms in actions.
function myAction({ forms }) {
const form = forms.get('path.to.form')
}
Reset the form to its default values (or empty string by default).
function myAction({ forms }) {
forms.reset('path.to.form')
}
Typically you want to convert your forms to a plain value structure.
function myAction({ forms }) {
const form = forms.toJSON('path.to.form')
}
This form will now have the structure of:
{
myField: 'theValue',
address: {
street: 'street value',
zipCode: 'zip code value'
}
}
Dynamically update global error messages:
function myAction({ forms }) {
forms.updateErrorMessages({
someRule() {}
})
}
Dynamically update available rules:
function myAction({ forms }) {
forms.updateRules({
someNewRule() {}
})
}
You add validation rules on the field:
{
myForm: {
firstName: {
value: '',
validationRules: ['minLength:3']
}
}
}
{
field1: {
value: 123, // valid
validationRules: ['equals:123']
},
field2: {
value: '123', // valid
validationRules: ['equals:"123"']
},
field3: {
value: [], // not valid
validationRules: ['equals:[]']
}
}
{
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']
}
}
{
field1: {
value: 'abc', // valid
validationRules: ['isAlpha']
},
field2: {
value: 'AbC', // valid
validationRules: ['isAlpha']
},
field3: {
value: '123abc', // not valid
validationRules: ['isAlpha']
}
}
{
field1: {
value: '123abc', // valid
validationRules: ['isAlphanumeric']
},
field2: {
value: '123', // valid
validationRules: ['isAlphanumeric']
},
field3: {
value: '123+abc', // not valid
validationRules: ['isAlphanumeric']
}
}
{
field1: {
value: 'ho@hep.co', // valid
validationRules: ['isEmail']
},
field2: {
value: 'hello@', // not valid
validationRules: ['isEmail']
},
field3: {
value: 'hel.co', // not valid
validationRules: ['isEmail']
}
}
{
field1: {
value: '', // valid
validationRules: ['isEmpty']
},
field2: {
value: 'hello', // not valid
validationRules: ['isEmpty']
},
field3: {
value: 123, // not valid
validationRules: ['isEmpty']
}
}
{
field1: {
value: 0, // valid
validationRules: ['isExisty']
},
field2: {
value: [], // valid
validationRules: ['isExisty']
},
field3: {
value: null, // not valid
validationRules: ['isExisty']
}
}
{
field1: {
value: false, // valid
validationRules: ['isFalse']
},
field2: {
value: 'false', // not valid
validationRules: ['isFalse']
},
field3: {
value: true, // not valid
validationRules: ['isFalse']
}
}
{
field1: {
value: '22.5', // valid
validationRules: ['isFloat']
},
field2: {
value: 22.5, // valid
validationRules: ['isFloat']
},
field3: {
value: '22', // not valid
validationRules: ['isFloat']
}
}
{
field1: {
value: '123', // valid
validationRules: ['isInt']
},
field2: {
value: 123, // valid
validationRules: ['isInt']
},
field3: {
value: '22.5', // not valid
validationRules: ['isInt']
}
}
{
field1: {
value: 'hey', // valid
validationRules: ['isLength:3']
},
field2: {
value: ['foo', 'bar'], // valid
validationRules: ['isLength:2']
},
field3: {
value: 'hm 123', // not valid
validationRules: ['isLength:3']
}
}
{
field1: {
value: '123', // valid
validationRules: ['isNumeric']
},
field2: {
value: 123, // valid
validationRules: ['isNumeric']
},
field3: {
value: '123abc', // not valid
validationRules: ['isNumeric']
}
}
{
field1: {
value: 'hey there', // valid
validationRules: ['isSpecialWords']
},
field2: {
value: 'some åäö', // valid
validationRules: ['isSpecialWords']
},
field3: {
value: 'hm 123', // not valid
validationRules: ['isSpecialWords']
}
}
{
field1: {
value: true, // valid
validationRules: ['isTrue']
},
field2: {
value: 'true', // not valid
validationRules: ['isTrue']
},
field3: {
value: false, // not valid
validationRules: ['isTrue']
}
}
{
field1: {
value: undefined, // valid
validationRules: ['isUndefined']
},
field2: {
value: 'hello', // not valid
validationRules: ['isUndefined']
},
field3: {
value: 123, // not valid
validationRules: ['isUndefined']
}
}
{
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']
}
}
{
field1: {
value: 'hey there', // valid
validationRules: ['isWords']
},
field2: {
value: 'wut åäö', // not valid
validationRules: ['isWords']
},
field3: {
value: 'hm 123', // not valid
validationRules: ['isWords']
}
}
{
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']
}
}
{
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']
}
}
{
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']
}
}
{
field1: {
value: 'foo', // valid
validationRules: [/foo/]
},
field2: {
value: 'bar', // not valid
validationRules: [/foo/]
}
}
FAQs
A computed form
The npm package @cerebral/forms receives a total of 30 weekly downloads. As such, @cerebral/forms popularity was classified as not popular.
We found that @cerebral/forms demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.