Skip to content

Commit e6e5abc

Browse files
add react
1 parent 0e6fbd1 commit e6e5abc

File tree

12 files changed

+2997
-5749
lines changed

12 files changed

+2997
-5749
lines changed

React/package-lock.json

Lines changed: 2643 additions & 5395 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

React/src/App.tsx

Lines changed: 99 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,106 @@
1-
import { useCallback, useState } from 'react';
2-
import './App.css';
31
import 'devextreme/dist/css/dx.material.blue.light.compact.css';
4-
import Button from 'devextreme-react/button';
2+
import DataGrid, {
3+
Editing, Column, Lookup, type DataGridTypes,
4+
} from 'devextreme-react/data-grid';
5+
import './App.css';
6+
import ArrayStore from 'devextreme/data/array_store';
7+
import { DataSource } from 'devextreme-react/common/data';
8+
import service, { type City, type Employee } from './data';
9+
import MultipleDropDownBox from './components/MultipleDropDownBox';
10+
11+
const dataSource: Employee[] = service.getEmployees();
12+
13+
const statesStore = new ArrayStore({
14+
data: service.getStates(),
15+
key: 'ID',
16+
});
17+
18+
const citiesStore = new ArrayStore({
19+
data: service.getCities(),
20+
key: 'ID',
21+
});
22+
23+
function getFilteredCities(cellInfo: DataGridTypes.ColumnEditCellTemplateData<Employee, number>, citiesStore: ArrayStore): DataSource {
24+
return new DataSource({
25+
store: citiesStore,
26+
filter: (data: City) => (cellInfo.data?.StateID && cellInfo.data?.StateID?.length > 0
27+
? cellInfo.data?.StateID.includes(data.StateID)
28+
: true),
29+
});
30+
}
31+
32+
async function setStateValue(this: DataGridTypes.Column<Employee, number>, rowData: Employee, value: number[], currentRowData: Employee): Promise<void> {
33+
rowData.CityID = [];
34+
await this.defaultSetCellValue?.(rowData, value, currentRowData);
35+
}
36+
37+
function arrayCellTemplate(container: HTMLElement, options: DataGridTypes.ColumnCellTemplateData<Employee, number>): void {
38+
const noBreakSpace = '\u00A0';
39+
const text = (options.value || [])
40+
.map((element: number) => options.column.lookup?.calculateCellValue?.(element) as string || '')
41+
.join(', ');
42+
container.textContent = text || noBreakSpace;
43+
container.title = text;
44+
}
45+
46+
function renderMultipleDropDownBox(
47+
currentValue: number[],
48+
// eslint-disable-next-line no-unused-vars
49+
setValue: (value: number[]) => void,
50+
dataSource: ArrayStore | DataSource,
51+
): JSX.Element {
52+
return (
53+
<MultipleDropDownBox
54+
dataSource={dataSource}
55+
value={currentValue}
56+
setValue={setValue}
57+
/>
58+
);
59+
}
60+
61+
function renderStateDropDownBox(e: DataGridTypes.ColumnEditCellTemplateData<Employee, number>): JSX.Element {
62+
const { setValue } = e;
63+
return renderMultipleDropDownBox(
64+
e.value,
65+
setValue,
66+
statesStore,
67+
);
68+
}
69+
70+
function renderCityDropDownBox(e: DataGridTypes.ColumnEditCellTemplateData<Employee, number>): JSX.Element {
71+
const { setValue } = e;
72+
return renderMultipleDropDownBox(
73+
e.value,
74+
setValue,
75+
getFilteredCities(e, citiesStore),
76+
);
77+
}
578

