22< html >
33
44< head >
5- < meta charset ="UTF-8 " />
6- < meta name ="viewport " content ="width=device-width, initial-scale=1.0 " />
7- < title > Gridstack.js React integration example</ title >
8- < link rel ="stylesheet " href ="demo.css " />
9- < script src ="../dist/gridstack-all.js "> </ script >
10-
11- <!-- Scripts to use react inside html -->
12- < script src ="https://unpkg.com/react@16/umd/react.production.min.js "> </ script >
13- < script src ="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js "> </ script >
14- < script src ="https://unpkg.com/babel-standalone@6.15.0/babel.min.js "> </ script >
5+ < meta charset ="UTF-8 " />
6+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0 " />
7+ < title > Gridstack.js React integration example</ title >
8+ < link rel ="stylesheet " href ="demo.css " />
9+ < script src ="../dist/gridstack-all.js "> </ script >
10+
11+ <!-- Scripts to use react inside html -->
12+ < script src ="https://unpkg.com/react@16/umd/react.production.min.js "> </ script >
13+ < script src ="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js "> </ script >
14+ < script src ="https://unpkg.com/babel-standalone@6.15.0/babel.min.js "> </ script >
1515</ head >
1616
1717< body >
18-
19- < div >
20- < h2 > Controlled stack</ h2 >
21- < div id ="controlled-stack "> </ div >
22- </ div >
23-
18+ < div >
19+ < h2 > Controlled stack</ h2 >
20+ < div id ="controlled-stack "> </ div >
21+ </ div >
2422</ body >
2523
2624< script type ="text/babel ">
27- const { useState, useEffect, useLayoutEffect, createRef, useRef } = React
28-
29- const Item = ( { id } ) => < div > I am item: { id } </ div >
30-
31- //
32- // Controlled example
33- //
34- const ControlledStack = ( { items, addItem, removeItem, id } ) => {
35- const refs = useRef ( { } )
36- const gridRef = useRef ( )
37- refs . current = { }
38-
39- if ( Object . keys ( refs . current ) . length !== items . length ) {
40- items . forEach ( ( { id } ) => {
41- refs . current [ id ] = refs . current [ id ] || createRef ( )
42- } )
43- }
44-
45-
46- useLayoutEffect ( ( ) => {
47-
48- gridRef . current =
49- // gridRef.current ||
50- GridStack . init (
51- {
52- float : true ,
53- acceptWidgets : true ,
54- } ,
55- `.controlled-${ id } `
56- )
57-
58- const grid = gridRef . current
59-
60- grid . on ( 'removed' , ( e , el ) => {
61- const elId = Array . isArray ( el ) ? el [ el . length - 1 ] . id : el . id ;
62- removeItem ( elId . split ( ':' ) [ 1 ] )
63- } )
64-
65- grid . on ( 'dropped' , ( e , p , n ) => {
66- console . log ( 'dropped' , p , n )
67-
68- // Remove "placeholder" item
69- // Gridstack creates a DOM element for dropped items, those need to be removed
70- // as they are rendered by React
71- grid . getGridItems ( ) . forEach ( ( item ) => {
72- const ids = item . getAttribute ( 'gs-id' ) . split ( ':' )
73- if ( ids [ 0 ] !== id ) {
74- grid . removeWidget ( item , true , false ) ;
75- }
76- } ) ;
77- addItem ( { id : n . id . split ( ':' ) [ 1 ] , x : n . x , y : n . y , w : n . w , h : n . h } )
78- } )
79-
80- grid . batchUpdate ( )
81-
82-
83- items . forEach ( ( a ) => {
84- // remove existing widgets
85- if ( refs . current [ a . id ] && refs . current [ a . id ] . current ) {
86- grid . removeWidget ( refs . current [ a . id ] . current , false , false )
87- }
88-
89- grid . makeWidget ( refs . current [ a . id ] . current )
90- } )
91- grid . batchUpdate ( false )
92-
93-
94-
95- } , [ items ] )
96-
97- useEffect ( ( ) => {
98- return ( ) => {
99- // console.log('cleanup', id)
100- // gridRef.current.destroy(false, false)
101- // gridRef.current = null
102- }
103- } )
104-
105-
106-
107-
108- return (
109- < div style = { { width : '100%' } } >
110- < div className = { `grid-stack controlled-${ id } ` } >
111- { items . map ( ( item , i ) => {
112- // console.log('render', id, item.id)
113- return (
114- < div ref = { refs . current [ item . id ] } key = { `${ id } -${ item . id } ` } className = { 'grid-stack-item' } gs-id = { `${ id } :${ item . id } ` } gs-w = { item . w } gs-h = { item . h } gs-x = { item . x } gs-y = { item . y } >
115- < div className = "grid-stack-item-content" >
116- < Item { ...item } />
117- </ div >
118- </ div >
119- )
120- } ) }
121- </ div >
122- < code >
123- < pre > { JSON . stringify ( items , null , 2 ) } </ pre >
124- </ code >
125- </ div >
126- )
25+ const { useState, useEffect, useLayoutEffect, createRef, useRef } = React
26+ const Item = ( { id } ) => < div > I am item: { id } </ div >
27+
28+ //
29+ // Controlled example
30+ //
31+ const ControlledStack = ( { items, addItem, removeItem, id } ) => {
32+ const refs = useRef ( { } )
33+ const gridRef = useRef ( )
34+ refs . current = { }
35+
36+ if ( Object . keys ( refs . current ) . length !== items . length ) {
37+ items . forEach ( ( { id } ) => {
38+ refs . current [ id ] = refs . current [ id ] || createRef ( )
39+ } )
12740 }
12841
129- const ControlledExample = ( ) => {
130- const [ items1 , setItems1 ] = useState ( [ { id : 'item-1-1' , x : 0 , y : 0 , w : 2 , h : 2 } , { id : 'item-1-2' , x : 2 , y : 0 , w : 2 , h : 2 } ] )
131- const [ items2 , setItems2 ] = useState ( [ { id : 'item-2-1' , x : 0 , y : 0 , w : 1 , h : 1 } , { id : 'item-2-2' , x : 0 , y : 1 , w : 1 , h : 1 } , { id : 'item-2-3' , x : 1 , y : 0 , w : 1 , h : 1 } ] )
132-
133- return (
134- < div style = { {
135- display : 'flex'
136- } } >
137- < div style = { { display : 'flex' , width : '50%' } } >
138- < ControlledStack
139- id = 'gs1'
140- items = { items1 }
141- addItem = { ( item ) => {
142- setItems1 ( [ ...items1 , item ] )
143- } }
144- removeItem = { ( id ) => {
145- setItems1 ( items1 . filter ( i => i . id !== id ) )
146- } }
147- />
148- </ div >
149- < div style = { { display : 'flex' , width : '50%' } } >
150- < ControlledStack
151- id = 'gs2'
152- items = { items2 }
153- addItem = { ( item ) => {
154- setItems2 ( [ ...items2 , item ] )
155- } }
156- removeItem = { ( id ) => {
157- setItems2 ( items2 . filter ( i => i . id !== id ) )
158- } }
159- />
160-
161- </ div >
162-
163- </ div >
42+ useLayoutEffect ( ( ) => {
43+ gridRef . current =
44+ // gridRef.current ||
45+ GridStack . init (
46+ {
47+ float : true ,
48+ acceptWidgets : true ,
49+ } ,
50+ `.controlled-${ id } `
16451 )
165- }
166-
167-
168-
169- ReactDOM . render ( < ControlledExample /> , document . getElementById ( 'controlled-stack' ) )
170-
52+ const grid = gridRef . current
53+
54+ grid . on ( 'removed' , ( e , el ) => {
55+ const elId = Array . isArray ( el ) ? el [ el . length - 1 ] . id : el . id ;
56+ removeItem ( elId . split ( ':' ) [ 1 ] )
57+ } )
58+
59+ grid . on ( 'dropped' , ( e , p , n ) => {
60+ console . log ( 'dropped' , p , n )
61+ // Remove "placeholder" item
62+ // Gridstack creates a DOM element for dropped items, those need to be removed
63+ // as they are rendered by React
64+ grid . getGridItems ( ) . forEach ( ( item ) => {
65+ const ids = item . getAttribute ( 'gs-id' ) . split ( ':' )
66+ if ( ids [ 0 ] !== id ) {
67+ grid . removeWidget ( item , true , false ) ;
68+ }
69+ } ) ;
70+ addItem ( { id : n . id . split ( ':' ) [ 1 ] , x : n . x , y : n . y , w : n . w , h : n . h } )
71+ } )
72+
73+ grid . batchUpdate ( )
74+ items . forEach ( ( a ) => {
75+ // remove existing widgets
76+ if ( refs . current [ a . id ] && refs . current [ a . id ] . current ) {
77+ grid . removeWidget ( refs . current [ a . id ] . current , false , false )
78+ }
79+ grid . makeWidget ( refs . current [ a . id ] . current )
80+ } )
81+ grid . batchUpdate ( false )
82+
83+ } , [ items ] )
84+
85+ useEffect ( ( ) => {
86+ return ( ) => {
87+ // console.log('cleanup', id)
88+ // gridRef.current.destroy(false, false)
89+ // gridRef.current = null
90+ }
91+ } )
92+
93+ return (
94+ < div style = { { width : '100%' } } >
95+ < div className = { `grid-stack controlled-${ id } ` } >
96+ { items . map ( ( item , i ) => {
97+ // console.log('render', id, item.id)
98+ return (
99+ < div ref = { refs . current [ item . id ] } key = { `${ id } -${ item . id } ` } className = { 'grid-stack-item' } gs-id = { `${ id } :${ item . id } ` } gs-w = { item . w } gs-h = { item . h } gs-x = { item . x } gs-y = { item . y } >
100+ < div className = "grid-stack-item-content" >
101+ < Item { ...item } />
102+ </ div >
103+ </ div >
104+ )
105+ } ) }
106+ </ div >
107+ < code >
108+ < pre > { JSON . stringify ( items , null , 2 ) } </ pre >
109+ </ code >
110+ </ div >
111+ )
112+ }
113+
114+ const ControlledExample = ( ) => {
115+ const [ items1 , setItems1 ] = useState ( [ { id : 'item-1-1' , x : 0 , y : 0 , w : 2 , h : 2 } , { id : 'item-1-2' , x : 2 , y : 0 , w : 2 , h : 2 } ] )
116+ const [ items2 , setItems2 ] = useState ( [ { id : 'item-2-1' , x : 0 , y : 0 , w : 1 , h : 1 } , { id : 'item-2-2' , x : 0 , y : 1 , w : 1 , h : 1 } , { id : 'item-2-3' , x : 1 , y : 0 , w : 1 , h : 1 } ] )
117+
118+ return (
119+ < div style = { { display : 'flex' } } >
120+ < div style = { { display : 'flex' , width : '50%' } } >
121+ < ControlledStack
122+ id = 'gs1'
123+ items = { items1 }
124+ addItem = { ( item ) => {
125+ setItems1 ( [ ...items1 , item ] )
126+ } }
127+ removeItem = { ( id ) => {
128+ setItems1 ( items1 . filter ( i => i . id !== id ) )
129+ } }
130+ />
131+ </ div >
132+ < div style = { { display : 'flex' , width : '50%' } } >
133+ < ControlledStack
134+ id = 'gs2'
135+ items = { items2 }
136+ addItem = { ( item ) => {
137+ setItems2 ( [ ...items2 , item ] )
138+ } }
139+ removeItem = { ( id ) => {
140+ setItems2 ( items2 . filter ( i => i . id !== id ) )
141+ } }
142+ />
143+ </ div >
144+ </ div >
145+ )
146+ }
147+
148+ ReactDOM . render ( < ControlledExample /> , document . getElementById ( 'controlled-stack' ) )
171149</ script >
172-
173150</ html >
0 commit comments