1- import { getBlankData , getSyncedData } from './data ' ;
1+ import React from 'react ' ;
22import { getArrayFormRow , getObjectFormRow } from './ui' ;
33import { EditorContext } from './util' ;
4+ import EditorState from './editorState' ;
45
56
6- export default class Form extends React . Component {
7- constructor ( props ) {
8- super ( props ) ;
9-
10- this . dataInput = document . getElementById ( this . props . dataInputId ) ;
11- this . schema = props . schema ;
12-
13- let data = props . data ;
14-
15- if ( ! data ) {
16- // create empty data from schema
17- data = getBlankData ( this . schema , this . getRef ) ;
18- } else {
19- // data might be stale if schema has new keys, so add them to data
20- try {
21- data = getSyncedData ( data , this . schema , this . getRef ) ;
22- } catch ( error ) {
23- console . error ( "Error: Schema and data structure don't match" ) ;
24- console . error ( error ) ;
25- }
26- }
27-
28- this . state = {
29- value : '' ,
30- data : data
31- } ;
32-
33- // update data in the input
34- this . populateDataInput ( ) ;
35- }
36-
37- componentDidUpdate ( prevProps , prevState ) {
38- if ( this . state . data !== prevState . data ) {
39- this . populateDataInput ( ) ;
40- }
41- }
42-
43- populateDataInput = ( ) => {
44- this . dataInput . value = JSON . stringify ( this . state . data ) ;
45- }
46-
7+ export default class ReactJSONForm extends React . Component {
478 handleChange = ( coords , value ) => {
489 /*
4910 e.target.name is a chain of indices and keys:
@@ -57,50 +18,25 @@ export default class Form extends React.Component {
5718
5819 coords . shift ( ) ; // remove first coord
5920
60- function setDataUsingCoords ( coords , data , value ) {
61- let coord = coords . shift ( ) ;
62- if ( ! isNaN ( Number ( coord ) ) )
63- coord = Number ( coord ) ;
21+ // :TODO: use immutable JS instead of JSON-ising the data
22+ let data = setDataUsingCoords ( coords , JSON . parse ( JSON . stringify ( this . props . editorState . getData ( ) ) ) , value ) ;
6423
65- if ( coords . length ) {
66- setDataUsingCoords ( coords , data [ coord ] , value ) ;
67- } else {
68- data [ coord ] = value ;
69- }
70- }
71-
72- let _data = JSON . parse ( JSON . stringify ( this . state . data ) ) ;
73-
74- setDataUsingCoords ( coords , _data , value ) ;
75-
76- this . setState ( { data : _data } ) ;
24+ this . props . onChange ( EditorState . update ( this . props . editorState , data ) ) ;
7725 }
7826
7927 getRef = ( ref ) => {
8028 /* Returns schema reference. Nothing to do with React's refs.*/
8129
82- let refSchema ;
83- let tokens = ref . split ( '/' ) ;
84-
85- for ( let i = 0 ; i < tokens . length ; i ++ ) {
86- let token = tokens [ i ] ;
87-
88- if ( token === '#' )
89- refSchema = this . schema ;
90- else
91- refSchema = refSchema [ token ] ;
92- }
93-
94-
95- return { ...refSchema } ;
30+ return EditorState . getRef ( ref , this . props . editorState . getSchema ( ) ) ;
9631 }
9732
9833 getFields = ( ) => {
99- let data = this . state . data ;
34+ let data = this . props . editorState . getData ( ) ;
35+ let schema = this . props . editorState . getSchema ( ) ;
10036 let formGroups = [ ] ;
10137
10238 try {
103- let type = this . schema . type ;
39+ let type = schema . type ;
10440
10541 if ( type === 'list' )
10642 type = 'array' ;
@@ -109,11 +45,12 @@ export default class Form extends React.Component {
10945
11046 let args = {
11147 data : data ,
112- schema : this . schema ,
48+ schema : schema ,
11349 name : 'rjf' ,
11450 onChange : this . handleChange ,
11551 onAdd : this . addFieldset ,
11652 onRemove : this . removeFieldset ,
53+ onEdit : this . editFieldset ,
11754 onMove : this . moveFieldset ,
11855 level : 0 ,
11956 getRef : this . getRef ,
@@ -125,6 +62,8 @@ export default class Form extends React.Component {
12562 return getObjectFormRow ( args ) ;
12663 }
12764 } catch ( error ) {
65+ console . log ( error ) ;
66+
12867 formGroups = (
12968 < p style = { { color : '#f00' } } >
13069 < strong > (!) Error:</ strong > Schema and data structure do not match.
@@ -139,26 +78,40 @@ export default class Form extends React.Component {
13978 coords = coords . split ( '-' ) ;
14079 coords . shift ( ) ;
14180
142- this . setState ( ( state ) => {
143- let _data = JSON . parse ( JSON . stringify ( state . data ) ) ;
81+ // :TODO: use immutable JS instead of JSON-ising the data
82+ let data = addDataUsingCoords ( coords , JSON . parse ( JSON . stringify ( this . props . editorState . getData ( ) ) ) , blankData ) ;
14483
145- addDataUsingCoords ( coords , _data , blankData ) ;
146-
147- return { data : _data } ;
148- } ) ;
84+ this . props . onChange ( EditorState . update ( this . props . editorState , data ) ) ;
14985 }
15086
15187 removeFieldset = ( coords ) => {
15288 coords = coords . split ( '-' ) ;
15389 coords . shift ( ) ;
90+
91+ // :TODO: use immutable JS instead of JSON-ising the data
92+ let data = removeDataUsingCoords ( coords , JSON . parse ( JSON . stringify ( this . props . editorState . getData ( ) ) ) ) ;
93+
94+ this . props . onChange ( EditorState . update ( this . props . editorState , data ) ) ;
95+ }
96+
97+ editFieldset = ( value , newCoords , oldCoords ) => {
98+ /* Add and remove in a single state update
99+
100+ newCoords will be added
101+ oldCoords willbe removed
102+ */
103+
104+ newCoords = newCoords . split ( '-' ) ;
105+ newCoords . shift ( ) ;
106+
107+ oldCoords = oldCoords . split ( '-' ) ;
108+ oldCoords . shift ( ) ;
154109
155- this . setState ( ( state ) => {
156- let _data = JSON . parse ( JSON . stringify ( state . data ) ) ;
110+ let data = addDataUsingCoords ( newCoords , JSON . parse ( JSON . stringify ( this . props . editorState . getData ( ) ) ) , value ) ;
157111
158- removeDataUsingCoords ( coords , _data ) ;
112+ data = removeDataUsingCoords ( oldCoords , data ) ;
159113
160- return { data : _data } ;
161- } ) ;
114+ this . props . onChange ( EditorState . update ( this . props . editorState , data ) ) ;
162115 }
163116
164117 moveFieldset = ( oldCoords , newCoords ) => {
@@ -168,13 +121,10 @@ export default class Form extends React.Component {
168121 newCoords = newCoords . split ( "-" ) ;
169122 newCoords . shift ( ) ;
170123
171- this . setState ( ( state ) => {
172- let _data = JSON . parse ( JSON . stringify ( state . data ) ) ;
173-
174- moveDataUsingCoords ( oldCoords , newCoords , _data ) ;
124+ // :TODO: use immutable JS instead of JSON-ising the data
125+ let data = moveDataUsingCoords ( oldCoords , newCoords , JSON . parse ( JSON . stringify ( this . props . editorState . getData ( ) ) ) ) ;
175126
176- return { data : _data } ;
177- } ) ;
127+ this . props . onChange ( EditorState . update ( this . props . editorState , data ) ) ;
178128 }
179129
180130 render ( ) {
@@ -196,26 +146,44 @@ export default class Form extends React.Component {
196146 }
197147}
198148
149+ function setDataUsingCoords ( coords , data , value ) {
150+ let coord = coords . shift ( ) ;
151+
152+ if ( ! isNaN ( Number ( coord ) ) )
153+ coord = Number ( coord ) ;
154+
155+ if ( coords . length ) {
156+ data [ coord ] = setDataUsingCoords ( coords , data [ coord ] , value ) ;
157+ } else {
158+ if ( coord === undefined ) // top level array with multiselect widget
159+ data = value ;
160+ else
161+ data [ coord ] = value ;
162+ }
163+
164+ return data ;
165+ }
199166
200167function addDataUsingCoords ( coords , data , value ) {
201168 let coord = coords . shift ( ) ;
202169 if ( ! isNaN ( Number ( coord ) ) )
203170 coord = Number ( coord ) ;
204171
205172 if ( coords . length ) {
206- addDataUsingCoords ( coords , data [ coord ] , value ) ;
173+ data [ coord ] = addDataUsingCoords ( coords , data [ coord ] , value ) ;
207174 } else {
208175 if ( Array . isArray ( data [ coord ] ) ) {
209176 data [ coord ] . push ( value ) ;
210- }
211- else {
177+ } else {
212178 if ( Array . isArray ( data ) ) {
213179 data . push ( value ) ;
214180 } else {
215181 data [ coord ] = value ;
216182 }
217183 }
218184 }
185+
186+ return data ;
219187}
220188
221189function removeDataUsingCoords ( coords , data ) {
@@ -231,6 +199,8 @@ function removeDataUsingCoords(coords, data) {
231199 else
232200 delete data [ coord ] ;
233201 }
202+
203+ return data ;
234204}
235205
236206
@@ -257,4 +227,6 @@ function moveDataUsingCoords(oldCoords, newCoords, data) {
257227 data . splice ( newCoord , 0 , item ) ;
258228 }
259229 }
230+
231+ return data ;
260232}
0 commit comments