Adding custom content to cells
Grid allows adding custom components to table cells as well as header and footer cells.
Adding components
Basically, what you need is four simple steps:
- create a component (using HTML or ready-made components from the @svar-ui/react-core library)
- in the component, access Grid properties via component props, if needed
- import the configured component to the application page with Grid
- add this component to the needed cell in Grid
Accessing Grid properties in components
Components in cells receive the following Grid data via props:
api
- Grid API, using which you can call actions or listen to themrow
- row data for body cells (data item)
- row index for header cells
column
- column data (its id, dimensions, etc.)cell
- for header/footer cells only, cell properties (its text, colspan, rowspan, etc.)onaction
- callback using which you can call built-in or custom actions
Let's look at some basic examples.
Creating static components
Embedding HTML to table cells
The example below demonstrates how to customize cells by adding images to them.
const AvatarCell = ({ row }) => (
<div className="container">
<div className="avatar">
<div className="user-avatar">
{row.avatar && <img className="user-photo" alt="" src={row.avatar} />}
</div>
</div>
<div className="info">
<div className="name">{row.lastName}</div>
<div className="mail">{row.email || ""}</div>
</div>
</div>
);
export default AvatarCell;
.container {
display: flex;
align-items: center;
height: 56px;
padding: 0 12px;
}
.avatar {
width: 70px;
}
.name, .mail {
flex: 1;
}
.user-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #dfe2e6;
text-align: center;
}
.user-photo {
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #dfe2e6;
}
Now you can import your component and apply it to a cell by adding its name to the cell
parameter of a column element in the columns
array:
import { Grid } from "@svar-ui/react-grid";
import { getData } from "../data";
import AvatarCell from "../custom/AvatarCell.jsx"; // import the component
const { data } = getData();
const columns = [
{ id: "id", width: 50 },
{ id: "avatar", cell: AvatarCell, width: 350 }, // apply the component to a cell
];
<Grid sizes={{ rowHeight: 70 }} data={data} columns={columns} />
Embedding HTML to header/footer
The next example customizes a footer cell by rendering its text and an icon in it.
const FooterTextCell = ({ cell }) => (
<div className="footer-content">
<span>{cell.text}</span>
<i className="wxi-check" />
</div>
);
export default FooterTextCell;
Optional CSS:
.footer-content {
display: flex;
align-items: center;
gap: 6px;
}
.footer-content i {
display: inline-flex;
font-size: 20px;
}
Now we can import the component and apply it by adding its name as the value of the cell
parameter of the footer
element in the columns
array.
import { Grid } from "@svar-ui/react-grid";
import { getData } from "../data";
import FooterTextCell from "../custom/FooterTextCell.jsx";
const { data } = getData();
const columns = [
{
id: "id",
width: 50,
footer: [
{
cell: FooterTextCell,
colspan: 3,
text: "Custom footer content",
},
],
}
];
<Grid data={data} columns={columns} footer />
Embedding Core components
The snippet below shows how to add a Button to a column cell. To connect button state with item data, use props to access row
and column
objects. This is how the component looks like:
import { Button } from "@svar-ui/react-core";
const ButtonCell = ({ row, column }) => (
<Button type="primary" disabled={!row[column.id]}>
Show on map
</Button>
);
export default ButtonCell;
Now you can render it in a column cell by adding its name to the cell
parameter of a column element in the columns
array:
import { Grid } from "@svar-ui/react-grid";
import { getData } from "../data";
import ButtonCell from "../custom/ButtonCell.jsx"; // import
const { data } = getData();
const columns = [
{
id: "city",
cell: ButtonCell, // add to a cell
width: 260,
},
// other columns
];
<Grid data={data} columns={columns} />
Similarly, you can create a button within a header cell.
import { Button } from "@svar-ui/react-core";
const HeaderButtonCell = () => (
<Button type="secondary" icon="wxi-plus">Add row</Button>
);
export default HeaderButtonCell;
Now we can import the component and apply it to a header cell by adding its name as the value of the cell
parameter of the header
element in the columns
array.
import { Grid } from "@svar-ui/react-grid";
import { getData } from "../data";
import HeaderButtonCell from "../custom/HeaderButtonCell.jsx";
const { data } = getData();
const columns = [
{
id: "id",
header: [{ cell: HeaderButtonCell }],
},
// other columns
];
<Grid data={data} columns={columns} />
Enabling interactivity
To enable communication between custom components and Grid, use either of the following ways:
Executing Grid actions
Use the api
prop to access Grid API and execute actions directly, e.g. add-row
:
import { Button } from "@svar-ui/react-core";
const AddRowCell = ({ api }) => {
function onClick() {
api.exec("add-row", { row: { city: "New York" } });
}
return (
<Button type="secondary" icon="wxi-plus" onClick={onClick}>
Add row
</Button>
);
};
export default AddRowCell;
Or, you can use the onaction
prop that allows sending a callback event to Grid. You can pass any existing Grid action with its parameters, and it will be executed by inner code:
import { Button } from "@svar-ui/react-core";
const AddRowCell = ({ onaction }) => {
function onClick() {
onaction &&
onaction({
action: "add-row", // Grid action name
data: { row: { city: "New York" } }, // action parameters
});
}
return (
<Button type="secondary" icon="wxi-plus" onClick={onClick}>
Add row
</Button>
);
};
export default AddRowCell;
Calling custom events
You can send a custom event in the onaction
callback and handle it at your Grid level. For example:
import { Button } from "@svar-ui/react-core";
const ButtonCell = ({ row, column, onaction }) => {
function onClick() {
onaction &&
onaction({
action: "custom-button", // call custom event
data: {
column: column.id,
row: row.id,
},
});
}
return (
<Button type="primary" disabled={!row[column.id]} onClick={onClick}>
Show on map
</Button>
);
};
export default ButtonCell;
Now handle this custom event in Grid. Beware that the on
prefix should be added and hyphens in the event name should be removed and converted to camelCase. For example, the action name custom-button
becomes the Grid prop onCustomButton
:
import { Grid } from "@svar-ui/react-grid";
import ButtonCell from "../custom/CheckboxCell.jsx";
import { getData } from "../data";
const { data } = getData();
const columns = [
{
header: "City",
cell: ButtonCell,
width: 260,
},
// other columns
];
function action(ev) {
const { row, column } = ev;
// e.g. open in Maps the city from row data
}
<Grid
data={data}
columns={columns}
onCustomButton={ev => action(ev)} // handle the custom event
/>
Use cases
Practical usage examples you can find here:
If you are interested to know how to apply custom styles to a cell, see the Styling section.
Related articles: