|
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