Skip to content

Commit 6c79245

Browse files
swernerxerikras
authored andcommitted
Adding support for dynamic update methods. (#6)
* Added support for 'updates' being a method. * Added test case for new update method handling * Minor changes * Added example
1 parent 8de217b commit 6c79245

File tree

3 files changed

+100
-5
lines changed

3 files changed

+100
-5
lines changed

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ yarn add final-form-calculate
2727
## Usage
2828

2929
```js
30-
import { createForm } from 'final-form'
30+
import { createForm, getIn } from 'final-form'
3131
import createDecorator from 'final-form-calculate'
3232

3333
// Create Form
@@ -50,6 +50,20 @@ const decorator = createDecorator(
5050
total: (itemValue, allValues) =>
5151
(allValues.items || []).reduce((sum, value) => sum + value, 0)
5252
}
53+
},
54+
{
55+
field: /\.timeFrom/, // when a deeper field matching this pattern changes...
56+
updates: (value, name, allValues) => {
57+
const toField = name.replace('timeFrom', 'timeTo')
58+
const toValue = getIn(allValues, toField)
59+
if (toValue && value > toValue) {
60+
return {
61+
[toField]: value
62+
}
63+
}
64+
65+
return {}
66+
}
5367
}
5468
)
5569

src/decorator.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,17 @@ const createDecorator = (...calculations: Calculation[]): Decorator => (
1414
const next = getIn(values, field)
1515
const previous = getIn(previousValues, field)
1616
if (next !== previous) {
17-
Object.keys(updates).forEach(destField => {
18-
const update = updates[destField]
19-
form.change(destField, update(next, values))
20-
})
17+
if (typeof updates === 'function') {
18+
const results = updates(next, field, values)
19+
Object.keys(results).forEach(destField => {
20+
form.change(destField, results[destField])
21+
})
22+
} else {
23+
Object.keys(updates).forEach(destField => {
24+
const update = updates[destField]
25+
form.change(destField, update(next, values))
26+
})
27+
}
2128
}
2229
}
2330
const fields = form.getRegisteredFields()

src/decorator.test.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,78 @@ describe('decorator', () => {
204204
expect(spy.mock.calls[5][0].values).toEqual({ items: [3, 4, 5], total: 7 })
205205
expect(spy.mock.calls[6][0].values).toEqual({ items: [3, 4, 5], total: 12 })
206206
})
207+
208+
it('should allow seperate array summing', () => {
209+
const form = createForm({ onSubmit: onSubmitMock })
210+
const spy = jest.fn()
211+
const total = jest.fn()
212+
const sum = jest.fn((itemValue, allValues) =>
213+
(allValues.list[0].items || []).reduce((sum, item) => sum + item, 0)
214+
)
215+
form.subscribe(spy, { values: true })
216+
form.registerField('list[0].items[0]', () => {}, {})
217+
form.registerField('list[0].items[1]', () => {}, {})
218+
form.registerField('list[0].items[2]', () => {}, {})
219+
form.registerField('list[0].total', total, { value: true })
220+
const decorator = createDecorator({
221+
field: /\.items\[\d+\]/,
222+
updates: (value, name, all) => {
223+
const totalField = name.replace(/items\[[0-9]+\]/, 'total')
224+
return {
225+
[totalField]: sum(value, all)
226+
}
227+
}
228+
})
229+
decorator(form)
230+
231+
expect(spy).toHaveBeenCalled()
232+
expect(spy).toHaveBeenCalledTimes(1)
233+
expect(spy.mock.calls[0][0].values).toEqual({})
234+
235+
expect(total).toHaveBeenCalled()
236+
expect(total).toHaveBeenCalledTimes(1)
237+
expect(total.mock.calls[0][0].value).toBeUndefined()
238+
239+
expect(sum).not.toHaveBeenCalled()
240+
241+
// change first item value
242+
form.change('list[0].items[0]', 3)
243+
244+
expect(sum).toHaveBeenCalled()
245+
expect(sum).toHaveBeenCalledTimes(1)
246+
247+
expect(spy).toHaveBeenCalledTimes(3)
248+
expect(spy.mock.calls[1][0].values).toEqual({ list: [{ items: [3] }] })
249+
expect(spy.mock.calls[2][0].values).toEqual({
250+
list: [{ items: [3], total: 3 }]
251+
})
252+
253+
// change second item value
254+
form.change('list[0].items[1]', 4)
255+
256+
expect(sum).toHaveBeenCalled()
257+
expect(sum).toHaveBeenCalledTimes(2)
258+
259+
expect(spy).toHaveBeenCalledTimes(5)
260+
expect(spy.mock.calls[3][0].values).toEqual({
261+
list: [{ items: [3, 4], total: 3 }]
262+
})
263+
expect(spy.mock.calls[4][0].values).toEqual({
264+
list: [{ items: [3, 4], total: 7 }]
265+
})
266+
267+
// change third item value
268+
form.change('list[0].items[2]', 5)
269+
270+
expect(sum).toHaveBeenCalled()
271+
expect(sum).toHaveBeenCalledTimes(3)
272+
273+
expect(spy).toHaveBeenCalledTimes(7)
274+
expect(spy.mock.calls[5][0].values).toEqual({
275+
list: [{ items: [3, 4, 5], total: 7 }]
276+
})
277+
expect(spy.mock.calls[6][0].values).toEqual({
278+
list: [{ items: [3, 4, 5], total: 12 }]
279+
})
280+
})
207281
})

0 commit comments

Comments
 (0)