Skip to content

Commit 9d79b71

Browse files
spacebaboonn1k0
authored andcommitted
Fix behaviour of arrays with minItems and default (rjsf-team#663)
Fix bug whereby defaults in an array were munged together and added to extra item's formData. Behaviour now is to fill the array with the object level default array, and then add extra items up to minItems. These extra items will be either empty or the item-level default. Added demonstration of this in the Arrays tab of the playground.
1 parent bfcc32e commit 9d79b71

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

playground/samples/arrays.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ module.exports = {
5757
$ref: "#/definitions/Thing",
5858
},
5959
},
60+
defaultsAndMinItems: {
61+
type: "array",
62+
title: "List and item level defaults",
63+
minItems: 5,
64+
default: ["carp", "trout", "bream"],
65+
items: {
66+
type: "string",
67+
default: "unidentified",
68+
},
69+
},
6070
nestedList: {
6171
type: "array",
6272
title: "Nested list",

src/utils.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,19 @@ function computeDefaults(schema, parentDefaults, definitions = {}) {
141141
case "array":
142142
if (schema.minItems) {
143143
if (!isMultiSelect(schema, definitions)) {
144-
return new Array(schema.minItems).fill(
145-
computeDefaults(schema.items, defaults, definitions)
146-
);
144+
const defaultsLength = defaults ? defaults.length : 0;
145+
if (schema.minItems > defaultsLength) {
146+
const defaultEntries = defaults || [];
147+
// populate the array with the defaults
148+
const fillerEntries = new Array(
149+
schema.minItems - defaultsLength
150+
).fill(
151+
computeDefaults(schema.items, schema.items.defaults, definitions)
152+
);
153+
// then fill up the rest with either the item default or empty, up to minItems
154+
155+
return defaultEntries.concat(fillerEntries);
156+
}
147157
} else {
148158
return [];
149159
}

test/ArrayField_test.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,76 @@ describe("ArrayField", () => {
410410
expect(inputs[1].value).eql("Default name");
411411
});
412412

413+
it("should render an input for each default value, even when this is greater than minItems", () => {
414+
const schema = {
415+
type: "object",
416+
properties: {
417+
turtles: {
418+
type: "array",
419+
minItems: 2,
420+
default: ["Raphael", "Michaelangelo", "Donatello", "Leonardo"],
421+
items: {
422+
type: "string",
423+
},
424+
},
425+
},
426+
};
427+
const { node } = createFormComponent({ schema: schema });
428+
const inputs = node.querySelectorAll("input[type=text]");
429+
expect(inputs.length).to.eql(4);
430+
expect(inputs[0].value).to.eql("Raphael");
431+
expect(inputs[1].value).to.eql("Michaelangelo");
432+
expect(inputs[2].value).to.eql("Donatello");
433+
expect(inputs[3].value).to.eql("Leonardo");
434+
});
435+
436+
it("should render enough input to match minItems, populating the first with default values, and the rest empty", () => {
437+
const schema = {
438+
type: "object",
439+
properties: {
440+
turtles: {
441+
type: "array",
442+
minItems: 4,
443+
default: ["Raphael", "Michaelangelo"],
444+
items: {
445+
type: "string",
446+
},
447+
},
448+
},
449+
};
450+
const { node } = createFormComponent({ schema });
451+
const inputs = node.querySelectorAll("input[type=text]");
452+
expect(inputs.length).to.eql(4);
453+
expect(inputs[0].value).to.eql("Raphael");
454+
expect(inputs[1].value).to.eql("Michaelangelo");
455+
expect(inputs[2].value).to.eql("");
456+
expect(inputs[3].value).to.eql("");
457+
});
458+
459+
it("should render enough input to match minItems, populating the first with default values, and the rest with the item default", () => {
460+
const schema = {
461+
type: "object",
462+
properties: {
463+
turtles: {
464+
type: "array",
465+
minItems: 4,
466+
default: ["Raphael", "Michaelangelo"],
467+
items: {
468+
type: "string",
469+
default: "Unknown",
470+
},
471+
},
472+
},
473+
};
474+
const { node } = createFormComponent({ schema });
475+
const inputs = node.querySelectorAll("input[type=text]");
476+
expect(inputs.length).to.eql(4);
477+
expect(inputs[0].value).to.eql("Raphael");
478+
expect(inputs[1].value).to.eql("Michaelangelo");
479+
expect(inputs[2].value).to.eql("Unknown");
480+
expect(inputs[3].value).to.eql("Unknown");
481+
});
482+
413483
it("should not add minItems extra formData entries when schema item is a multiselect", () => {
414484
const schema = {
415485
type: "object",

0 commit comments

Comments
 (0)