Decorator for 🏁 Final Form that allows you to define calculations that happen between fields, i.e. "When field X changes, update field Y."
npm install --save final-form-calculate
or
yarn add final-form-calculate
import { createForm, getIn } from 'final-form'
import createDecorator from 'final-form-calculate'
// Create Form
const form = createForm({ onSubmit })
// Create Decorator
const decorator = createDecorator(
// Calculations:
{
field: 'foo', // when the value of foo changes...
updates: {
// ...set field "doubleFoo" to twice the value of foo
doubleFoo: (fooValue, allValues) => fooValue * 2
}
},
{
field: 'bar', // when the value of bar changes...
updates: {
// ...set field "foo" to previous value of bar
foo: (fooValue, allValues, prevValues) => prevValues.bar
}
},
{
field: /items\[\d+\]/, // when a field matching this pattern changes...
updates: {
// ...sets field "total" to the sum of all items
total: (itemValue, allValues) =>
(allValues.items || []).reduce((sum, value) => sum + value, 0)
}
},
{
field: 'foo', // when the value of foo changes...
updates: {
// ...asynchronously set field "doubleFoo" to twice the value using a promise
doubleFoo: (fooValue, allValues) =>
new Promise(resolve => {
setTimeout(() => resolve(fooValue * 2), 100)
})
}
},
{
field: /\.timeFrom/, // when a deeper field matching this pattern changes...
updates: (value, name, allValues) => {
const toField = name.replace('timeFrom', 'timeTo')
const toValue = getIn(allValues, toField)
if (toValue && value > toValue) {
return {
[toField]: value
}
}
return {}
}
}
)
// Decorate form
const undecorate = decorator(form)
// Use form as normal
Example using 🏁 React Final Form.
createDecorator: (...calculations: Calculation[]) => Decorator
A function that takes a set of calculations and returns a 🏁 Final Form
Decorator
.
Calculation: { field: FieldPattern, isEqual?: (any, any) => boolean, updates: Updates }
A calculation to perform, with an optional isEqual
predicate to determine if a value has really changed (defaults to ===
).
FieldName: string
FieldPattern: FieldName | RegExp | (FieldName | RegExp)[]
A pattern to match a field with.
Updates: UpdatesByName | UpdatesForAll
Either an object of updater functions or a function that generates updates for multiple fields.
UpdatesByName: { [FieldName]: (value: any, allValues: Object, prevValues: Object) => Promise | any }
Updater functions for each calculated field.
UpdatesForAll: (value: any, field: string, allValues: Object, prevValues: Object) => Promise | { [FieldName]: any }
Takes the value and name of the field that just changed, as well as all the values, and returns an object of fields and new values.