Skip to content

Commit 3539d33

Browse files
authored
Merge pull request #2148 from dprokop/dprokop/multi-grid-react
Demo - multiple react grids example
2 parents e19628f + 8553ced commit 3539d33

File tree

2 files changed

+178
-1
lines changed

2 files changed

+178
-1
lines changed

demo/index.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
<!DOCTYPE html>
22
<html>
3+
34
<head>
45
<meta charset="utf-8">
56
<title>Demo</title>
67
</head>
8+
79
<body>
810
<h1>Demos</h1>
911
<ul>
@@ -18,6 +20,7 @@ <h1>Demos</h1>
1820
<li><a href="nested_advanced.html">Nested Advanced grids</a></li>
1921
<li><a href="offset.html">Offset parent</a></li>
2022
<li><a href="react-hooks.html">ReactJS (Hooks)</a></li>
23+
<li><a href="react-hooks-controlled-multiple.html">ReactJS (Hooks), mulitple, controlled</a></li>
2124
<li><a href="react.html">ReactJS</a></li>
2225
<li><a href="responsive.html">Responsive</a></li>
2326
<li><a href="right-to-left(rtl).html">Right-To-Left (RTL)</a></li>
@@ -49,4 +52,5 @@ <h1>Old v5.1.1 Jquery Demos</h1>
4952
<li><a href="old_nested-jq.html">Nested grids</a></li>
5053
</ul>
5154
</body>
52-
</html>
55+
56+
</html>
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
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-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>
15+
</head>
16+
17+
<body>
18+
19+
<div>
20+
<h2>Controlled stack</h2>
21+
<div id="controlled-stack"></div>
22+
</div>
23+
24+
</body>
25+
26+
<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+
)
127+
}
128+
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 >
164+
)
165+
}
166+
167+
168+
169+
ReactDOM.render(<ControlledExample />, document.getElementById('controlled-stack'))
170+
171+
</script>
172+
173+
</html>

0 commit comments

Comments
 (0)