Skip to content

Commit 44b2d25

Browse files
Merge ColumnDrageReorder pull-request
facebookarchive/fixed-data-table#361
2 parents ac404ef + 76f99e0 commit 44b2d25

11 files changed

+548
-8
lines changed

.eslintrc.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"extends": "eslint:recommended",
3+
"env": {
4+
"browser": true,
5+
"node": true,
6+
"amd": true,
7+
"commonjs": true,
8+
"es6": true
9+
},
10+
"globals": {
11+
},
12+
"parser": "babel-eslint",
13+
"parserOptions": {
14+
"ecmaVersion": 6,
15+
"ecmaFeatures": {
16+
"jsx": true,
17+
"experimentalObjectRestSpread": true
18+
},
19+
"plugins": [
20+
"react"
21+
]
22+
},
23+
"rules": {
24+
"no-unused-vars": 0,
25+
"eqeqeq": 2,
26+
"quotes": [1, "single"],
27+
"no-console": 1,
28+
"dot-location": [1, "property"],
29+
"no-caller": 2,
30+
"no-fallthrough": 2,
31+
"no-floating-decimal": 1,
32+
"no-loop-func": 0,
33+
"no-new-func": 2,
34+
"no-sequences": 1,
35+
"no-throw-literal": 2,
36+
"no-label-var": 2,
37+
"no-shadow-restricted-names": 2,
38+
"no-shadow": 2,
39+
"no-use-before-define": 2,
40+
41+
"comma-dangle": 0,
42+
"no-lonely-if": 1,
43+
"no-nested-ternary": 2,
44+
"no-unneeded-ternary": 1,
45+
"no-trailing-spaces": 1,
46+
"semi": 2
47+
}
48+
}

examples/ReorderExample.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/**
2+
* This file provided by Facebook is for non-commercial testing and evaluation
3+
* purposes only. Facebook reserves all rights not expressly granted.
4+
*
5+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
7+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
8+
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
9+
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
10+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11+
*/
12+
13+
"use strict";
14+
15+
var FakeObjectDataListStore = require('./helpers/FakeObjectDataListStore');
16+
var FixedDataTable = require('fixed-data-table');
17+
var React = require('react');
18+
19+
const {Table, Column, Cell} = FixedDataTable;
20+
21+
const TextCell = ({rowIndex, data, columnKey, ...props}) => (
22+
<Cell {...props}>
23+
{data.getObjectAt(rowIndex)[columnKey]}
24+
</Cell>
25+
);
26+
27+
var columnTitles = {
28+
'firstName': 'First Name',
29+
'lastName': 'Last Name',
30+
'sentence': 'Sentence',
31+
'companyName': 'Company'
32+
};
33+
34+
var columnWidths = {
35+
firstName: 150,
36+
lastName: 150,
37+
sentence: 240,
38+
companyName: 100,
39+
};
40+
41+
class ReorderExample extends React.Component {
42+
constructor(props) {
43+
super(props);
44+
45+
this.state = {
46+
dataList: new FakeObjectDataListStore(1000000),
47+
columnOrder: [
48+
'firstName',
49+
'lastName',
50+
'sentence',
51+
'companyName'
52+
],
53+
};
54+
55+
this._onColumnReorderEndCallback = this._onColumnReorderEndCallback.bind(this);
56+
}
57+
58+
_onColumnReorderEndCallback(event) {
59+
console.log(event);
60+
var columnOrder = this.state.columnOrder.filter((columnKey) => {
61+
return columnKey !== event.reorderColumn;
62+
});
63+
if (event.columnAfter) {
64+
var index = columnOrder.indexOf(event.columnAfter);
65+
columnOrder.splice(index, 0, event.reorderColumn);
66+
} else {
67+
columnOrder.push(event.reorderColumn);
68+
}
69+
this.setState({
70+
columnOrder: columnOrder
71+
});
72+
}
73+
74+
render() {
75+
var {dataList} = this.state;
76+
77+
return (
78+
<Table
79+
rowHeight={30}
80+
headerHeight={50}
81+
rowsCount={dataList.getSize()}
82+
onColumnReorderEndCallback={this._onColumnReorderEndCallback}
83+
isColumnReordering={false}
84+
width={1000}
85+
height={500}
86+
{...this.props}>
87+
{this.state.columnOrder.map(function (columnKey, i) {
88+
return <Column
89+
columnKey={columnKey}
90+
key={i}
91+
header={<Cell>{columnTitles[columnKey]}</Cell>}
92+
cell={<TextCell data={dataList} />}
93+
fixed={i === 0}
94+
width={columnWidths[columnKey]}
95+
/>;
96+
})}
97+
</Table>
98+
);
99+
}
100+
}
101+
102+
module.exports = ReorderExample;

