@@ -9,7 +9,9 @@ import React, { Component } from "react";
9
9
import PropTypes from "prop-types" ;
10
10
import { getIn , FieldArray } from "formik" ;
11
11
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" ;
13
15
import { FieldLabel } from "./FieldLabel" ;
14
16
15
17
export class ArrayField extends Component {
@@ -31,6 +33,32 @@ export class ArrayField extends Component {
31
33
return false ;
32
34
} ;
33
35
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
+
34
62
renderFormField = ( props ) => {
35
63
const {
36
64
form : { values, errors } ,
@@ -44,18 +72,21 @@ export class ArrayField extends Component {
44
72
label,
45
73
labelIcon,
46
74
helpText,
75
+ requiredOptions,
47
76
...uiProps
48
77
} = this . props ;
49
78
const hasError = this . hasGroupErrors ( errors ) ? { error : { } } : { } ;
50
79
const { nextKey } = this . state ;
80
+ const valuesToDisplay = this . getValues ( values , fieldPath ) ;
51
81
return (
52
82
< Form . Field { ...uiProps } { ...hasError } >
53
83
< FieldLabel htmlFor = { fieldPath } icon = { labelIcon } label = { label } />
54
84
55
- { getIn ( values , fieldPath , [ ] ) . map ( ( value , index , array ) => {
85
+ { valuesToDisplay . map ( ( value , index , array ) => {
56
86
const arrayPath = fieldPath ;
57
87
const indexPath = index ;
58
88
const key = value . __key || index ;
89
+
59
90
return (
60
91
< div key = { key } >
61
92
{ children ( {
@@ -64,6 +95,7 @@ export class ArrayField extends Component {
64
95
arrayPath,
65
96
indexPath,
66
97
key,
98
+ value,
67
99
...props ,
68
100
} ) }
69
101
</ div >
@@ -114,11 +146,15 @@ ArrayField.propTypes = {
114
146
helpText : PropTypes . oneOfType ( [ PropTypes . string , PropTypes . object ] ) ,
115
147
label : PropTypes . oneOfType ( [ PropTypes . string , PropTypes . object ] ) ,
116
148
labelIcon : PropTypes . string ,
149
+ requiredOptions : PropTypes . array ,
150
+ showEmptyValue : PropTypes . bool ,
117
151
} ;
118
152
119
153
ArrayField . defaultProps = {
120
154
addButtonLabel : "Add new row" ,
121
155
helpText : "" ,
122
156
label : "" ,
123
157
labelIcon : "" ,
158
+ requiredOptions : [ ] ,
159
+ showEmptyValue : false ,
124
160
} ;
0 commit comments