Skip to content

Data Table

FTDataTable is a slot-driven table component for richer row layouts, sortable headers, column filter triggers, and expandable detail rows.

Usage

vue
<script setup lang="ts">
import { FTDataTable, FTTableFilter } from '@fasttrack-solutions/vue-components-lib';
import type { IFTDataTableHead } from '@fasttrack-solutions/vue-components-lib';

const heads: IFTDataTableHead[] = [
  { label: 'Name', field: 'name', sortKey: 'name' },
  { label: 'Role', field: 'role' },
];
</script>
<script setup lang="ts">
import { FTDataTable, FTTableFilter } from '@fasttrack-solutions/vue-components-lib';
import type { IFTDataTableHead } from '@fasttrack-solutions/vue-components-lib';

const heads: IFTDataTableHead[] = [
  { label: 'Name', field: 'name', sortKey: 'name' },
  { label: 'Role', field: 'role' },
];
</script>

Sortable rows with filters and expansion

vue
<FTDataTable
  v-model:sortKey="sortKey"
  v-model:sortOrder="sortOrder"
  v-model:expandedRows="expandedRows"
  :heads="heads"
  :items="items"
  rowKey="id"
  :sortFn="sortFn"
>
  <template #filter="{ head }">
    <FTTableFilter v-if="head.filterKey" @clear="statusFilter = 'all'">
      <!-- filter controls -->
    </FTTableFilter>
  </template>

  <template #row="{ item, isExpanded, toggleExpand }">
    <tr>
      <td>
        <button type="button" @click="toggleExpand()">
          {{ isExpanded ? 'Hide' : 'Show' }}
        </button>
        {{ item.name }}
      </td>
      <td>{{ item.email }}</td>
      <td>{{ item.role }}</td>
      <td>{{ item.department }}</td>
      <td>{{ item.status }}</td>
    </tr>
  </template>

  <template #expanded-row="{ item }">
    <div>Detail row for {{ item.name }} — {{ item.department }}</div>
  </template>
</FTDataTable>
<FTDataTable
  v-model:sortKey="sortKey"
  v-model:sortOrder="sortOrder"
  v-model:expandedRows="expandedRows"
  :heads="heads"
  :items="items"
  rowKey="id"
  :sortFn="sortFn"
>
  <template #filter="{ head }">
    <FTTableFilter v-if="head.filterKey" @clear="statusFilter = 'all'">
      <!-- filter controls -->
    </FTTableFilter>
  </template>

  <template #row="{ item, isExpanded, toggleExpand }">
    <tr>
      <td>
        <button type="button" @click="toggleExpand()">
          {{ isExpanded ? 'Hide' : 'Show' }}
        </button>
        {{ item.name }}
      </td>
      <td>{{ item.email }}</td>
      <td>{{ item.role }}</td>
      <td>{{ item.department }}</td>
      <td>{{ item.status }}</td>
    </tr>
  </template>

  <template #expanded-row="{ item }">
    <div>Detail row for {{ item.name }} — {{ item.department }}</div>
  </template>
</FTDataTable>

Empty state

vue
<FTDataTable :heads="heads" :items="[]" :showEmpty="true">
  <template #empty>
    <div>No rows found.</div>
  </template>
</FTDataTable>
<FTDataTable :heads="heads" :items="[]" :showEmpty="true">
  <template #empty>
    <div>No rows found.</div>
  </template>
</FTDataTable>

Props

PropTypeDefaultDescription
headsIFTDataTableHead[]requiredColumn definitions used to render the header row.
itemsTItem[]requiredItems rendered through the row slot.
showEmptyboolean | nullnullOverrides derived empty-state visibility.
loadingbooleanfalseParticipates in empty-state display when showEmpty is not set.
rowKeykeyof TItem & stringundefinedStable key for rows and expandable-row behavior.
sortFn(items, sortKey, sortOrder) => TItem[]undefinedCustom sorting function.
scrollablebooleantrueEnables horizontal overflow scrolling.
iconPrefixstring'fas'Font Awesome prefix for internal icons.

IFTDataTableHead

PropertyTypeRequiredDescription
labelstringyesColumn header text.
fieldstringyesItem property key used to read cell values.
sortKeystringnoProperty key used for sorting. When omitted, the column is not sortable.
filterKeystringnoEnables the #filter slot for this column.
align'left' | 'right' | 'center'noHeader and cell text alignment. Defaults to 'left'.
tooltipstringnoTooltip text shown with an info icon next to the label.
classstringnoAdditional CSS class applied to the header cell.

Models

ModelTypeDefaultDescription
v-model:sortKeystring''Active sort column key.
v-model:sortOrder'asc' | 'desc''desc'Active sort direction.
v-model:expandedRows(string | number)[][]Expanded row identifiers, requires rowKey.

Events

EventDescription
sortChangeEmitted after a sortable header updates the active sort key or order.

Slots

SlotPropsDescription
selectAllnoneAdds a leading header cell, typically for bulk actions.
filterheadRenders a per-column filter trigger when filterKey is set.
rowitem, index, isExpanded, toggleExpandRequired row renderer.
expanded-rowitem, indexOptional detail row rendered below expanded rows.
emptynoneEmpty-state content.