Skip to content

Commit 916b720

Browse files
vitalii-parkhomenko-officialVitaliy Parkhomenko
and
Vitaliy Parkhomenko
authored
fix(remove): submit errors are not removed on "fields.remove" call (final-form#48)
Co-authored-by: Vitaliy Parkhomenko <[email protected]>
1 parent 7e27b5c commit 916b720

File tree

4 files changed

+190
-13
lines changed

4 files changed

+190
-13
lines changed

src/remove.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { escapeRegexTokens } from './utils'
66
const remove: Mutator<any> = (
77
[name, index]: any[],
88
state: MutableState<any>,
9-
{ changeValue, renameField }: Tools<any>
9+
{ changeValue, renameField, getIn, setIn }: Tools<any>
1010
) => {
1111
let returnValue
1212
changeValue(state, name, (array: ?(any[])): any[] => {
@@ -27,6 +27,17 @@ const remove: Mutator<any> = (
2727
if (fieldIndex === index) {
2828
// delete any subfields for this array item
2929
delete state.fields[key]
30+
// delete any submitErrors for this array item
31+
// if the root key of the delete index
32+
if (key === `${name}[${index}]`) {
33+
const path = `formState.submitErrors.${name}`
34+
const submitErrors = getIn(state, path)
35+
// if has submitErrors for array
36+
if (Array.isArray(submitErrors)) {
37+
submitErrors.splice(index, 1)
38+
state = setIn(state, path, submitErrors)
39+
}
40+
}
3041
} else if (fieldIndex > index) {
3142
// shift all higher ones down
3243
delete state.fields[key]

src/remove.test.js

+174-7
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('remove', () => {
2323
}
2424
}
2525
}
26-
const result = remove(['foo', 0], state, { changeValue })
26+
const result = remove(['foo', 0], state, { changeValue, getIn, setIn })
2727
expect(result).toBeUndefined()
2828
expect(changeValue).toHaveBeenCalled()
2929
expect(changeValue).toHaveBeenCalledTimes(1)
@@ -42,7 +42,7 @@ describe('remove', () => {
4242
},
4343
fields: {}
4444
}
45-
const returnValue = remove(['foo', 1], state, { changeValue })
45+
const returnValue = remove(['foo', 1], state, { changeValue, getIn, setIn })
4646
expect(returnValue).toBeUndefined()
4747
const op = changeValue.mock.calls[0][2]
4848
const result = op(undefined)
@@ -116,7 +116,7 @@ describe('remove', () => {
116116
}
117117
}
118118
}
119-
const returnValue = remove(['foo', 1], state, { changeValue })
119+
const returnValue = remove(['foo', 1], state, { changeValue, getIn, setIn })
120120
expect(returnValue).toBe('b')
121121
expect(state.formState.values.foo).not.toBe(array) // copied
122122
expect(state).toEqual({
@@ -160,7 +160,6 @@ describe('remove', () => {
160160
}
161161
})
162162
})
163-
164163

165164
it('should remove value from the specified index, and return it (nested arrays)', () => {
166165
const array = ['a', 'b', 'c', 'd']
@@ -228,7 +227,11 @@ describe('remove', () => {
228227
}
229228
}
230229
}
231-
const returnValue = remove(['foo[0]', 1], state, { changeValue })
230+
const returnValue = remove(['foo[0]', 1], state, {
231+
changeValue,
232+
getIn,
233+
setIn
234+
})
232235
expect(returnValue).toBe('b')
233236
expect(state.formState.values.foo).not.toBe(array) // copied
234237
expect(state).toEqual({
@@ -271,7 +274,7 @@ describe('remove', () => {
271274
}
272275
}
273276
})
274-
})
277+
})
275278

