Merge pull request #461 from antonvialibri1/fix-for-array-checkboxes-… · final-form/final-form@b905214

2 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -45,6 +45,7 @@ const stringToPath = (string) => {

4545

};

4646
4747

const keysCache: { [string]: string[] } = {};

48+

const keysRegex = /[.[\]]+/;

4849
4950

const toPath = (key: string): string[] => {

5051

if (key === null || key === undefined || !key.length) {

@@ -54,7 +55,26 @@ const toPath = (key: string): string[] => {

5455

throw new Error("toPath() expects a string");

5556

}

5657

if (keysCache[key] == null) {

57-

keysCache[key] = stringToPath(key);

58+

/**

59+

* The following patch fixes issue 456, introduced since v4.20.3:

60+

*

61+

* Before v4.20.3, i.e. in v4.20.2, a `key` like 'choices[]' would map to ['choices']

62+

* (e.g. an array of choices used where 'choices[]' is name attribute of an input of type checkbox).

63+

*

64+

* Since v4.20.3, a `key` like 'choices[]' would map to ['choices', ''] which is wrong and breaks

65+

* this kind of inputs e.g. in React.

66+

*

67+

* v4.20.3 introduced an unwanted breaking change, this patch fixes it, see the issue at the link below.

68+

*

69+

* @see https://github.com/final-form/final-form/issues/456

70+

*/

71+

if (key.endsWith("[]")) {

72+

// v4.20.2 (a `key` like 'choices[]' should map to ['choices'], which is fine).

73+

keysCache[key] = key.split(keysRegex).filter(Boolean);

74+

} else {

75+

// v4.20.3 (a `key` like 'choices[]' maps to ['choices', ''], which breaks applications relying on inputs like `<input type="checkbox" name="choices[]" />`).

76+

keysCache[key] = stringToPath(key);

77+

}

5878

}

5979

return keysCache[key];

6080

};

Original file line numberDiff line numberDiff line change

@@ -38,7 +38,13 @@ describe("structure.toPath", () => {

3838

"cow",

3939

]);

4040

});

41+
4142

it("should support string properties that are not valid JS identifiers", () => {

4243

expect(toPath('foo["bar.baz\\"["]')).toEqual(["foo", 'bar.baz"[']);

4344

});

45+
46+

it("should be retrocompatible with v4.20.2 where key names like 'choices[]' and 'options[]' map to ['choices'] and ['options'] instead of ['choices', ''] and ['options', ''] as introduced by v4.20.3 (unwanted breaking change)", () => {

47+

expect(toPath("choices[]")).toEqual(["choices"]);

48+

expect(toPath("options[]")).toEqual(["options"]);

49+

});

4450

});