1 | /*
|
2 | EXPERIMENTAL
|
3 |
|
4 | const sameContents = (arrayA, arrayB) => arrayA === arrayB || (arrayA.length === arrayB.length && arrayA.every((valueA, index) => valueA === arrayB[ index ]))
|
5 |
|
6 | const generate = (field, tree = {}, values = {}, path = '', createField, createArray) => {
|
7 | const [ all, key, rest ] = /([^.]+)\.?(.+)?/.exec(field) // eslint-disable-line no-unused-vars
|
8 | if (/.+\[\]/.test(key)) {
|
9 | // is array key
|
10 | const noBrackets = key.substring(0, key.length - 2)
|
11 | const valuesArray = values[ noBrackets ]
|
12 | if (valuesArray && !Array.isArray(valuesArray)) {
|
13 | throw new Error(`Expected array value for ${path}${field}, but found ${typeof array}: ${JSON.stringify(valuesArray)}`)
|
14 | }
|
15 | const treeArray = tree[ noBrackets ] || []
|
16 | const results = []
|
17 | if (valuesArray) {
|
18 | if (rest) {
|
19 | valuesArray.forEach((value, index) => {
|
20 | results[ index ] = generate(rest, treeArray[ index ], value, `${path}${noBrackets}[${index}].`, createField, createArray)
|
21 | })
|
22 | } else {
|
23 | valuesArray.forEach((value, index) => {
|
24 | const fieldKey = `${path}${noBrackets}[${index}]`
|
25 | results[ index ] = !treeArray[ index ] || treeArray[ index ].key !== fieldKey ?
|
26 | createField(fieldKey) : treeArray[ index ]
|
27 | })
|
28 | }
|
29 | }
|
30 | const arrayKey = `${path}${noBrackets}`
|
31 | if (!tree[ noBrackets ] || !sameContents(treeArray, results) || treeArray.key !== arrayKey) {
|
32 | return {
|
33 | ...tree,
|
34 | [noBrackets]: createArray(arrayKey, results)
|
35 | }
|
36 | }
|
37 | } else if (rest) {
|
38 | // need to recurse
|
39 | const result = generate(rest, tree[ key ], values[ key ], `${path}${key}.`, createField, createArray)
|
40 | if (!tree[ key ] || tree[ key ] !== result) {
|
41 | return {
|
42 | ...tree,
|
43 | [key]: result
|
44 | }
|
45 | }
|
46 | } else {
|
47 | // value key
|
48 | const fieldKey = `${path}${key}`
|
49 | const existing = tree[ key ]
|
50 | if (!existing || existing.key !== fieldKey) {
|
51 | return {
|
52 | ...tree,
|
53 | [key]: createField(fieldKey)
|
54 | }
|
55 | }
|
56 | }
|
57 | return tree
|
58 | }
|
59 | */
|
60 |
|
61 | /**
|
62 | * Generates a tree of field objects
|
63 | *
|
64 | * @param fields The fields array passed to redux-form
|
65 | * @param tree The existing field tree
|
66 | * @param values The form values from the Redux store
|
67 | * @param createField A callback to create a field object
|
68 | * @param createArray A callback to create a field array
|
69 | */
|
70 |
|
71 | /*
|
72 | EXPERIMENTAL
|
73 |
|
74 | const generateFields = (fields = [], tree = {}, values, createField, createArray) =>
|
75 | fields.reduce((accumulator, field) =>
|
76 | generate(field, accumulator, values, undefined, createField, createArray),
|
77 | tree)
|
78 |
|
79 | export default generateFields
|
80 | */
|
81 | ; |
\ | No newline at end of file |