Security News
New Python Packaging Proposal Aims to Solve Phantom Dependency Problem with SBOMs
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
@cerebral/forms
Advanced tools
NPM
npm install @cerebral/forms
The forms provider allows you to easily compute forms based on a number of rules. Easily add new rules, error messages and, if you want, add whatever you want to your fields for custom logic.
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
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.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
Security News
Socket CEO Feross Aboukhadijeh discusses open source security challenges, including zero-day attacks and supply chain risks, on the Cyber Security Council podcast.
Security News
Research
Socket researchers uncover how threat actors weaponize Out-of-Band Application Security Testing (OAST) techniques across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.