Skip to content

Commit d66bbf0

Browse files
jrcastro2kpsherva
authored andcommitted
arrayfield: add required options
* closes zenodo/who-rdm#4
1 parent 07e287a commit d66bbf0

File tree

1 file changed

+38
-2
lines changed

1 file changed

+38
-2
lines changed

src/lib/forms/ArrayField.js

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import React, { Component } from "react";
99
import PropTypes from "prop-types";
1010
import { getIn, FieldArray } from "formik";
1111
import { Form, Icon } from "semantic-ui-react";
12-
12+
import _isEmpty from "lodash/isEmpty";
13+
import _filter from "lodash/filter";
14+
import _matches from "lodash/matches";
1315
import { FieldLabel } from "./FieldLabel";
1416

1517
export class ArrayField extends Component {
@@ -31,6 +33,32 @@ export class ArrayField extends Component {
3133
return false;
3234
};
3335

36+
/**
37+
* Returns the array of values to display, it checks for required options and adds empty rows with the required values prefilled
38+
* @param {Array} values The array of values
39+
* @param {String} fieldPath The path of the field
40+
* @returns An array of values to display
41+
*/
42+
getValues = (values, fieldPath) => {
43+
const { requiredOptions, defaultNewValue, showEmptyValue } = this.props;
44+
const existingValues = getIn(values, fieldPath, []);
45+
46+
if (_isEmpty(requiredOptions) && _isEmpty(existingValues) && showEmptyValue) {
47+
existingValues.push({ __key: existingValues.length, ...defaultNewValue });
48+
}
49+
50+
for (const requiredOption of requiredOptions) {
51+
const valuesMatchingRequiredOption = _filter(
52+
existingValues,
53+
_matches(requiredOption)
54+
);
55+
if (valuesMatchingRequiredOption.length === 0) {
56+
existingValues.push({ __key: existingValues.length, ...requiredOption });
57+
}
58+
}
59+
return existingValues;
60+
};
61+
3462
renderFormField = (props) => {
3563
const {
3664
form: { values, errors },
@@ -44,18 +72,21 @@ export class ArrayField extends Component {
4472
label,
4573
labelIcon,
4674
helpText,
75+
requiredOptions,
4776
...uiProps
4877
} = this.props;
4978
const hasError = this.hasGroupErrors(errors) ? { error: {} } : {};
5079
const { nextKey } = this.state;
80+
const valuesToDisplay = this.getValues(values, fieldPath);
5181
return (
5282
<Form.Field {...uiProps} {...hasError}>
5383
<FieldLabel htmlFor={fieldPath} icon={labelIcon} label={label} />
5484

55-
{getIn(values, fieldPath, []).map((value, index, array) => {
85+
{valuesToDisplay.map((value, index, array) => {
5686
const arrayPath = fieldPath;
5787
const indexPath = index;
5888
const key = value.__key || index;
89+
5990
return (
6091
<div key={key}>
6192
{children({
@@ -64,6 +95,7 @@ export class ArrayField extends Component {
6495
arrayPath,
6596
indexPath,
6697
key,
98+
value,
6799
...props,
68100
})}
69101
</div>
@@ -114,11 +146,15 @@ ArrayField.propTypes = {
114146
helpText: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
115147
label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
116148
labelIcon: PropTypes.string,
149+
requiredOptions: PropTypes.array,
150+
showEmptyValue: PropTypes.bool,
117151
};
118152

119153
ArrayField.defaultProps = {
120154
addButtonLabel: "Add new row",
121155
helpText: "",
122156
label: "",
123157
labelIcon: "",
158+
requiredOptions: [],
159+
showEmptyValue: false,
124160
};

0 commit comments

Comments
 (0)