@@ -3,6 +3,8 @@ import React, { Component, PropTypes } from "react";
33import {
44 getDefaultFormState ,
55 isMultiSelect ,
6+ isFixedItems ,
7+ allowAdditionalItems ,
68 optionsList ,
79 retrieveSchema ,
810 toIdSchema ,
@@ -59,8 +61,12 @@ class ArrayField extends Component {
5961 const { items} = this . state ;
6062 const { schema, registry} = this . props ;
6163 const { definitions} = registry ;
64+ let itemSchema = schema . items ;
65+ if ( isFixedItems ( schema ) && allowAdditionalItems ( schema ) ) {
66+ itemSchema = schema . additionalItems ;
67+ }
6268 this . asyncSetState ( {
63- items : items . concat ( [ getDefaultFormState ( schema . items , undefined , definitions ) ] )
69+ items : items . concat ( [ getDefaultFormState ( itemSchema , undefined , definitions ) ] )
6470 } , { validate : false } ) ;
6571 } ;
6672
@@ -88,25 +94,22 @@ class ArrayField extends Component {
8894 } ;
8995
9096 render ( ) {
97+ const { schema} = this . props ;
98+ if ( isFixedItems ( schema ) ) {
99+ return this . renderFixedArray ( ) ;
100+ }
101+ if ( isMultiSelect ( schema ) ) {
102+ return this . renderMultiSelect ( ) ;
103+ }
104+ return this . renderNormalArray ( ) ;
105+ }
106+
107+ renderNormalArray ( ) {
91108 const { schema, uiSchema, errorSchema, idSchema, name} = this . props ;
92109 const title = schema . title || name ;
93110 const { items} = this . state ;
94- const { fields, definitions} = this . props . registry ;
95- const { SchemaField} = fields ;
111+ const { definitions} = this . props . registry ;
96112 const itemsSchema = retrieveSchema ( schema . items , definitions ) ;
97- if ( isMultiSelect ( schema ) ) {
98- return (
99- < SelectWidget
100- id = { idSchema && idSchema . id }
101- multiple
102- onChange = { this . onSelectChange }
103- options = { optionsList ( itemsSchema ) }
104- schema = { schema }
105- title = { title }
106- value = { items }
107- />
108- ) ;
109- }
110113
111114 return (
112115 < fieldset
@@ -119,37 +122,138 @@ class ArrayField extends Component {
119122 const itemErrorSchema = errorSchema ? errorSchema [ index ] : undefined ;
120123 const itemIdPrefix = idSchema . id + "_" + index ;
121124 const itemIdSchema = toIdSchema ( itemsSchema , itemIdPrefix , definitions ) ;
122- return (
123- < div key = { index } >
124- < div className = "col-xs-10" >
125- < SchemaField
126- schema = { itemsSchema }
127- uiSchema = { uiSchema . items }
128- formData = { items [ index ] }
129- errorSchema = { itemErrorSchema }
130- idSchema = { itemIdSchema }
131- required = { this . isItemRequired ( itemsSchema ) }
132- onChange = { this . onChangeForIndex ( index ) }
133- registry = { this . props . registry } />
134- </ div >
135- < div className = "col-xs-2 array-item-remove text-right" >
136- < button type = "button" className = "btn btn-danger col-xs-12"
137- tabIndex = "-1"
138- onClick = { this . onDropIndexClick ( index ) } > Delete</ button >
139- </ div >
140- </ div >
141- ) ;
125+ return this . renderArrayFieldItem ( {
126+ index,
127+ itemSchema : itemsSchema ,
128+ itemIdSchema,
129+ itemErrorSchema,
130+ itemData : items [ index ] ,
131+ itemUiSchema : uiSchema . items
132+ } ) ;
142133 } )
143134 } </ div >
144- < div className = "row" >
145- < p className = "col-xs-2 col-xs-offset-10 array-item-add text-right" >
146- < button type = "button" className = "btn btn-info col-xs-12"
147- tabIndex = "-1" onClick = { this . onAddClick } > Add</ button >
148- </ p >
149- </ div >
135+ < AddButton onClick = { this . onAddClick } />
150136 </ fieldset >
151137 ) ;
152138 }
139+
140+ renderMultiSelect ( ) {
141+ const { schema, idSchema, name} = this . props ;
142+ const title = schema . title || name ;
143+ const { items} = this . state ;
144+ const { definitions} = this . props . registry ;
145+ const itemsSchema = retrieveSchema ( schema . items , definitions ) ;
146+ return (
147+ < SelectWidget
148+ id = { idSchema && idSchema . id }
149+ multiple
150+ onChange = { this . onSelectChange }
151+ options = { optionsList ( itemsSchema ) }
152+ schema = { schema }
153+ title = { title }
154+ value = { items }
155+ />
156+ ) ;
157+ }
158+
159+ renderFixedArray ( ) {
160+ const { schema, uiSchema, errorSchema, idSchema, name} = this . props ;
161+ const title = schema . title || name ;
162+ let { items} = this . state ;
163+ const { definitions} = this . props . registry ;
164+ const itemSchemas = schema . items . map ( item =>
165+ retrieveSchema ( item , definitions ) ) ;
166+ const additionalSchema = allowAdditionalItems ( schema ) ?
167+ retrieveSchema ( schema . additionalItems , definitions ) : null ;
168+
169+ if ( ! items || items . length < itemSchemas . length ) {
170+ // to make sure at least all fixed items are generated
171+ items = items || [ ] ;
172+ items = items . concat ( new Array ( itemSchemas . length - items . length ) ) ;
173+ }
174+
175+ return (
176+ < fieldset className = "field field-array field-array-fixed-items" >
177+ { title ? < legend > { title } </ legend > : null }
178+ { schema . description ?
179+ < div className = "field-description" > { schema . description } </ div > : null }
180+ < div className = "row array-item-list" > {
181+ items . map ( ( item , index ) => {
182+ const additional = index >= itemSchemas . length ;
183+ const itemSchema = additional ?
184+ additionalSchema : itemSchemas [ index ] ;
185+ const itemIdPrefix = idSchema . id + "_" + index ;
186+ const itemIdSchema = toIdSchema ( itemSchema , itemIdPrefix , definitions ) ;
187+ const itemUiSchema = additional ?
188+ uiSchema . additionalItems || { } :
189+ Array . isArray ( uiSchema . items ) ?
190+ uiSchema . items [ index ] : uiSchema . items || { } ;
191+ const itemErrorSchema = errorSchema ? errorSchema [ index ] : undefined ;
192+
193+ return this . renderArrayFieldItem ( {
194+ index,
195+ removable : additional ,
196+ itemSchema,
197+ itemData : item ,
198+ itemUiSchema,
199+ itemIdSchema,
200+ itemErrorSchema
201+ } ) ;
202+ } )
203+ } </ div >
204+ {
205+ additionalSchema ? < AddButton onClick = { this . onAddClick } /> : null
206+ }
207+ </ fieldset >
208+ ) ;
209+ }
210+
211+ renderArrayFieldItem ( {
212+ index,
213+ removable= true ,
214+ itemSchema,
215+ itemData,
216+ itemUiSchema,
217+ itemIdSchema,
218+ itemErrorSchema
219+ } ) {
220+ const { SchemaField} = this . props . registry . fields ;
221+ return (
222+ < div key = { index } >
223+ < div className = { removable ? "col-xs-10" : "col-xs-12" } >
224+ < SchemaField
225+ schema = { itemSchema }
226+ uiSchema = { itemUiSchema }
227+ formData = { itemData }
228+ errorSchema = { itemErrorSchema }
229+ idSchema = { itemIdSchema }
230+ required = { this . isItemRequired ( itemSchema ) }
231+ onChange = { this . onChangeForIndex ( index ) }
232+ registry = { this . props . registry } />
233+ </ div >
234+ {
235+ removable ?
236+ < div className = "col-xs-2 array-item-remove text-right" >
237+ < button type = "button" className = "btn btn-danger col-xs-12"
238+ tabIndex = "-1"
239+ onClick = { this . onDropIndexClick ( index ) } > Delete</ button >
240+ </ div >
241+ : null
242+ }
243+ </ div >
244+ ) ;
245+ }
246+ }
247+
248+ function AddButton ( { onClick} ) {
249+ return (
250+ < div className = "row" >
251+ < p className = "col-xs-2 col-xs-offset-10 array-item-add text-right" >
252+ < button type = "button" className = "btn btn-info col-xs-12"
253+ tabIndex = "-1" onClick = { onClick } > Add</ button >
254+ </ p >
255+ </ div >
256+ ) ;
153257}
154258
155259if ( process . env . NODE_ENV !== "production" ) {
0 commit comments