Skip to content

Commit

Permalink
Adding support for dynamic update methods. (#6)
Browse files Browse the repository at this point in the history
* Added support for 'updates' being a method.

* Added test case for new update method handling

* Minor changes

* Added example
  • Loading branch information
swernerx authored and erikras committed Mar 19, 2018
1 parent 8de217b commit 6c79245
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 5 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ yarn add final-form-calculate
## Usage

```js
import { createForm } from 'final-form'
import { createForm, getIn } from 'final-form'
import createDecorator from 'final-form-calculate'

// Create Form
Expand All @@ -50,6 +50,20 @@ const decorator = createDecorator(
total: (itemValue, allValues) =>
(allValues.items || []).reduce((sum, value) => sum + value, 0)
}
},
{
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 {}
}
}
)

Expand Down
15 changes: 11 additions & 4 deletions src/decorator.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,17 @@ const createDecorator = (...calculations: Calculation[]): Decorator => (
const next = getIn(values, field)
const previous = getIn(previousValues, field)
if (next !== previous) {
Object.keys(updates).forEach(destField => {
const update = updates[destField]
form.change(destField, update(next, values))
})
if (typeof updates === 'function') {
const results = updates(next, field, values)
Object.keys(results).forEach(destField => {
form.change(destField, results[destField])
})
} else {
Object.keys(updates).forEach(destField => {
const update = updates[destField]
form.change(destField, update(next, values))
})
}
}
}
const fields = form.getRegisteredFields()
Expand Down
74 changes: 74 additions & 0 deletions src/decorator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,78 @@ describe('decorator', () => {
expect(spy.mock.calls[5][0].values).toEqual({ items: [3, 4, 5], total: 7 })
expect(spy.mock.calls[6][0].values).toEqual({ items: [3, 4, 5], total: 12 })
})

it('should allow seperate array summing', () => {
const form = createForm({ onSubmit: onSubmitMock })
const spy = jest.fn()
const total = jest.fn()
const sum = jest.fn((itemValue, allValues) =>
(allValues.list[0].items || []).reduce((sum, item) => sum + item, 0)
)
form.subscribe(spy, { values: true })
form.registerField('list[0].items[0]', () => {}, {})
form.registerField('list[0].items[1]', () => {}, {})
form.registerField('list[0].items[2]', () => {}, {})
form.registerField('list[0].total', total, { value: true })
const decorator = createDecorator({
field: /\.items\[\d+\]/,
updates: (value, name, all) => {
const totalField = name.replace(/items\[[0-9]+\]/, 'total')
return {
[totalField]: sum(value, all)
}
}
})
decorator(form)

expect(spy).toHaveBeenCalled()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy.mock.calls[0][0].values).toEqual({})

expect(total).toHaveBeenCalled()
expect(total).toHaveBeenCalledTimes(1)
expect(total.mock.calls[0][0].value).toBeUndefined()

expect(sum).not.toHaveBeenCalled()

// change first item value
form.change('list[0].items[0]', 3)

expect(sum).toHaveBeenCalled()
expect(sum).toHaveBeenCalledTimes(1)

expect(spy).toHaveBeenCalledTimes(3)
expect(spy.mock.calls[1][0].values).toEqual({ list: [{ items: [3] }] })
expect(spy.mock.calls[2][0].values).toEqual({
list: [{ items: [3], total: 3 }]
})

// change second item value
form.change('list[0].items[1]', 4)

expect(sum).toHaveBeenCalled()
expect(sum).toHaveBeenCalledTimes(2)

expect(spy).toHaveBeenCalledTimes(5)
expect(spy.mock.calls[3][0].values).toEqual({
list: [{ items: [3, 4], total: 3 }]
})
expect(spy.mock.calls[4][0].values).toEqual({
list: [{ items: [3, 4], total: 7 }]
})

// change third item value
form.change('list[0].items[2]', 5)

expect(sum).toHaveBeenCalled()
expect(sum).toHaveBeenCalledTimes(3)

expect(spy).toHaveBeenCalledTimes(7)
expect(spy.mock.calls[5][0].values).toEqual({
list: [{ items: [3, 4, 5], total: 7 }]
})
expect(spy.mock.calls[6][0].values).toEqual({
list: [{ items: [3, 4, 5], total: 12 }]
})
})
})

0 comments on commit 6c79245

Please sign in to comment.