276279
it('should remove value from the specified index, and handle new fields', () => {
277280
const array = ['a', { key: 'val' }]
@@ -324,11 +327,175 @@ describe('remove', () => {
324327
}
325328
}
326329
}
327-
const returnValue = remove(['foo', 0], state, { renameField, changeValue })
330+
const returnValue = remove(['foo', 0], state, {
331+
renameField,
332+
changeValue,
333+
getIn,
334+
setIn
335+
})
328336
expect(returnValue).toBeUndefined()
329337
expect(renameField).toHaveBeenCalledTimes(1)
330338
expect(renameField.mock.calls[0][0]).toEqual(state)
331339
expect(renameField.mock.calls[0][1]).toEqual('foo[1].key')
332340
expect(renameField.mock.calls[0][2]).toEqual('foo[0].key')
333341
})
342+
343+
it('should remove value from the specified index with submitError if one error in array', () => {
344+
const array = ['a', { key: 'val' }]
345+
const changeValue = jest.fn()
346+
const renameField = jest.fn()
347+
function blur0() {}
348+
function change0() {}
349+
function focus0() {}
350+
function blur1() {}
351+
function change1() {}
352+
function focus1() {}
353+
function blur2() {}
354+
function change2() {}
355+
function focus2() {}
356+
const state = {
357+
formState: {
358+
values: {
359+
foo: array,
360+
anotherField: 42
361+
},
362+
submitErrors: {
363+
foo: [
364+
{
365+
key: 'A Submit Error'
366+
}
367+
]
368+
}
369+
},
370+
fields: {
371+
'foo[0]': {
372+
name: 'foo[0]',
373+
blur: blur0,
374+
change: change0,
375+
focus: focus0,
376+
touched: true,
377+
error: 'A Error'
378+
},
379+
'foo[0].key': {
380+
name: 'foo[0].key',
381+
blur: blur2,
382+
change: change2,
383+
focus: focus2,
384+
touched: false,
385+
error: 'A Error'
386+
},
387+
'foo[1]': {
388+
name: 'foo[1]',
389+
blur: blur1,
390+
change: change1,
391+
focus: focus1,
392+
touched: false,
393+
error: 'B Error'
394+
},
395+
'foo[1].key': {
396+
name: 'foo[1].key',
397+
blur: blur2,
398+
change: change2,
399+
focus: focus2,
400+
touched: false,
401+
error: 'B Error'
402+
},
403+
anotherField: {
404+
name: 'anotherField',
405+
touched: false
406+
}
407+
}
408+
}
409+
410+
const returnValue = remove(['foo', 0], state, {
411+
renameField,
412+
changeValue,
413+
getIn,
414+
setIn
415+
})
416+
expect(returnValue).toBeUndefined()
417+
expect(getIn(state, 'formState.submitErrors')).toEqual({ foo: [] })
418+
})
419+
420+
it('should remove value from the specified index with submitError if two errors in array', () => {
421+
const array = ['a', { key: 'val' }]
422+
const changeValue = jest.fn()
423+
const renameField = jest.fn()
424+
function blur0() {}
425+
function change0() {}
426+
function focus0() {}
427+
function blur1() {}
428+
function change1() {}
429+
function focus1() {}
430+
function blur2() {}
431+
function change2() {}
432+
function focus2() {}
433+
const state = {
434+
formState: {
435+
values: {
436+
foo: array,
437+
anotherField: 42
438+
},
439+
submitErrors: {
440+
foo: [
441+
{
442+
key: 'A Submit Error'
443+
},
444+
{
445+
key: 'B Submit Error'
446+
}
447+
]
448+
}
449+
},
450+
fields: {
451+
'foo[0]': {
452+
name: 'foo[0]',
453+
blur: blur0,
454+
change: change0,
455+
focus: focus0,
456+
touched: true,
457+
error: 'A Error'
458+
},
459+
'foo[0].key': {
460+
name: 'foo[0].key',
461+
blur: blur2,
462+
change: change2,
463+
focus: focus2,
464+
touched: false,
465+
error: 'A Error'
466+
},
467+
'foo[1]': {
468+
name: 'foo[1]',
469+
blur: blur1,
470+
change: change1,
471+
focus: focus1,
472+
touched: false,
473+
error: 'B Error'
474+
},
475+
'foo[1].key': {
476+
name: 'foo[1].key',
477+
blur: blur2,
478+
change: change2,
479+
focus: focus2,
480+
touched: false,
481+
error: 'B Error'
482+
},
483+
anotherField: {
484+
name: 'anotherField',
485+
touched: false
486+
}
487+
}
488+
}
489+
490+
const returnValue = remove(['foo', 0], state, {
491+
renameField,
492+
changeValue,
493+
getIn,
494+
setIn
495+
})
496+
expect(returnValue).toBeUndefined()
497+
expect(getIn(state, 'formState.submitErrors')).toEqual({
498+
foo: [{ key: 'B Submit Error' }]
499+
})
500+
})
334501
})

src/shift.test.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('shift', () => {
2323
}
2424
}
2525
}
26-
const result = shift(['foo'], state, { changeValue })
26+
const result = shift(['foo'], state, { changeValue, getIn, setIn })
2727
expect(result).toBeUndefined()
2828
expect(changeValue).toHaveBeenCalled()
2929
expect(changeValue).toHaveBeenCalledTimes(1)
@@ -42,7 +42,7 @@ describe('shift', () => {
4242
},
4343
fields: {}
4444
}
45-
const returnValue = shift(['foo'], state, { changeValue })
45+
const returnValue = shift(['foo'], state, { changeValue, getIn, setIn })
4646
expect(returnValue).toBeUndefined()
4747
const op = changeValue.mock.calls[0][2]
4848
const result = op(undefined)
@@ -92,7 +92,7 @@ describe('shift', () => {
9292
}
9393
}
9494
}
95-
const returnValue = shift(['foo'], state, { changeValue })
95+
const returnValue = shift(['foo'], state, { changeValue, getIn, setIn })
9696
expect(returnValue).toBe('a')
9797
expect(state.formState.values.foo).not.toBe(array) // copied
9898
expect(state).toEqual({

src/utils.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@
22

33
// From MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
44
export const escapeRegexTokens = (string: string): string =>
5-
string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
6-
5+
string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string

0 commit comments

Comments
 (0)