DataGrid Component


In its most simple usage the DataGrid component can be used to render typed collections:

<DataGrid :items="tracks" />

const tracks = [
    track("Everythings Ruined", "Faith No More", "Angel Dust", 1992),
    track("Lightning Crashes", "Live", "Throwing Copper", 1994),
    track("Heart-Shaped Box", "Nirvana", "In Utero", 1993),
    track("Alive", "Pearl Jam", "Ten", 1991),

Which by default will display all object properties:

Use selected-columns to control which columns to display and header-titles to use different column names:

<DataGrid :items="tracks" :selected-columns="['year','album','name','artist']" 
          :header-titles="{ name:'Track' }" />

Which for a wrist-friendly alternative also supports a string of comma delimited column names, e.g:

<DataGrid :items="tracks" selected-columns="year,album,name,artist" />

Simple Customizations

Which columns are shown and how they're rendered is customizable with custom <template #column> definitions:

<DataGrid :items="forecasts" class="max-w-screen-md" :table-style="['stripedRows','uppercaseHeadings']"
          :header-titles="{ temperatureC:'TEMP. (C)', temperatureF:'TEMP. (F)' }">
    <template #date-header>
        <span class="text-indigo-600">Date</span>
    <template #date="{ date }">
        {‎{ new Intl.DateTimeFormat().format(new Date(date)) }‎}
    <template #temperatureC="{ temperatureC }">
        {‎{ temperatureC }‎}&deg;
    <template #temperatureF="{ temperatureF }">
        {‎{ temperatureF }‎}&deg;
    <template #summary="{ summary }">{‎{ summary }‎}</template>

Column names can be changed with a header-titles alias mapping, or dynamically with a header-title mapping function.

Alternatively for more advanced customizations, custom <template #column-header> definitions can be used to control how column headers are rendered.

If any custom column or header definitions are provided, only those columns will be displayed. Alternatively specify an explicit array of column names in selected-columns to control the number and order or columns displayed.


A more advanced example showing how to implement a responsive datagrid defining what columns and Headers are visible at different screen sizes using visible-from to specify which columns to show from different Tailwind responsive breakpoints and <template #column-header> definitions to collapse column names at small screen sizes:

<DataGrid :items="bookings" 
      :visible-from="{ name:'xl', bookingStartDate:'sm', bookingEndDate:'xl' }"
      @row-selected="rowSelected" :is-selected="row => selected ==">
    <template #id="{ id }">
        <span class="text-gray-900" v-html="id"></span>
    <template #name="{ name }">{‎{name}‎}</template>
    <template #roomNumber-header>
        <span class="hidden lg:inline">Room </span>No

    <template #cost="{ cost }" v-html="currency(cost)"></template>
    <template #bookingStartDate-header>
        Start<span class="hidden lg:inline"> Date</span>
    <template #bookingEndDate-header>
        End<span class="hidden lg:inline"> Date</span>

    <template #createdBy-header>
    <template #createdBy="{ createdBy }" v-html="createdBy"></template>

<script setup lang="ts">
import { ref } from 'vue'
import { useFormatters } from '@servicestack/vue'
import { bookings } from '../data'
import { Booking } from '../dtos'

const { currency } = useFormatters()
const selected = ref()

function headerSelected(column:string) {
function rowSelected(row:Booking) {
    selected.value = selected.value === ? null :
    console.log('rowSelected', row)

Behavior of the DataGrid can be customized with the @header-selected event to handle when column headers are selected to apply custom filtering to the items data source whilst the @row-selected event can be used to apply custom behavior when a row is selected.

Using Formatters

Your App and custom templates can also utilize @servicestack/vue's built-in formatting functions from:

import { useFormatters } from '@servicestack/vue'

const {
    Formats,             // Available format methods to use in <PreviewFormat />
    formatValue,         // Format any value or object graph
    currency,            // Format number as Currency
    bytes,               // Format number in human readable disk size
    link,                // Format URL as <a> link
    linkTel,             // Format Phone Number as <a> tel: link
    linkMailTo,          // Format email as <a> mailto: link
    icon,                // Format Image URL as an Icon
    iconRounded,         // Format Image URL as a full rounded Icon
    attachment,          // Format File attachment URL as an Attachment
    hidden,              // Format as empty string
    time,                // Format duration in time format
    relativeTime,        // Format Date as Relative Time from now
    relativeTimeFromMs,  // Format time in ms as Relative Time from now
    formatDate,          // Format as Date
    formatNumber,        // Format as Number
} = useFormatters()

Many of these formatting functions return rich HTML markup which will need to be rendered using Vue's v-html directive:

<span v-html="formatValue(value)"></span>

The PreviewFormat component also offers a variety of flexible formatting options.

Table Styles

The appearance of DataGrids can use tableStyles to change to different Tailwind Table Styles, e.g:

Default (Striped Rows)

<DataGrid :items="tracks" />


<DataGrid :items="tracks" table-style="simple" />

Uppercase Headings

<DataGrid :items="tracks" table-style="uppercaseHeadings" />

Vertical Lines

<DataGrid :items="tracks" table-style="verticalLines" />

White Background

<DataGrid :items="tracks" table-style="whiteBackground" />

Full Width

<DataGrid :items="tracks" table-style="fullWidth" />

Full Width, Uppercase with Vertical Lines

<DataGrid :items="tracks" :table-style="['uppercaseHeadings', 'fullWidth', 'verticalLines']" />

Using App Metadata

By default DataGrid will render values using its default configured formatters, so results with strings, numbers and defaults will display a stock standard resultset:

<DataGrid :items="bookings" />

Another option for formatting this dataset is to use the rich format functions in ServiceStack to annotate the DTOs with how each field should be formatted, e.g:

public class Booking
    public int Id { get; set; }
    public string Name { get; set; }
    public RoomType RoomType { get; set; }
    public int RoomNumber { get; set; }

    public DateTime BookingStartDate { get; set; }

    public DateTime? BookingEndDate { get; set; }

    [IntlNumber(Currency = NumberCurrency.USD)]
    public decimal Cost { get; set; }

Which can be enabled when using useMetadata by specifying the MetadataType for the DataGrid's results in type:

<DataGrid :items="bookings" type="Booking" />

Declaratively annotating your DTOs with preferred formatting hints makes this rich metadata information available to clients where it's used to enhance ServiceStack's built-in UI's and Components like: