Adding and configuring the context menu
You can add/configure the context menu in one of the two ways:
- add the default menu and/or modify necessary settings by importing the ContextMenu component from "@svar-ui/react-grid"
- add a custom menu by importing the ContextMenu component from "@svar-ui/react-menu"; for a custom menu you can also apply the ActionMenu
Adding the default context menu
To add a context menu with default menu options, import the ContextMenu component from "@svar-ui/react-grid" and wrap Grid inside the ContextMenu component. You should also pass the api object to the ContextMenu component.
Example:
import { useRef } from "react";
import { Grid, ContextMenu } from "@svar-ui/react-grid";
import { getData } from "./common/data";
const { data, columns } = getData();
const table = useRef(null);
return (
<ContextMenu api={table}>
<Grid data={data} columns={columns} ref={table} />
</ContextMenu>
);
Customizing the context menu
To customize menu options, import the ContextMenu component, and then modify the required settings. The example below shows how to add the separator after the "Add after" option, and display the menu at the bottom of the selected item.
import { useRef } from "react";
import { getData } from "../data";
import { Grid, ContextMenu } from "@svar-ui/react-grid";
const { data, columns } = getData();
const table = useRef(null);
const options = [
{
id: "add:before",
text: "Add before",
icon: "wxi-table-row-plus-before",
},
{
id: "add:after",
text: "Add after",
icon: "wxi-table-row-plus-after",
},
{ type: "separator" },
{ id: "copy", text: "Copy", icon: "wxi-content-copy" },
{ type: "separator" },
{ id: "delete", text: "Delete", icon: "wxi-delete-outline" },
];
return (
<ContextMenu api={table} options={options} at="bottom">
<Grid data={data} columns={columns} ref={table} />
</ContextMenu>
);
Adding a custom context menu
In the example below we add a custom menu with two menu options: "Add" with subitems and "Delete". To add a custom menu we do the following:
- import the ContextMenu component from "@svar-ui/react-menu"
- add the options array
- add the function to handle clicks on the menu items
- pass a ref to the Grid component and provide that ref as the api prop
import { useRef } from "react";
import { getData } from "./common/data";
import { Grid } from "@svar-ui/react-grid";
import { ContextMenu } from "@svar-ui/react-menu"; // import the component
const { data, columns } = getData();
const table = useRef(null);
// add menu options
const options = [
{
id: "add",
text: "Add",
icon: "wxi-table-row-plus",
// add subitems
data: [
{ id: "add-before:child", icon: "wxi-table-row-plus-before", text: "Add before this row" },
{ id: "add-after:child", icon: "wxi-table-row-plus-after", text: "Add after this row" },
],
},
{ type: "separator" },
{ id: "delete", text: "Delete", icon: "wxi-delete-outline" },
];
const handleClicks = (ev) => {
const option = ev.action;
if (option) {
// access API via ref.current
const id = table.current?.getState().selected;
switch (option.id) {
case "add-before:child":
table.current?.exec("add-row", { row: {}, before: id });
break;
case "add-after:child":
table.current?.exec("add-row", { row: {}, after: id });
break;
case "delete":
table.current?.exec("delete-row", { id });
break;
default:
// helpers.showNotice({ text: `You clicked ${option.text}` });
// FIXME: replace helpers.showNotice with your notification method
console.log(`You clicked ${option.text}`);
}
}
};
// select item and open menu for it
function getItem(id) {
if (id) table.current?.exec("select-row", { id });
return id;
}
return (
<ContextMenu
api={table}
options={options}
onClick={handleClicks}
at="point"
resolver={getItem}
>
<Grid data={data} columns={columns} ref={table} />
</ContextMenu>
);
Adding a header menu
The header context menu allows hiding/showing the columns by clicking their names in this menu.
To add the default context menu for all column headers, import the HeaderMenu component (from the "@svar-ui/react-grid" package), wrap the Grid component inside the HeaderMenu component and pass the api object to the HeaderMenu component.
Example:
import { useRef } from "react";
import { getData } from "./common/data";
import { Grid, HeaderMenu } from "@svar-ui/react-grid";
const { data, columns } = getData();
const table = useRef(null);
return (
<HeaderMenu api={table}>
<Grid data={data} columns={columns} ref={table} />
</HeaderMenu>
);
To add the header context menu for specific columns, wrap the Grid component into the HeaderMenu component. For the columns you want to show the menu, pass the columns object with the required column IDs set to true. Don't forget to pass the api object to the HeaderMenu component.
import { useRef } from "react";
import { getData } from "./common/data";
import { Grid, HeaderMenu } from "@svar-ui/react-grid";
const { data, columns } = getData();
const gridRef = useRef(null);
return (
<HeaderMenu api={gridRef} columns={{ city: true, firstName: true, id: true }}>
<Grid data={data} columns={columns} ref={gridRef} />
</HeaderMenu>
);
Adding an Action menu
You can use the ActionMenu component with Grid. The next example shows how to add an icon to a cell and open the ActionMenu by clicking on it. To learn how to render components in Grid cells, refer to Adding custom content to cells.
First, create the IconCell component with an icon. It's crucial to set the data-action-id attribute with the row id on an HTML element so that the ActionMenu can be shown by clicking on it.
IconCell.jsx
// IconCell.jsx
export default function IconCell({ row }) {
return (
<div className="table_icon" data-action-id={row.id}>
<i className="wxi-dots-h" />
</div>
);
}
IconCell.css
.table_icon {
height: 20px;
cursor: pointer;
font-size: 18px;
text-align: center;
}
Then apply the component to Grid cells. Import all necessary components: ActionMenu from "@svar-ui/react-menu", IconCell as well as defaultMenuOptions helper if you want to reuse the default options set.
To open ActionMenu on icon click:
- set its dataKey to the same value as the data- attribute of an icon element (data-action-id -> dataKey="actionId")
- define its resolver function which returns a boolean/ID value (e.g., returns the id if the menu should open)
- handle clicks using onClick to process menu actions and modify the Grid state accordingly
import { useRef } from "react";
import { Grid, defaultMenuOptions } from "@svar-ui/react-grid";
import { ActionMenu } from "@svar-ui/react-menu";
import IconCell from "../custom/IconCell.jsx";
import { getData } from "../data";
const api = useRef(null);
const { data } = getData();
const columns = [
{ id: "menu", cell: IconCell, width: 50 },
{ id: "firstName", header: "First Name" },
{ id: "lastName", header: "Last Name" },
{ id: "email", header: "Email" },
];
const handleClicks = (ev) => {
const option = ev.action;
if (option) {
// clicking the icon also selects this row
const id = api.current?.getState().selectedRows?.[0];
switch (option.id) {
case "add:before":
api.current?.exec("add-row", { row: {}, before: id });
break;
case "add:after":
api.current?.exec("add-row", { row: {}, after: id });
break;
case "copy":
api.current?.exec("add-row", {
row: { ...(api.current?.getRow(id) ?? {}), id: null },
after: id,
});
break;
case "delete":
api.current?.exec("delete-row", { id });
break;
}
}
};
return (
<ActionMenu
resolver={(id) => id}
api={api}
at="point"
dataKey="actionId"
options={defaultMenuOptions}
onClick={handleClicks}
>
<Grid ref={api} data={data} columns={columns} />
</ActionMenu>
);
Related articles: