Skip to main content

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/vue-core library)
  • in the component, access Grid properties via defineProps, 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 have access to the following Grid data via defineProps:

  • api - Grid API, using which you can call actions or listen to them
  • row
    • row data for body cells (data item)
    • row index for header cells
  • column - column data (its id, dimensions, etc.)
  • cell - for header 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.

AvatarCell
<script setup>
const props = defineProps({ row: {} }); // access Grid row data
</script>

<template>
<div class="container">
<div class="avatar">
<div class="user-avatar">
<img v-if="props.row.avatar" class="user-photo" alt="" :src="props.row.avatar" />
</div>
</div>
<div class="info">
<div class="name">{{ props.row.lastName }}</div>
<div class="mail">{{ props.row.email || "" }}</div>
</div>
</div>
</template>

<style scoped>
.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;
}
</style>

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:

<script setup>
import { Grid } from "@svar-ui/vue-grid";
import { getData } from "../data";
import AvatarCell from "../custom/AvatarCell.vue"; //import the component

const { data } = getData();

const columns = [
{ id: "id", width: 50 },
{ id: "avatar", cell: AvatarCell, width: 350 }, //apply the component to a cell
];
</script>

<template>
<Grid :sizes="{ rowHeight: 70 }" :data="data" :columns="columns" />
</template>

Embedding HTML to header/footer​

The next example customizes a footer cell by rendering its text and the icon in it.

FooterTextCell
<script setup>
const props = defineProps({ cell: {} }); //access cell data
</script>

<template>
<div class="footer-content">
<span>{{ props.cell.text }}</span>
<i class="wxi-check"></i>
</div>
</template>

<style scoped>
.footer-content {
display: flex;
align-items: center;
gap: 6px;
}

.footer-content i {
display: inline-flex;
font-size: 20px;
}
</style>

Now we can import the component and apply it by adding its names as the value of the cell parameter of the footer element in the columns array.

<script setup>
import { Grid } from "@svar-ui/vue-grid";
import { getData } from "../data";

import FooterTextCell from "../custom/FooterTextCell.vue";

const { data } = getData();

const columns = [
{
id: "id",
width: 50,
footer: [
{
cell: FooterTextCell,
colspan: 3,
text: "Custom footer content",
},
],
}
];
</script>

<template>
<Grid :data="data" :columns="columns" footer />
</template>

Embedding Core components​

The snippet below shows how to add a Button to a column cell. To connect button state with item data, use defineProps to access row and column objects. This is how the component looks like:

ButtonCell
<script setup>
import { Button } from "@svar-ui/vue-core";
const props = defineProps({ row: {}, column: {} }); // access row and column data
</script>

<template>
<Button type="primary" :disabled="!props.row[props.column.id]">
Show on map
</Button>
</template>

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:

<script setup>
import { Grid } from "@svar-ui/vue-grid";
import { getData } from "../data";
import ButtonCell from "../custom/ButtonCell.vue"; // import

const { data } = getData();

const columns = [
{
id: "city",
cell: ButtonCell, // add to a cell
width: 260,
},
//other columns
];
</script>

<template>
<Grid :data="data" :columns="columns" />
</template>

Similarly, you can create a button within a header cell.

HeaderButtonCell
<script setup>
import { Button } from "@svar-ui/vue-core";
</script>

<template>
<Button type="secondary" icon="wxi-plus">Add row</Button>
</template>

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.

<script setup>
import { Grid } from "@svar-ui/vue-grid";
import { getData } from "../data";
import HeaderButtonCell from "../custom/HeaderButtonCell.vue";

const { data } = getData();

const columns = [
{
id: "id",
header: [{ cell: HeaderButtonCell }],
},
//other columns
];
</script>

<template>
<Grid :data="data" :columns="columns" />
</template>

Enabling interactivity​

To enable communication between custom components and Grid, use either of the following ways:

Executing Grid actions​

Use defineProps to access Grid api and execute actions directly, e.g. add-row:

<script setup>
import { Button } from "@svar-ui/vue-core";
const props = defineProps({ api: {} });

function onClick() {
props.api.exec("add-row", { row: { city: "New York"}});
}
</script>

<template>
<Button type="secondary" icon="wxi-plus" :onclick="onClick">Add row</Button>
</template>

Or, you can use the onaction property 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:

<script setup>
import { Button } from "@svar-ui/vue-core";
const props = defineProps({ onaction: { type: Function } });

function onClick() {
props.onaction?.({
action: "add-row", //Grid action name
data: { row: { city: "New York"}}, //action parameters
});
}
</script>

<template>
<Button type="secondary" icon="wxi-plus" :onclick="onClick">Add row</Button>
</template>

Calling custom events​

You can send a custom event in the onaction callback and handle it at your Grid level. For example:

<script setup>
import { Button } from "@svar-ui/vue-core";
const props = defineProps({ row: {}, column: {}, onaction: { type: Function } });

function onClick() {
props.onaction?.({
action: "custom-button", // call custom event
data: {
column: props.column.id,
row: props.row.id,
},
});
}
</script>

<template>
<Button type="primary" :disabled="!props.row[props.column.id]" :onclick="onClick">
Show on map
</Button>
</template>

Now handle this custom event in Grid. Beware that the on prefix should be added and a hyphen in the event name should be removed:

<script setup>
import { Grid } from "@svar-ui/vue-grid";
import ButtonCell from "../custom/ButtonCell.vue"
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
}
</script>

<template>
<Grid
:data="data"
:columns="columns"
:oncustombutton="ev => action(ev)"
/>
</template>

Use cases​

Practical usage examples you can find here:

info

If you are interested to know how to apply custom styles to a cell, see the Styling section.


Related articles: