Skip to content

Commit 8fbc8b5

Browse files
author
Mariela Tihova
authored
refactor: Custom Context Menu sample update for 19 (#786)
1 parent e3b36e8 commit 8fbc8b5

1 file changed

Lines changed: 142 additions & 122 deletions

File tree

  • samples/grids/grid/custom-context-menu/src
Lines changed: 142 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,159 @@
1-
import React, { useEffect, useRef, useState } from 'react';
2-
import ReactDOM from 'react-dom/client';
3-
import './index.css';
1+
import React, { useEffect, useRef, useState } from "react";
2+
import ReactDOM from "react-dom/client";
3+
import "./index.css";
44

5-
import { IgrGridBaseDirective, IgrGridContextMenuEventArgs, IgrGridModule } from 'igniteui-react-grids';
6-
import { IgrGrid, IgrColumn } from 'igniteui-react-grids';
7-
import { NwindData } from './NwindData';
5+
import {
6+
IgrGridContextMenuEventArgs
7+
} from "igniteui-react-grids";
8+
import { IgrGrid, IgrColumn } from "igniteui-react-grids";
9+
import { NwindData } from "./NwindData";
810

9-
import 'igniteui-react-grids/grids/combined';
10-
import 'igniteui-react-grids/grids/themes/light/bootstrap.css';
11-
import { IgrIcon } from 'igniteui-react';
11+
import "igniteui-react-grids/grids/combined";
12+
import "igniteui-react-grids/grids/themes/light/bootstrap.css";
13+
import { IgrIcon } from "igniteui-react";
14+
import { registerIconFromText } from "igniteui-webcomponents";
1215

13-
const mods: any[] = [
14-
IgrGridModule
15-
];
16-
mods.forEach((m) => m.register());
1716
const icon = `<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48"><path d="M180-81q-24 0-42-18t-18-42v-603h60v603h474v60H180Zm120-120q-24 0-42-18t-18-42v-560q0-24 18-42t42-18h440q24 0 42 18t18 42v560q0 24-18 42t-42 18H300Zm0-60h440v-560H300v560Zm0 0v-560 560Z"/></svg>`;
1817

1918
export default function App() {
20-
const [clickedCell, setClickedCell] = useState(null);
21-
const [isCellWithinRange, setIsCellWithinRange] = useState(false);
22-
const [selectedData, setSelectedData] = useState('');
23-
const gridRef = useRef<IgrGrid>(null);
24-
const iconRef = useRef<IgrIcon>(null);
25-
const contextMenuRef = useRef(null);
26-
const northWindData = new NwindData();
19+
const [clickedCell, setClickedCell] = useState(null);
20+
const [isCellWithinRange, setIsCellWithinRange] = useState(false);
21+
const [selectedData, setSelectedData] = useState("");
22+
const gridRef = useRef<IgrGrid>(null);
23+
const iconRef = useRef<IgrIcon>(null);
24+
const contextMenuRef = useRef(null);
25+
const northWindData = new NwindData();
2726

28-
useEffect(() => {
29-
if (iconRef.current) {
30-
iconRef.current.registerIconFromText('content_copy', icon, 'material');
27+
useEffect(() => {
28+
registerIconFromText("content_copy", icon, "material");
29+
}, []);
30+
31+
const rightClick = (event: IgrGridContextMenuEventArgs) => {
32+
const eventArgs = event.detail;
33+
eventArgs.event.preventDefault();
34+
const node = eventArgs.cell.cellID;
35+
const isCellWithinRange = gridRef.current
36+
.getSelectedRanges()
37+
.some((range: any) => {
38+
if (
39+
node.columnID >= range.columnStart &&
40+
node.columnID <= range.columnEnd &&
41+
node.rowIndex >= range.rowStart &&
42+
node.rowIndex <= range.rowEnd
43+
) {
44+
return true;
3145
}
32-
}, [])
46+
return false;
47+
});
48+
setIsCellWithinRange(isCellWithinRange);
49+
setClickedCell(eventArgs.cell);
50+
openContextMenu(eventArgs.event.clientX, eventArgs.event.clientY);
51+
};
52+
53+
const openContextMenu = (x: number, y: number) => {
54+
contextMenuRef.current.style.left = x + "px";
55+
contextMenuRef.current.style.top = y + "px";
56+
contextMenuRef.current.style.display = "";
57+
};
3358

34-
function rightClick(grid: IgrGridBaseDirective, event: IgrGridContextMenuEventArgs) {
35-
const eventArgs = event.detail;
36-
eventArgs.event.preventDefault();
37-
const node = eventArgs.cell.cellID;
38-
const isCellWithinRange = grid.getSelectedRanges().some((range: any) => {
39-
if (node.columnID >= range.columnStart &&
40-
node.columnID <= range.columnEnd &&
41-
node.rowIndex >= range.rowStart &&
42-
node.rowIndex <= range.rowEnd
43-
) {
44-
return true;
45-
}
46-
return false;
47-
});
48-
setIsCellWithinRange(isCellWithinRange);
49-
setClickedCell(eventArgs.cell);
50-
openContextMenu(eventArgs.event.clientX, eventArgs.event.clientY)
51-
}
59+
const closeContextMenu = () => {
60+
contextMenuRef.current.style.display = "none";
61+
};
5262

53-
function openContextMenu(x: number, y: number) {
54-
contextMenuRef.current.style.left = x + 'px';
55-
contextMenuRef.current.style.top = y + 'px';
56-
contextMenuRef.current.style.display = "";
57-
}
63+
const copySelectedRowData = () => {
64+
const selectedData = gridRef.current.getRowData(clickedCell.cellID.rowID);
65+
copyData(selectedData);
66+
closeContextMenu();
67+
};
5868

59-
function closeContextMenu() {
60-
contextMenuRef.current.style.display = "none";
61-
}
69+
const copySelectedCellData = () => {
70+
const selectedData = clickedCell.value;
71+
copyData(selectedData);
72+
closeContextMenu();
73+
};
6274

63-
function copySelectedRowData() {
64-
const selectedData = gridRef.current.getRowData(clickedCell.cellID.rowID);
65-
copyData(selectedData);
66-
closeContextMenu();
67-
}
68-
69-
function copySelectedCellData() {
70-
const selectedData = clickedCell.value;
71-
copyData(selectedData);
72-
closeContextMenu();
73-
}
74-
75-
function copySelectedData() {
76-
const selectedData = gridRef.current.getSelectedData(null,null);
77-
copyData(selectedData);
78-
closeContextMenu();
79-
}
80-
81-
function copyData(data: any[]) {
82-
const tempElement = document.createElement('input');
83-
document.body.appendChild(tempElement);
84-
tempElement.setAttribute('id', 'temp_id');
85-
(document.getElementById('temp_id') as HTMLInputElement).value = JSON.stringify(data);
86-
tempElement.select();
87-
document.execCommand('copy');
88-
document.body.removeChild(tempElement);
89-
setSelectedData(JSON.stringify(data));
90-
}
75+
const copySelectedData = () => {
76+
const selectedData = gridRef.current.getSelectedData(null, null);
77+
copyData(selectedData);
78+
closeContextMenu();
79+
};
9180

92-
return (
93-
<>
94-
<div className="container sample">
95-
<div className="wrapper" onClick={closeContextMenu}>
96-
<IgrGrid
97-
autoGenerate={false}
98-
data={northWindData}
99-
primaryKey="ProductID"
100-
ref={gridRef}
101-
contextMenu={rightClick}>
102-
<IgrColumn field="ProductID" header="Product ID">
103-
</IgrColumn>
104-
<IgrColumn field="ProductName" header="Product Name">
105-
</IgrColumn>
106-
<IgrColumn field="UnitsInStock" header="Units In Stock" dataType="number">
107-
</IgrColumn>
108-
<IgrColumn field="UnitPrice" header="Units Price" dataType="number">
109-
</IgrColumn>
110-
<IgrColumn field="Discontinued" dataType="boolean">
111-
</IgrColumn>
112-
<IgrColumn field="OrderDate" header="Order Date" dataType="date">
113-
</IgrColumn>
114-
</IgrGrid>
115-
<div className="selected-data-area">
116-
{selectedData}
117-
</div>
118-
</div>
119-
</div>
120-
<div style={{display: "none"}} className="contextmenu" ref={contextMenuRef}>
121-
<span className="item" onClick={copySelectedCellData}>
122-
<IgrIcon ref={iconRef} collection='material' name="content_copy"></IgrIcon>Copy Cell Data
123-
</span>
124-
<span className="item" onClick={copySelectedRowData}>
125-
<IgrIcon collection='material' name="content_copy"></IgrIcon>Copy Row Data
126-
</span>
127-
{isCellWithinRange && (
128-
<span className="item" onClick={copySelectedData}>
129-
<IgrIcon collection='material' name="content_copy"></IgrIcon>Copy Cells Data
130-
</span>)}
131-
</div>
132-
</>
81+
const copyData = (data: any[]) => {
82+
const tempElement = document.createElement("input");
83+
document.body.appendChild(tempElement);
84+
tempElement.setAttribute("id", "temp_id");
85+
(document.getElementById("temp_id") as HTMLInputElement).value =
86+
JSON.stringify(data);
87+
tempElement.select();
88+
const dataStringified = JSON.stringify(data);
89+
navigator.clipboard.writeText(dataStringified).catch((err) => {
90+
console.error("Failed to copy: ", err);
91+
});
92+
document.body.removeChild(tempElement);
93+
setSelectedData(dataStringified);
94+
};
13395

134-
);
96+
return (
97+
<>
98+
<div className="container sample">
99+
<div className="wrapper" onClick={closeContextMenu}>
100+
<IgrGrid
101+
autoGenerate={false}
102+
data={northWindData}
103+
primaryKey="ProductID"
104+
ref={gridRef}
105+
onContextMenu={rightClick}
106+
>
107+
<IgrColumn field="ProductID" header="Product ID"></IgrColumn>
108+
<IgrColumn field="ProductName" header="Product Name"></IgrColumn>
109+
<IgrColumn
110+
field="UnitsInStock"
111+
header="Units In Stock"
112+
dataType="number"
113+
></IgrColumn>
114+
<IgrColumn
115+
field="UnitPrice"
116+
header="Units Price"
117+
dataType="number"
118+
></IgrColumn>
119+
<IgrColumn field="Discontinued" dataType="boolean"></IgrColumn>
120+
<IgrColumn
121+
field="OrderDate"
122+
header="Order Date"
123+
dataType="date"
124+
></IgrColumn>
125+
</IgrGrid>
126+
<div className="selected-data-area">{selectedData}</div>
127+
</div>
128+
</div>
129+
<div
130+
style={{ display: "none" }}
131+
className="contextmenu"
132+
ref={contextMenuRef}
133+
>
134+
<span className="item" onClick={copySelectedCellData}>
135+
<IgrIcon
136+
ref={iconRef}
137+
collection="material"
138+
name="content_copy"
139+
></IgrIcon>
140+
Copy Cell Data
141+
</span>
142+
<span className="item" onClick={copySelectedRowData}>
143+
<IgrIcon collection="material" name="content_copy"></IgrIcon>Copy Row
144+
Data
145+
</span>
146+
{isCellWithinRange && (
147+
<span className="item" onClick={copySelectedData}>
148+
<IgrIcon collection="material" name="content_copy"></IgrIcon>Copy
149+
Cells Data
150+
</span>
151+
)}
152+
</div>
153+
</>
154+
);
135155
}
136156

137157
// rendering above component in the React DOM
138-
const root = ReactDOM.createRoot(document.getElementById('root'));
139-
root.render(<App/>);
158+
const root = ReactDOM.createRoot(document.getElementById("root"));
159+
root.render(<App />);

0 commit comments

Comments
 (0)