Skip to content

Custom cells ​

Anything beyond plain text goes through slots: set slotName on the column and fill the slot. It receives { row }.

Status badge ​

ts
{label: "Status", slotName: "status", contentAlign: "center"}
vue
<template #status="{ row }">
    <span :class="['badge', `badge--${row.status}`]">{{ row.status }}</span>
</template>
css
.badge { padding: 2px 8px; border-radius: 999px; font-size: 12px; }
.badge--active { background: #dcfce7; color: #166534; }
.badge--blocked { background: #fee2e2; color: #991b1b; }
vue
<template #name="{ row }">
    <a :href="`/users/${row.id}`">{{ row.name }}</a>
</template>

Dates and money ​

For plain text, a value function is enough, no slot needed:

ts
const date = new Intl.DateTimeFormat("en-GB", {dateStyle: "medium"});
const money = new Intl.NumberFormat("en-US", {style: "currency", currency: "USD"});

columns: [
    {label: "Created", value: (row) => date.format(new Date(row.createdAt)), sortable: "createdAt"},
    {label: "Balance", value: (row) => money.format(row.balance), contentAlign: "right"},
]

Image only ​

No slot needed: use the image formatter.

ts
{label: "Photo", value: "photoUrl", formatter: GridFormatter.image}

Avatar + name ​

vue
<template #user="{ row }">
    <span style="display: inline-flex; align-items: center; gap: 8px">
        <img :src="row.avatarUrl" alt="" width="24" height="24" style="border-radius: 50%">
        {{ row.name }}
    </span>
</template>

Header with a tooltip ​

Set headerSlotName. The slot receives { column }. It works on sortable columns too.

ts
{label: "Score", value: "score", sortable: "score", headerSlotName: "scoreHeader"}
vue
<template #scoreHeader="{ column }">
    {{ column.label }} <span title="Calculated nightly">ⓘ</span>
</template>

Sponsored by MobicardBusyBPC-InfoLinkTrust