diff --git a/src/remove.js b/src/remove.js index 8af1f60..887c906 100644 --- a/src/remove.js +++ b/src/remove.js @@ -6,7 +6,7 @@ import { escapeRegexTokens } from './utils' const remove: Mutator = ( [name, index]: any[], state: MutableState, - { changeValue, renameField }: Tools + { changeValue, renameField, getIn, setIn }: Tools ) => { let returnValue changeValue(state, name, (array: ?(any[])): any[] => { @@ -27,6 +27,17 @@ const remove: Mutator = ( if (fieldIndex === index) { // delete any subfields for this array item delete state.fields[key] + // delete any submitErrors for this array item + // if the root key of the delete index + if (key === `${name}[${index}]`) { + const path = `formState.submitErrors.${name}` + const submitErrors = getIn(state, path) + // if has submitErrors for array + if (Array.isArray(submitErrors)) { + submitErrors.splice(index, 1) + state = setIn(state, path, submitErrors) + } + } } else if (fieldIndex > index) { // shift all higher ones down delete state.fields[key] diff --git a/src/remove.test.js b/src/remove.test.js index fd4a685..e103d7d 100644 --- a/src/remove.test.js +++ b/src/remove.test.js @@ -23,7 +23,7 @@ describe('remove', () => { } } } - const result = remove(['foo', 0], state, { changeValue }) + const result = remove(['foo', 0], state, { changeValue, getIn, setIn }) expect(result).toBeUndefined() expect(changeValue).toHaveBeenCalled() expect(changeValue).toHaveBeenCalledTimes(1) @@ -42,7 +42,7 @@ describe('remove', () => { }, fields: {} } - const returnValue = remove(['foo', 1], state, { changeValue }) + const returnValue = remove(['foo', 1], state, { changeValue, getIn, setIn }) expect(returnValue).toBeUndefined() const op = changeValue.mock.calls[0][2] const result = op(undefined) @@ -116,7 +116,7 @@ describe('remove', () => { } } } - const returnValue = remove(['foo', 1], state, { changeValue }) + const returnValue = remove(['foo', 1], state, { changeValue, getIn, setIn }) expect(returnValue).toBe('b') expect(state.formState.values.foo).not.toBe(array) // copied expect(state).toEqual({ @@ -160,7 +160,6 @@ describe('remove', () => { } }) }) - it('should remove value from the specified index, and return it (nested arrays)', () => { const array = ['a', 'b', 'c', 'd'] @@ -228,7 +227,11 @@ describe('remove', () => { } } } - const returnValue = remove(['foo[0]', 1], state, { changeValue }) + const returnValue = remove(['foo[0]', 1], state, { + changeValue, + getIn, + setIn + }) expect(returnValue).toBe('b') expect(state.formState.values.foo).not.toBe(array) // copied expect(state).toEqual({ @@ -271,7 +274,7 @@ describe('remove', () => { } } }) - }) + }) it('should remove value from the specified index, and handle new fields', () => { const array = ['a', { key: 'val' }] @@ -324,11 +327,175 @@ describe('remove', () => { } } } - const returnValue = remove(['foo', 0], state, { renameField, changeValue }) + const returnValue = remove(['foo', 0], state, { + renameField, + changeValue, + getIn, + setIn + }) expect(returnValue).toBeUndefined() expect(renameField).toHaveBeenCalledTimes(1) expect(renameField.mock.calls[0][0]).toEqual(state) expect(renameField.mock.calls[0][1]).toEqual('foo[1].key') expect(renameField.mock.calls[0][2]).toEqual('foo[0].key') }) + + it('should remove value from the specified index with submitError if one error in array', () => { + const array = ['a', { key: 'val' }] + const changeValue = jest.fn() + const renameField = jest.fn() + function blur0() {} + function change0() {} + function focus0() {} + function blur1() {} + function change1() {} + function focus1() {} + function blur2() {} + function change2() {} + function focus2() {} + const state = { + formState: { + values: { + foo: array, + anotherField: 42 + }, + submitErrors: { + foo: [ + { + key: 'A Submit Error' + } + ] + } + }, + fields: { + 'foo[0]': { + name: 'foo[0]', + blur: blur0, + change: change0, + focus: focus0, + touched: true, + error: 'A Error' + }, + 'foo[0].key': { + name: 'foo[0].key', + blur: blur2, + change: change2, + focus: focus2, + touched: false, + error: 'A Error' + }, + 'foo[1]': { + name: 'foo[1]', + blur: blur1, + change: change1, + focus: focus1, + touched: false, + error: 'B Error' + }, + 'foo[1].key': { + name: 'foo[1].key', + blur: blur2, + change: change2, + focus: focus2, + touched: false, + error: 'B Error' + }, + anotherField: { + name: 'anotherField', + touched: false + } + } + } + + const returnValue = remove(['foo', 0], state, { + renameField, + changeValue, + getIn, + setIn + }) + expect(returnValue).toBeUndefined() + expect(getIn(state, 'formState.submitErrors')).toEqual({ foo: [] }) + }) + + it('should remove value from the specified index with submitError if two errors in array', () => { + const array = ['a', { key: 'val' }] + const changeValue = jest.fn() + const renameField = jest.fn() + function blur0() {} + function change0() {} + function focus0() {} + function blur1() {} + function change1() {} + function focus1() {} + function blur2() {} + function change2() {} + function focus2() {} + const state = { + formState: { + values: { + foo: array, + anotherField: 42 + }, + submitErrors: { + foo: [ + { + key: 'A Submit Error' + }, + { + key: 'B Submit Error' + } + ] + } + }, + fields: { + 'foo[0]': { + name: 'foo[0]', + blur: blur0, + change: change0, + focus: focus0, + touched: true, + error: 'A Error' + }, + 'foo[0].key': { + name: 'foo[0].key', + blur: blur2, + change: change2, + focus: focus2, + touched: false, + error: 'A Error' + }, + 'foo[1]': { + name: 'foo[1]', + blur: blur1, + change: change1, + focus: focus1, + touched: false, + error: 'B Error' + }, + 'foo[1].key': { + name: 'foo[1].key', + blur: blur2, + change: change2, + focus: focus2, + touched: false, + error: 'B Error' + }, + anotherField: { + name: 'anotherField', + touched: false + } + } + } + + const returnValue = remove(['foo', 0], state, { + renameField, + changeValue, + getIn, + setIn + }) + expect(returnValue).toBeUndefined() + expect(getIn(state, 'formState.submitErrors')).toEqual({ + foo: [{ key: 'B Submit Error' }] + }) + }) }) diff --git a/src/shift.test.js b/src/shift.test.js index 8cdd551..59bac3b 100644 --- a/src/shift.test.js +++ b/src/shift.test.js @@ -23,7 +23,7 @@ describe('shift', () => { } } } - const result = shift(['foo'], state, { changeValue }) + const result = shift(['foo'], state, { changeValue, getIn, setIn }) expect(result).toBeUndefined() expect(changeValue).toHaveBeenCalled() expect(changeValue).toHaveBeenCalledTimes(1) @@ -42,7 +42,7 @@ describe('shift', () => { }, fields: {} } - const returnValue = shift(['foo'], state, { changeValue }) + const returnValue = shift(['foo'], state, { changeValue, getIn, setIn }) expect(returnValue).toBeUndefined() const op = changeValue.mock.calls[0][2] const result = op(undefined) @@ -92,7 +92,7 @@ describe('shift', () => { } } } - const returnValue = shift(['foo'], state, { changeValue }) + const returnValue = shift(['foo'], state, { changeValue, getIn, setIn }) expect(returnValue).toBe('a') expect(state.formState.values.foo).not.toBe(array) // copied expect(state).toEqual({ diff --git a/src/utils.js b/src/utils.js index 35c90cb..592f664 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,5 +2,4 @@ // From MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping export const escapeRegexTokens = (string: string): string => - string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string - + string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string