site/Constants.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ exports.ExamplePages = {
4646
title: 'Resizable columns',
4747
description: 'Table with drag and drop column resizing and a dummy "store" for persistence. The Last Name column demonstrates the ability to constrain to both a min- and max-width.',
4848
},
49+
REORDER_EXAMPLE: {
50+
location: 'example-reorder.html',
51+
file: EXAMPLES_LOCATION_BASE + 'ReorderExample.js',
52+
title: 'Reorderable columns',
53+
description: 'Table with drag and drop column reordering and a dummy "store" for persistence.',
54+
},
4955
COLUMN_GROUPS_EXAMPLE: {
5056
location: 'example-column-groups.html',
5157
file: EXAMPLES_LOCATION_BASE + 'ColumnGroupsExample.js',

site/examples/ExamplesPage.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ require('fixed-data-table/css/layout/fixedDataTableRowLayout.css');
2222
require('fixed-data-table/css/style/fixedDataTable.css');
2323
require('fixed-data-table/css/style/fixedDataTableCell.css');
2424
require('fixed-data-table/css/style/fixedDataTableColumnResizerLine.css');
25+
require('fixed-data-table/css/style/fixedDataTableColumnReorder.css');
2526
require('fixed-data-table/css/style/fixedDataTableRow.css');
2627
require('fixed-data-table/css/style/Scrollbar.css');
2728

@@ -36,6 +37,7 @@ var ExamplePages = Constants.ExamplePages;
3637
var EXAMPLE_COMPONENTS = {
3738
[ExamplePages.OBJECT_DATA_EXAMPLE.location]: require('../../examples/ObjectDataExample'),
3839
[ExamplePages.RESIZE_EXAMPLE.location]: require('../../examples/ResizeExample'),
40+
[ExamplePages.REORDER_EXAMPLE.location]: require('../../examples/ReorderExample'),
3941
[ExamplePages.FLEXGROW_EXAMPLE.location]: require('../../examples/FlexGrowExample'),
4042
[ExamplePages.COLUMN_GROUPS_EXAMPLE.location]: require('../../examples/ColumnGroupsExample'),
4143
[ExamplePages.FILTER_EXAMPLE.location]: require('../../examples/FilterExample'),

src/FixedDataTable.react.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,31 @@ var FixedDataTable = React.createClass({
260260
*/
261261
onColumnResizeEndCallback: PropTypes.func,
262262

263+
/**
264+
* Callback that is called when reordering has been completed
265+
* and columns need to be updated.
266+
*
267+
* ```
268+
* function(
269+
* event {
270+
* columnBefore: string|undefined, // the column before the new location of this one
271+
* columnAfter: string|undefined, // the column after the new location of this one
272+
* reorderColumn: string, // the column key that was just reordered
273+
* }
274+
* )
275+
* ```
276+
*/
277+
onColumnReorderEndCallback: PropTypes.func,
278+
263279
/**
264280
* Whether a column is currently being resized.
265281
*/
266282
isColumnResizing: PropTypes.bool,
283+
284+
/**
285+
* Whether columns are currently being reordered.
286+
*/
287+
isColumnReordering: PropTypes.bool,
267288
},
268289

269290
getDefaultProps() /*object*/ {
@@ -408,6 +429,8 @@ var FixedDataTable = React.createClass({
408429
var state = this.state;
409430
var props = this.props;
410431

432+
var onColumnReorder = props.onColumnReorderEndCallback ? this._onColumnReorder : null;
433+
411434
var groupHeader;
412435
if (state.useGroupHeader) {
413436
groupHeader = (
@@ -427,6 +450,8 @@ var FixedDataTable = React.createClass({
427450
fixedColumns={state.groupHeaderFixedColumns}
428451
scrollableColumns={state.groupHeaderScrollableColumns}
429452
onColumnResize={this._onColumnResize}
453+
onColumnReorder={onColumnReorder}
454+
onColumnReorderMove={this._onColumnReorderMove}
430455
/>
431456
);
432457
}
@@ -537,6 +562,11 @@ var FixedDataTable = React.createClass({
537562
fixedColumns={state.headFixedColumns}
538563
scrollableColumns={state.headScrollableColumns}
539564
onColumnResize={this._onColumnResize}
565+
onColumnReorder={onColumnReorder}
566+
onColumnReorderMove={this._onColumnReorderMove}
567+
onColumnReorderEnd={this._onColumnReorderEnd}
568+
isColumnReordering={!!state.isColumnReordering}
569+
columnReorderingData={state.columnReorderingData}
540570
/>;
541571

542572
var topShadow;
@@ -654,6 +684,56 @@ var FixedDataTable = React.createClass({
654684
});
655685
},
656686

687+
_onColumnReorder(
688+
/*string*/ columnKey,
689+
/*number*/ width,
690+
/*number*/ left,
691+
/*object*/ event
692+
) {
693+
this.setState({
694+
isColumnReordering: true,
695+
columnReorderingData: {
696+
dragDistance: 0,
697+
columnKey: columnKey,
698+
columnWidth: width,
699+
originalLeft: left,
700+
columnsBefore: [],
701+
columnsAfter: []
702+
}
703+
});
704+
},
705+
706+
_onColumnReorderMove(
707+
/*number*/ deltaX
708+
) {
709+
var reorderingData = this.state.columnReorderingData;
710+
reorderingData.dragDistance = deltaX;
711+
reorderingData.columnBefore = undefined;
712+
reorderingData.columnAfter = undefined;
713+
714+
this.setState({
715+
columnReorderingData: reorderingData
716+
});
717+
},
718+
719+
_onColumnReorderEnd(
720+
/*object*/ props,
721+
/*object*/ event
722+
) {
723+
724+
var columnBefore = this.state.columnReorderingData.columnBefore;
725+
var columnAfter = this.state.columnReorderingData.columnAfter;
726+
var reorderColumn = this.state.columnReorderingData.columnKey;
727+
728+
this.setState({
729+
isReordering: false,
730+
columnReorderingData: {}
731+
});
732+
this.props.onColumnReorderEndCallback({
733+
columnBefore, columnAfter, reorderColumn
734+
});
735+
},
736+
657737
_areColumnSettingsIdentical(
658738
oldColumns: Array,
659739
newColumns: Array

0 commit comments

Comments
 (0)