1 | `reactabular-dnd` provides [React DnD](https://gaearon.github.io/react-dnd/) based helpers for Reactabular.
|
2 |
|
3 | **Example:**
|
4 |
|
5 | ```jsx
|
6 | /*
|
7 | import React from 'react';
|
8 | import { DragDropContext } from 'react-dnd';
|
9 | import HTML5Backend from 'react-dnd-html5-backend';
|
10 | import cloneDeep from 'lodash/cloneDeep';
|
11 | import findIndex from 'lodash/findIndex';
|
12 | import * as Table from 'reactabular-table';
|
13 | import * as dnd from 'reactabular-dnd';
|
14 | import * as resolve from 'table-resolver';
|
15 | */
|
16 |
|
17 | const rows = [
|
18 | {
|
19 | id: 1,
|
20 | name: {
|
21 | first: 'John',
|
22 | last: 'Johnson'
|
23 | },
|
24 | company: 'John Inc.',
|
25 | sentence: 'consequatur nihil minima corporis omnis nihil rem'
|
26 | },
|
27 | {
|
28 | id: 2,
|
29 | name: {
|
30 | first: 'Mike',
|
31 | last: 'Mikeson'
|
32 | },
|
33 | company: 'Mike Inc.',
|
34 | sentence: 'a sequi doloremque sed id quo voluptatem voluptatem ut voluptatibus'
|
35 | },
|
36 | {
|
37 | id: 3,
|
38 | name: {
|
39 | first: 'Jake',
|
40 | last: 'Jackson'
|
41 | },
|
42 | company: 'Jake Inc.',
|
43 | sentence: 'sed id quo voluptatem voluptatem ut voluptatibus'
|
44 | },
|
45 | {
|
46 | id: 4,
|
47 | name: {
|
48 | first: 'Don',
|
49 | last: 'Donson'
|
50 | },
|
51 | company: 'Don Inc.',
|
52 | sentence: 'voluptatem voluptatem ut voluptatibus'
|
53 | }
|
54 | ];
|
55 |
|
56 | class DragAndDropTable extends React.Component {
|
57 | constructor(props) {
|
58 | super(props);
|
59 |
|
60 | this.state = {
|
61 | columns: [
|
62 | {
|
63 | props: {
|
64 | style: {
|
65 | width: 100
|
66 | }
|
67 | },
|
68 | header: {
|
69 | label: 'Name',
|
70 | props: {
|
71 | label: 'Name',
|
72 | onMove: o => this.onMoveColumn(o)
|
73 | }
|
74 | },
|
75 | children: [
|
76 | {
|
77 | property: 'name.first',
|
78 | props: {
|
79 | style: {
|
80 | width: 50
|
81 | }
|
82 | },
|
83 | header: {
|
84 | label: 'First Name',
|
85 | props: {
|
86 | label: 'First Name',
|
87 | onMove: o => this.onMoveChildColumn(o)
|
88 | }
|
89 | }
|
90 | },
|
91 | {
|
92 | property: 'name.last',
|
93 | props: {
|
94 | style: {
|
95 | width: 50
|
96 | }
|
97 | },
|
98 | header: {
|
99 | label: 'Last Name',
|
100 | props: {
|
101 | label: 'Last Name',
|
102 | onMove: o => this.onMoveChildColumn(o)
|
103 | }
|
104 | }
|
105 | }
|
106 | ]
|
107 | },
|
108 | {
|
109 | property: 'company',
|
110 | props: {
|
111 | label: 'Company',
|
112 | style: {
|
113 | width: 100
|
114 | }
|
115 | },
|
116 | header: {
|
117 | label: 'Company',
|
118 | props: {
|
119 | onMove: o => this.onMoveColumn(o)
|
120 | }
|
121 | }
|
122 | },
|
123 | {
|
124 | property: 'sentence',
|
125 | props: {
|
126 | style: {
|
127 | width: 300
|
128 | }
|
129 | },
|
130 | header: {
|
131 | label: 'Sentence',
|
132 | props: {
|
133 | label: 'Sentence',
|
134 | onMove: o => this.onMoveColumn(o)
|
135 | }
|
136 | }
|
137 | }
|
138 | ],
|
139 | rows
|
140 | };
|
141 |
|
142 | this.onRow = this.onRow.bind(this);
|
143 | this.onMoveRow = this.onMoveRow.bind(this);
|
144 | this.onMoveColumn = this.onMoveColumn.bind(this);
|
145 | this.onMoveChildColumn = this.onMoveChildColumn.bind(this);
|
146 | }
|
147 | render() {
|
148 | const components = {
|
149 | header: {
|
150 | cell: dnd.Header
|
151 | },
|
152 | body: {
|
153 | row: dnd.Row
|
154 | }
|
155 | };
|
156 | const { columns, rows } = this.state;
|
157 | const resolvedColumns = resolve.columnChildren({ columns });
|
158 | const resolvedRows = resolve.resolve({
|
159 | columns: resolvedColumns,
|
160 | method: resolve.nested
|
161 | })(rows);
|
162 |
|
163 | return (
|
164 | <Table.Provider
|
165 | components={components}
|
166 | columns={resolvedColumns}
|
167 | >
|
168 | <Table.Header
|
169 | headerRows={resolve.headerRows({ columns })}
|
170 | />
|
171 |
|
172 | <Table.Body
|
173 | rows={resolvedRows}
|
174 | rowKey="id"
|
175 | onRow={this.onRow}
|
176 | />
|
177 | </Table.Provider>
|
178 | );
|
179 | }
|
180 | onRow(row) {
|
181 | return {
|
182 | rowId: row.id,
|
183 | onMove: this.onMoveRow
|
184 | };
|
185 | }
|
186 | onMoveRow({ sourceRowId, targetRowId }) {
|
187 | const rows = dnd.moveRows({
|
188 | sourceRowId,
|
189 | targetRowId
|
190 | })(this.state.rows);
|
191 |
|
192 | if (rows) {
|
193 | this.setState({ rows });
|
194 | }
|
195 | }
|
196 | onMoveColumn(labels) {
|
197 | const movedColumns = dnd.moveLabels(this.state.columns, labels);
|
198 |
|
199 | if (movedColumns) {
|
200 | // Retain widths to avoid flashing while drag and dropping.
|
201 | const source = movedColumns.source;
|
202 | const target = movedColumns.target;
|
203 | const sourceWidth = source.props.style && source.props.style.width;
|
204 | const targetWidth = target.props.style && target.props.style.width;
|
205 |
|
206 | source.props.style = {
|
207 | ...source.props.style,
|
208 | width: targetWidth
|
209 | };
|
210 | target.props.style = {
|
211 | ...target.props.style,
|
212 | width: sourceWidth
|
213 | };
|
214 |
|
215 | this.setState({
|
216 | columns: movedColumns.columns
|
217 | });
|
218 | }
|
219 | }
|
220 | onMoveChildColumn(labels) {
|
221 | const movedChildren = dnd.moveChildrenLabels(this.state.columns, labels);
|
222 |
|
223 | if (movedChildren) {
|
224 | const columns = cloneDeep(this.state.columns);
|
225 |
|
226 | columns[movedChildren.target].children = movedChildren.columns;
|
227 |
|
228 | // Here we assume children have the same width.
|
229 | this.setState({ columns });
|
230 | }
|
231 | }
|
232 | }
|
233 |
|
234 | // Set up drag and drop context
|
235 | //const DragAndDrop = DragDropContext(HTML5Backend)(DragAndDropTable);
|
236 |
|
237 | <DragAndDropTable />
|
238 | ```
|