DataGrid Component

Default

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

<DataGrid :items="tracks" />

<script>
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),
]
</script>

Which by default will display all object properties:

Id
Name
Artist
Album
Year
1Everythings RuinedFaith No MoreAngel Dust1992
2Lightning CrashesLiveThrowing Copper1994
3Heart-Shaped BoxNirvanaIn Utero1993
4AlivePearl JamTen1991

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' }" />
Year
Album
Track
Artist
1992Angel DustEverythings RuinedFaith No More
1994Throwing CopperLightning CrashesLive
1993In UteroHeart-Shaped BoxNirvana
1991TenAlivePearl Jam

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" ::tableStyle="['stripedRows','uppercaseHeadings']"
          :header-titles="{ temperatureC:'TEMP. (C)', temperatureF:'TEMP. (F)' }">
    <template #date-header>
        <span class="text-indigo-600">Date</span>
    </template>
    <template #date="{ date }">
        {{ new Intl.DateTimeFormat().format(new Date(date)) }}
    </template>
    <template #temperatureC="{ temperatureC }">
        {{ temperatureC }}&deg;
    </template>
    <template #temperatureF="{ temperatureF }">
        {{ temperatureF }}&deg;
    </template>
    <template #summary="{ summary }">{{ summary }}</template>
</DataGrid>
Date
TEMP. (C)
TEMP. (F)
Summary
5/6/201834° Freezing
5/7/201814° 57° Bracing
5/8/2018-13° Freezing
5/9/2018-16° Balmy
5/10/2018-2° 28° Chilly

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.

Responsive

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:

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

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

    <template #createdBy-header>
        Employee
    </template>
    <template #createdBy="{ createdBy }">{{ createdBy }}</template>
</DataGrid>
</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) {
    console.log('headerSelected',column)
}
function rowSelected(row:Booking) {
    selected.value = selected.value === row.id ? null : row.id
    console.log('rowSelected', row)
}
</script>

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" />
Id
Name
Artist
Album
Year
1Everythings RuinedFaith No MoreAngel Dust1992
2Lightning CrashesLiveThrowing Copper1994
3Heart-Shaped BoxNirvanaIn Utero1993
4AlivePearl JamTen1991

Simple

<DataGrid :items="tracks" tableStyle="simple" />
Id
Name
Artist
Album
Year
1Everythings RuinedFaith No MoreAngel Dust1992
2Lightning CrashesLiveThrowing Copper1994
3Heart-Shaped BoxNirvanaIn Utero1993
4AlivePearl JamTen1991

Uppercase Headings

<DataGrid :items="tracks" tableStyle="uppercaseHeadings" />
Id
Name
Artist
Album
Year
1Everythings RuinedFaith No MoreAngel Dust1992
2Lightning CrashesLiveThrowing Copper1994
3Heart-Shaped BoxNirvanaIn Utero1993
4AlivePearl JamTen1991

Vertical Lines

<DataGrid :items="tracks" tableStyle="verticalLines" />
Id
Name
Artist
Album
Year
1Everythings RuinedFaith No MoreAngel Dust1992
2Lightning CrashesLiveThrowing Copper1994
3Heart-Shaped BoxNirvanaIn Utero1993
4AlivePearl JamTen1991

White Background

<DataGrid :items="tracks" tableStyle="whiteBackground" />
Id
Name
Artist
Album
Year
1Everythings RuinedFaith No MoreAngel Dust1992
2Lightning CrashesLiveThrowing Copper1994
3Heart-Shaped BoxNirvanaIn Utero1993
4AlivePearl JamTen1991

Full Width

<DataGrid :items="tracks" tableStyle="fullWidth" />
Id
Name
Artist
Album
Year
1Everythings RuinedFaith No MoreAngel Dust1992
2Lightning CrashesLiveThrowing Copper1994
3Heart-Shaped BoxNirvanaIn Utero1993
4AlivePearl JamTen1991

Full Width, Uppercase with Vertical Lines

<DataGrid :items="tracks" :tableStyle="['uppercaseHeadings', 'fullWidth', 'verticalLines']" />
Id
Name
Artist
Album
Year
1Everythings RuinedFaith No MoreAngel Dust1992
2Lightning CrashesLiveThrowing Copper1994
3Heart-Shaped BoxNirvanaIn Utero1993
4AlivePearl JamTen1991

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" />
Id
Name
Room Type
Room Number
Booking Start Date
Booking End Date
Cost
1First Booking!Queen10Dec 9, 2022Dec 16, 2022100
2Booking 2Double12Dec 11, 2022Dec 18, 2022120
3Booking the 3rdSuite13Dec 12, 2022Dec 19, 2022130

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
{
    [AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    public RoomType RoomType { get; set; }
    public int RoomNumber { get; set; }

    [IntlDateTime(DateStyle.Long)]
    public DateTime BookingStartDate { get; set; }

    [IntlRelativeTime]
    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" />
Id
Name
Room Type
Room Number
Booking Start Date
Booking End Date
Cost
1First Booking!Queen10December 9, 20223 months ago$100.00
2Booking 2Double12December 11, 20223 months ago$120.00
3Booking the 3rdSuite13December 12, 20223 months ago$130.00

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: