1+ <!DOCTYPE html>
2+ < html >
3+
4+ < 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-h5.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 >
15+ </ head >
16+
17+ < body >
18+ < div >
19+ < h1 > Using GridStack.js with React hooks</ h1 >
20+ < p >
21+ As with any virtualDOM-based framework, you need to check if Reacthas rendered the DOM (or any updates to it)
22+ < strong > before</ strong > you initialize GridStack or call its methods. This example shows how to make rendered
23+ components widgets:
24+ </ p >
25+ < ol >
26+ < li > Render items, each with a reference</ li >
27+ < li > Convert each rendered item to a widget using the reference and the < a
28+ href ="https://github.com/gridstack/gridstack.js/tree/develop/doc#makewidgetel ">
29+ makeWidget</ a > function</ li >
30+ </ ol >
31+ </ div >
32+ < div >
33+ < h2 > Controlled stack</ h2 >
34+ < div id ="controlled-stack "> </ div >
35+ </ div >
36+ < div >
37+ < h2 > Uncontrolled stack</ h2 >
38+ < div id ="uncontrolled-stack "> </ div >
39+ </ div >
40+ </ body >
41+
42+ < script type ="text/babel ">
43+ const { useState, useEffect, createRef, useRef } = React
44+
45+ const Item = ( { id } ) => < div > I am item: { id } </ div >
46+
47+ //
48+ // Controlled example
49+ //
50+
51+ const ControlledStack = ( { items, addItem } ) => {
52+ const refs = useRef ( { } )
53+ const gridRef = useRef ( )
54+
55+ if ( Object . keys ( refs . current ) . length !== items . length ) {
56+ items . forEach ( ( { id } ) => {
57+ refs . current [ id ] = refs . current [ id ] || createRef ( )
58+ } )
59+ }
60+
61+ useEffect ( ( ) => {
62+ gridRef . current =
63+ gridRef . current ||
64+ GridStack . init (
65+ {
66+ float : true ,
67+ } ,
68+ '.controlled'
69+ )
70+ const grid = gridRef . current
71+ grid . batchUpdate ( )
72+ grid . removeAll ( false )
73+ items . forEach ( ( { id } ) => grid . makeWidget ( refs . current [ id ] . current ) )
74+ grid . commit ( )
75+ } , [ items ] )
76+
77+ return (
78+ < div >
79+ < button onClick = { addItem } > Add new widget</ button >
80+ < div className = { `grid-stack controlled` } >
81+ { items . map ( ( item , i ) => {
82+ return (
83+ < div ref = { refs . current [ item . id ] } key = { item . id } className = { 'grid-stack-item' } >
84+ < div className = "grid-stack-item-content" >
85+ < Item { ...item } />
86+ </ div >
87+ </ div >
88+ )
89+ } ) }
90+ </ div >
91+ </ div >
92+ )
93+ }
94+
95+ const ControlledExample = ( ) => {
96+ const [ items , setItems ] = useState ( [ { id : 'item-1' } , { id : 'item-2' } ] )
97+
98+ return (
99+ < ControlledStack
100+ items = { items }
101+ addItem = { ( ) => setItems ( [ ...items , { id : `item-${ items . length + 1 } ` } ] ) }
102+ />
103+ )
104+ }
105+
106+ //
107+ // Uncontrolled example
108+ //
109+
110+ const UncontrolledExample = ( ) => {
111+ const gridRef = useRef ( )
112+
113+ const [ state , setState ] = useState ( {
114+ count : 0 ,
115+ info : '' ,
116+ items : [
117+ { x : 2 , y : 1 , h : 2 } ,
118+ { x : 2 , y : 4 , w : 3 } ,
119+ { x : 4 , y : 2 } ,
120+ { x : 3 , y : 1 , h : 2 } ,
121+ { x : 0 , y : 6 , w : 2 , h : 2 } ,
122+ ] ,
123+ } )
124+
125+ useEffect ( ( ) => {
126+ gridRef . current =
127+ gridRef . current ||
128+ GridStack . init (
129+ {
130+ float : true ,
131+ cellHeight : '70px' ,
132+ minRow : 1 ,
133+ } ,
134+ '.uncontrolled'
135+ )
136+
137+ const grid = gridRef . current
138+
139+ grid . on ( 'dragstop' , ( event , element ) => {
140+ const node = element . gridstackNode
141+ setState ( prevState => ( {
142+ ...prevState ,
143+ info : `you just dragged node #${ node . id } to ${ node . x } ,${ node . y } – good job!` ,
144+ } ) )
145+
146+ let timerId
147+ window . clearTimeout ( timerId )
148+ timerId = window . setTimeout ( ( ) => {
149+ setState ( prevState => ( {
150+ ...prevState ,
151+ info : '' ,
152+ } ) )
153+ } , 2000 )
154+ } )
155+ } , [ ] )
156+
157+ return (
158+ < div >
159+ < button
160+ onClick = { ( ) => {
161+ const grid = gridRef . current
162+ const node = state . items [ state . count ] || {
163+ x : Math . round ( 12 * Math . random ( ) ) ,
164+ y : Math . round ( 5 * Math . random ( ) ) ,
165+ w : Math . round ( 1 + 3 * Math . random ( ) ) ,
166+ h : Math . round ( 1 + 3 * Math . random ( ) ) ,
167+ }
168+ node . id = node . content = String ( state . count )
169+ setState ( prevState => ( {
170+ ...prevState ,
171+ count : prevState . count + 1 ,
172+ } ) )
173+ grid . addWidget ( node )
174+ } }
175+ >
176+ Add Widget
177+ </ button >
178+ < div > { JSON . stringify ( state ) } </ div >
179+ < section class = "grid-stack uncontrolled" > </ section >
180+ </ div >
181+ )
182+ }
183+
184+ ReactDOM . render ( < ControlledExample /> , document . getElementById ( 'controlled-stack' ) )
185+ ReactDOM . render ( < UncontrolledExample /> , document . getElementById ( 'uncontrolled-stack' ) )
186+
187+ </ script >
188+
189+ </ html >
0 commit comments