|
1 | 1 | // @flow |
2 | 2 | import type { MutableState, Mutator, Tools } from 'final-form' |
3 | 3 |
|
| 4 | +const countBelow = (array, value) => |
| 5 | + array.reduce((count, item) => (item < value ? count + 1 : count), 0) |
| 6 | + |
4 | 7 | const removeBatch: Mutator = ( |
5 | 8 | [name, indexes]: any[], |
6 | 9 | state: MutableState, |
7 | 10 | { changeValue }: Tools |
8 | 11 | ) => { |
| 12 | + const sortedIndexes: number[] = [...indexes] |
| 13 | + sortedIndexes.sort() |
| 14 | + // remove duplicates |
| 15 | + for (let i = 0; i < sortedIndexes.length; i++) { |
| 16 | + if (i > 0 && sortedIndexes[i] === sortedIndexes[i - 1]) { |
| 17 | + sortedIndexes.splice(i--, 1) |
| 18 | + } |
| 19 | + } |
| 20 | + |
| 21 | + let returnValue = [] |
9 | 22 | changeValue( |
10 | 23 | state, |
11 | 24 | name, |
12 | 25 | (array: ?(any[])): ?(any[]) => { |
13 | | - if (!array || !indexes) { |
| 26 | + // use original order of indexes for return value |
| 27 | + returnValue = indexes.map(index => array && array[index]) |
| 28 | + if (!array || !sortedIndexes.length) { |
14 | 29 | return array |
15 | 30 | } |
16 | 31 |
|
17 | | - let mask = new Array(indexes.length) |
18 | | - for (let i = 0; i < indexes.length; i++) { |
19 | | - mask[indexes[i]] = true |
20 | | - } |
| 32 | + const copy = [...array] |
| 33 | + const removed = [] |
| 34 | + sortedIndexes.forEach((index: number) => { |
| 35 | + copy.splice(index - removed.length, 1) |
| 36 | + removed.push(array && array[index]) |
| 37 | + }) |
| 38 | + return copy |
| 39 | + } |
| 40 | + ) |
21 | 41 |
|
22 | | - let offset = 0 |
23 | | - for (let i = 0; i < array.length; i++) { |
24 | | - if (mask[i] === undefined) { |
25 | | - array[offset] = array[i] |
26 | | - offset++ |
27 | | - } |
| 42 | + // now we have to remove any subfields for our indexes, |
| 43 | + // and decrement all higher indexes. |
| 44 | + const pattern = new RegExp(`^${name}\\[(\\d+)\\](.*)`) |
| 45 | + const newFields = {} |
| 46 | + Object.keys(state.fields).forEach(key => { |
| 47 | + const tokens = pattern.exec(key) |
| 48 | + if (tokens) { |
| 49 | + const fieldIndex = Number(tokens[1]) |
| 50 | + if (!~sortedIndexes.indexOf(fieldIndex)) { |
| 51 | + // not one of the removed indexes |
| 52 | + // shift all higher ones down |
| 53 | + const decrementedKey = `${name}[${fieldIndex - |
| 54 | + countBelow(sortedIndexes, fieldIndex)}]${tokens[2]}` |
| 55 | + newFields[decrementedKey] = state.fields[key] |
| 56 | + newFields[decrementedKey].name = decrementedKey |
28 | 57 | } |
29 | | - |
30 | | - array.length = offset |
31 | | - return array |
| 58 | + } else { |
| 59 | + newFields[key] = state.fields[key] |
32 | 60 | } |
33 | | - ) |
| 61 | + }) |
| 62 | + state.fields = newFields |
| 63 | + return returnValue |
34 | 64 | } |
35 | 65 |
|
36 | 66 | export default removeBatch |
0 commit comments