1+ import { useState , useMemo , useCallback } from 'react' ;
2+ import DataGrid , { Column , RowDragging , Scrolling , Lookup , Selection } from 'devextreme-react/data-grid' ;
3+ import dxDataGrid , { RowDraggingStartEvent , Column as DxColumn , RowDraggingAddEvent , Row } from 'devextreme/ui/data_grid' ;
4+ import { DragTemplateData } from 'devextreme/ui/draggable' ;
5+ import CustomStore from 'devextreme/data/custom_store' ;
6+ import { Task , priorities } from './data' ;
7+
8+ interface GridDemoComponentProps {
9+ status ?: number ;
10+ tasksStore ?: CustomStore ;
11+ shouldClearSelection : boolean ;
12+ }
13+
14+ function draggedItemsRender ( data : DragTemplateData ) {
15+ const draggedItems = data . itemData . map ( ( item : Task , rowIndex : number ) => {
16+ const cellValues = ( Object . keys ( item ) as ( keyof Task ) [ ] ) . map ( ( key : keyof Task , dataIndex : number ) =>
17+ < td key = { "key" + dataIndex } > { item [ key ] } </ td >
18+ ) ;
19+ return ( < tr key = { "row" + rowIndex } > { cellValues } </ tr > )
20+ } ) ;
21+ return ( < table className = "drag-container" >
22+ < tbody > { draggedItems } </ tbody >
23+ </ table > ) ;
24+ }
25+
26+ function getVisibleRowValues ( rowsData : Task [ ] , grid : dxDataGrid ) {
27+ const visibleColumns = grid . getVisibleColumns ( ) ;
28+ const selectedData = rowsData . map ( ( rowData : Task ) => {
29+ const visibleValues : any = { } ;
30+ visibleColumns . forEach ( ( column : DxColumn ) => {
31+ if ( column . dataField )
32+ visibleValues [ column . dataField ] = getVisibleCellValue ( column , rowData ) ;
33+ } ) ;
34+ return visibleValues ;
35+ } ) ;
36+ return selectedData ;
37+ }
38+
39+ function getVisibleCellValue ( column : DxColumn , rowData : Task ) {
40+ if ( column . dataField ) {
41+ const propKey = column . dataField as ( keyof Task ) ;
42+ const cellValue = rowData [ propKey ] ;
43+ return column . lookup && column . lookup . calculateCellValue ? column . lookup . calculateCellValue ( cellValue ) : cellValue ;
44+ }
45+ }
46+
47+ export default function Grid ( { status, tasksStore, shouldClearSelection } : GridDemoComponentProps ) {
48+ const [ updateInProgress , setUpdateInProgress ] = useState ( false ) ;
49+
50+ const filterExpr = useMemo ( ( ) => {
51+ return [ 'Status' , '=' , status ] ;
52+ } , [ status ] ) ;
53+
54+ const dataSource = useMemo ( ( ) => {
55+ return {
56+ store : tasksStore ,
57+ reshapeOnPush : true ,
58+ } ;
59+ } , [ tasksStore ] ) ;
60+
61+ const canDrag = useCallback ( ( e : RowDraggingStartEvent ) => {
62+ if ( updateInProgress ) return false ;
63+ const visibleRows = e . component . getVisibleRows ( ) ;
64+ return visibleRows . some ( ( r : Row ) => r . isSelected && r . rowIndex === e . fromIndex ) ;
65+ } , [ updateInProgress ] ) ;
66+
67+ const onDragStart = useCallback ( ( e : RowDraggingStartEvent ) => {
68+ const selectedData : Task [ ] = e . component . getSelectedRowsData ( ) ;
69+ e . itemData = getVisibleRowValues ( selectedData , e . component ) ;
70+ e . cancel = ! canDrag ( e ) ;
71+ } , [ canDrag ] ) ;
72+
73+ const onAdd = useCallback ( ( e : RowDraggingAddEvent ) => {
74+ const fromGrid = e . fromComponent as dxDataGrid ;
75+ const toGrid = e . toComponent as dxDataGrid ;
76+ const selectedRowKeys : ( keyof Task ) [ ] = fromGrid . getSelectedRowKeys ( ) ;
77+ const updateProcess : ( Promise < any > | undefined ) [ ] = [ ] ;
78+ const changes : any [ ] = [ ] ;
79+
80+ setUpdateInProgress ( true ) ;
81+ fromGrid . beginCustomLoading ( "Loading..." ) ;
82+ toGrid . beginCustomLoading ( "Loading..." ) ;
83+ for ( let key of selectedRowKeys ) {
84+ const values = { Status : e . toData } ;
85+ updateProcess . push ( tasksStore ?. update ( key , values ) ) ;
86+ changes . push ( {
87+ type : 'update' ,
88+ key,
89+ data : values ,
90+ } ) ;
91+ }
92+ Promise . all ( updateProcess ) . then ( ( ) => {
93+ tasksStore ?. push ( changes ) ;
94+ fromGrid . endCustomLoading ( ) ;
95+ toGrid . endCustomLoading ( ) ;
96+ setUpdateInProgress ( false ) ;
97+
98+ fromGrid . clearSelection ( ) ;
99+ if ( ! shouldClearSelection ) {
100+ toGrid . selectRows ( selectedRowKeys , true ) ;
101+ }
102+ } ) ;
103+ } , [ tasksStore , shouldClearSelection ] ) ;
104+
105+ return (
106+ < DataGrid
107+ dataSource = { dataSource }
108+ height = { 440 }
109+ showBorders = { true }
110+ filterValue = { filterExpr }
111+ >
112+ < RowDragging
113+ data = { status }
114+ group = "tasksGroup"
115+ onAdd = { onAdd }
116+ onDragStart = { onDragStart }
117+ dragRender = { draggedItemsRender }
118+ />
119+ < Selection mode = "multiple" />
120+ < Scrolling mode = "virtual" />
121+ < Column
122+ dataField = "Subject"
123+ dataType = "string"
124+ />
125+ < Column
126+ dataField = "Priority"
127+ dataType = "number"
128+ width = { 80 }
129+ >
130+ < Lookup
131+ dataSource = { priorities }
132+ valueExpr = "id"
133+ displayExpr = "text"
134+ />
135+ </ Column >
136+ < Column
137+ dataField = "Status"
138+ dataType = "number"
139+ visible = { false }
140+ />
141+
142+ </ DataGrid >
143+ ) ;
144+ } ;
0 commit comments