679
function App(): JSX.Element {
7-
var [count, setCount] = useState<number>(0);
8-
const clickHandler = useCallback(() => {
9-
setCount((prev) => prev + 1);
10-
}, [setCount]);
1180
return (
12-
<div className="main">
13-
<Button text={`Click count: ${count}`} onClick={clickHandler} />
81+
<div className="App">
82+
<DataGrid dataSource={dataSource}>
83+
<Editing
84+
mode="row"
85+
allowUpdating={true}
86+
allowAdding={true}>
87+
</Editing>
88+
<Column
89+
dataField="StateID"
90+
caption="State"
91+
setCellValue={setStateValue}
92+
cellTemplate={arrayCellTemplate}
93+
editCellRender={renderStateDropDownBox}>
94+
<Lookup dataSource={statesStore} displayExpr="Name" valueExpr="ID" />
95+
</Column>
96+
<Column
97+
dataField="CityID"
98+
caption="City"
99+
cellTemplate={arrayCellTemplate}
100+
editCellRender={renderCityDropDownBox}>
101+
<Lookup dataSource={citiesStore} displayExpr="Name" valueExpr="ID" />
102+
</Column>
103+
</DataGrid>
14104
</div>
15105
);
16106
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React, { useCallback } from 'react';
2+
import Button from 'devextreme-react/button';
3+
4+
type DropDownBoxAction =
5+
| { type: 'dropDownBoxValue'; data: number[] }
6+
| { type: 'selectedKeys'; data: number[] }
7+
| { type: 'openDropdown' };
8+
9+
interface DropDownBoxSaveProps {
10+
selectedKeys: number[];
11+
// eslint-disable-next-line no-unused-vars
12+
setCellValue: (value: number[]) => void;
13+
setState: React.Dispatch<DropDownBoxAction>;
14+
}
15+
16+
function DropDownBoxSave({ selectedKeys, setCellValue, setState }: DropDownBoxSaveProps): JSX.Element {
17+
const onClick = useCallback(() => {
18+
setState({ type: 'dropDownBoxValue', data: selectedKeys });
19+
setCellValue(selectedKeys);
20+
}, [selectedKeys, setCellValue, setState]);
21+
22+
return <Button text="Apply" onClick={onClick} />;
23+
}
24+
25+
export default DropDownBoxSave;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React, { useCallback, useMemo, useReducer } from 'react';
2+
import DataGrid, { Column, Selection, type DataGridTypes } from 'devextreme-react/data-grid';
3+
import DropDownBox from 'devextreme-react/drop-down-box';
4+
import type { ArrayStore, DataSource } from 'devextreme-react/common/data';
5+
import DropDownBoxSave from './DropDownBoxSave';
6+
7+
interface MultipleDropDownBoxProps {
8+
value: number[];
9+
dataSource: DataSource | ArrayStore;
10+
// eslint-disable-next-line no-unused-vars
11+
setValue: (newValue: number[]) => void;
12+
}
13+
14+
interface DropDownBoxState {
15+
selectedKeys: number[];
16+
currentValue: number[];
17+
isOpened: boolean;
18+
}
19+
20+
type DropDownBoxAction =
21+
| { type: 'dropDownBoxValue'; data: number[] }
22+
| { type: 'selectedKeys'; data: number[] }
23+
| { type: 'openDropdown' };
24+
25+
function reducer(state: DropDownBoxState, action: DropDownBoxAction): DropDownBoxState {
26+
switch (action.type) {
27+
case 'dropDownBoxValue':
28+
return { ...state, currentValue: action.data, isOpened: false };
29+
case 'selectedKeys':
30+
return { ...state, selectedKeys: action.data };
31+
case 'openDropdown':
32+
return { ...state, isOpened: true };
33+
default:
34+
return state;
35+
}
36+
}
37+
38+
function MultipleDropDownBox({ value, dataSource, setValue }: MultipleDropDownBoxProps): JSX.Element {
39+
const [{ selectedKeys, currentValue, isOpened }, dispatch] = useReducer(reducer, {
40+
selectedKeys: value,
41+
currentValue: value,
42+
isOpened: false,
43+
});
44+
45+
const onShowingHandler = useCallback(() => {
46+
dispatch({ type: 'openDropdown' });
47+
}, []);
48+
49+
const dropDownOpts = useMemo(() => ({
50+
onShowing: onShowingHandler,
51+
visible: isOpened,
52+
}), [isOpened]);
53+
54+
const onSelectionChanged = useCallback((args: DataGridTypes.SelectionChangedEvent): void => {
55+
const { selectedRowKeys } = args;
56+
dispatch({ type: 'selectedKeys', data: selectedRowKeys });
57+
}, []);
58+
59+
return (
60+
<DropDownBox
61+
dataSource={dataSource}
62+
value={currentValue}
63+
displayExpr="Name"
64+
valueExpr="ID"
65+
dropDownOptions={dropDownOpts}
66+
>
67+
<React.Fragment>
68+
<DataGrid
69+
dataSource={dataSource}
70+
selectedRowKeys={selectedKeys}
71+
hoverStateEnabled={true}
72+
height={250}
73+
onSelectionChanged={onSelectionChanged}
74+
>
75+
<Column dataField="ID" />
76+
<Column dataField="Name" />
77+
<Selection mode="multiple" />
78+
</DataGrid>
79+
<DropDownBoxSave
80+
selectedKeys={selectedKeys}
81+
setCellValue={setValue}
82+
setState={dispatch}
83+
/>
84+
</React.Fragment>
85+
</DropDownBox>
86+
);
87+
}
88+
89+
export default MultipleDropDownBox;

React/src/components/orig_DropDownBoxSave.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

React/src/components/orig_MultipleDropDownBox.js

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)