Svelte DataTables - Flowbite
Use the datatable component to search, sort, filter and paginate table data of rows and columns for your web application.
The datatable component examples from Flowbite are open-source under the MIT License and they are based on the simple-datatables repository from GitHub.
This page provides multiple examples of datatable components where you can search, sort, filter, and paginate table data up to thousands of entries.
All examples are responsive, dark mode and RTL support included and by installing the Flowbite-Svelte-DataTable plugin the custom styles will automatically be applied to the datatable components using Tailwind CSS.
Installation #
- Svelte
pnpm i -D @flowbite-svelte-plugins/datatable
app.d.ts #
Update app.d.ts
as the following:
declare global {
namespace App {}
}
declare module "simple-datatables" {
export { DataTable } from "simple-datatables/dist/dts/datatable";
export { convertCSV, convertJSON } from "simple-datatables/dist/dts/convert";
export { exportCSV, exportJSON, exportSQL, exportTXT } from "simple-datatables/dist/dts/export";
export { createElement, isJson, isObject } from "simple-datatables/dist/dts/helpers";
export { makeEditable } from "simple-datatables/dist/dts/editing";
export { addColumnFilter } from "simple-datatables/dist/dts/column_filter";
export type { DataTableOptions, DataTableConfiguration, ColumnOption, cellType, inputCellType, dataRowType, inputRowType, headerCellType, inputHeaderCellType, TableDataType, DataOption, renderType, nodeType, elementNodeType, textNodeType, cellDataType } from "simple-datatables/dist/dts/datatable";
export interface SelectableDataRow {
selected?: boolean;
[key: string]: any;
}
}
export {};
app.css #
@source "../node_modules/simple-datatables/dist";
@source "../node_modules/@flowbite-svelte-plugins/datatable/dist";
.datatable-pagination .datatable-active a,
.datatable-pagination .datatable-active a:focus,
.datatable-pagination .datatable-active a:hover,
.datatable-pagination .datatable-active button,
.datatable-pagination .datatable-active button:focus,
.datatable-pagination .datatable-active button:hover {
background-color: #ffe4de;
cursor: default;
}
.datatable-wrapper .datatable-table tbody tr.selected {
background-color: #fff1ee !important;
}
Default datatable #
Use this example to show table data with default sorting and pagination functionalities.
Name | ReleaseDate | NpmDownloads | Growth |
---|---|---|---|
Flowbite | 2021/25/09 | 269000 | 49% |
React | 2013/24/05 | 4500000 | 24% |
Angular | 2010/20/09 | 2800000 | 17% |
Vue | 2014/12/02 | 3600000 | 30% |
Svelte | 2016/26/11 | 1200000 | 57% |
Ember | 2011/08/12 | 500000 | 44% |
Backbone | 2010/13/10 | 300000 | 9% |
jQuery | 2006/28/01 | 6000000 | 5% |
Bootstrap | 2011/19/08 | 1800000 | 12% |
Foundation | 2011/23/09 | 700000 | 8% |
Bulma | 2016/24/10 | 500000 | 7% |
Next.js | 2016/25/10 | 2300000 | 45% |
Nuxt.js | 2016/16/10 | 900000 | 50% |
Meteor | 2012/17/01 | 1000000 | 10% |
Aurelia | 2015/08/07 | 200000 | 20% |
Inferno | 2016/27/09 | 100000 | 35% |
Preact | 2015/16/08 | 600000 | 28% |
Lit | 2018/28/05 | 400000 | 60% |
Alpine.js | 2019/02/11 | 300000 | 70% |
Stimulus | 2018/06/03 | 150000 | 25% |
Solid | 2021/05/07 | 250000 | 80% |
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import items from "./data/sample.json";
</script>
<Table {items} />
Snippets #
Use captionSlot
and footerSlot
snippet
s.
Name | ReleaseDate | NpmDownloads | Growth |
---|---|---|---|
Flowbite | 2021/25/09 | 269000 | 49% |
React | 2013/24/05 | 4500000 | 24% |
Angular | 2010/20/09 | 2800000 | 17% |
Vue | 2014/12/02 | 3600000 | 30% |
Svelte | 2016/26/11 | 1200000 | 57% |
Ember | 2011/08/12 | 500000 | 44% |
Backbone | 2010/13/10 | 300000 | 9% |
jQuery | 2006/28/01 | 6000000 | 5% |
Bootstrap | 2011/19/08 | 1800000 | 12% |
Foundation | 2011/23/09 | 700000 | 8% |
Bulma | 2016/24/10 | 500000 | 7% |
Next.js | 2016/25/10 | 2300000 | 45% |
Nuxt.js | 2016/16/10 | 900000 | 50% |
Meteor | 2012/17/01 | 1000000 | 10% |
Aurelia | 2015/08/07 | 200000 | 20% |
Inferno | 2016/27/09 | 100000 | 35% |
Preact | 2015/16/08 | 600000 | 28% |
Lit | 2018/28/05 | 400000 | 60% |
Alpine.js | 2019/02/11 | 300000 | 70% |
Stimulus | 2018/06/03 | 150000 | 25% |
Solid | 2021/05/07 | 250000 | 80% |
footerSlot: Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias laboriosam placeat eum facilis aliquam, adipisci consequuntur excepturi rerum distinctio illum quibusdam neque magni quaerat dolorum hic labore repellat omnis? Quisquam? |
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import { P, Heading } from "flowbite-svelte";
import items from "./data/sample.json";
</script>
<Table {items}>
{#snippet captionSlot()}
<Heading tag="h5" class="text-primary-700 text-left">Caption</Heading>
<P>Browse a list of Flowbite products designed to help you work and play, stay organized, get answers, keep in touch, grow your business, and more.</P>
{/snippet}
{#snippet footerSlot()}
<tr>
<td colspan={4} class="text-left text-base leading-normal font-normal tracking-normal whitespace-normal text-gray-900 dark:text-white">
<Span highlight="red" class="bold">footerSlot:</Span>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias laboriosam placeat eum facilis aliquam, adipisci consequuntur excepturi rerum distinctio illum quibusdam neque magni quaerat dolorum hic labore repellat omnis? Quisquam?
</td>
</tr>
{/snippet}
</Table>
searchable and sortable #
searchable
and sortable
options are true
as default. You can disable it as the following example.
Name | ReleaseDate | NpmDownloads | Growth |
---|---|---|---|
Flowbite | 2021/25/09 | 269000 | 49% |
React | 2013/24/05 | 4500000 | 24% |
Angular | 2010/20/09 | 2800000 | 17% |
Vue | 2014/12/02 | 3600000 | 30% |
Svelte | 2016/26/11 | 1200000 | 57% |
Ember | 2011/08/12 | 500000 | 44% |
Backbone | 2010/13/10 | 300000 | 9% |
jQuery | 2006/28/01 | 6000000 | 5% |
Bootstrap | 2011/19/08 | 1800000 | 12% |
Foundation | 2011/23/09 | 700000 | 8% |
Bulma | 2016/24/10 | 500000 | 7% |
Next.js | 2016/25/10 | 2300000 | 45% |
Nuxt.js | 2016/16/10 | 900000 | 50% |
Meteor | 2012/17/01 | 1000000 | 10% |
Aurelia | 2015/08/07 | 200000 | 20% |
Inferno | 2016/27/09 | 100000 | 35% |
Preact | 2015/16/08 | 600000 | 28% |
Lit | 2018/28/05 | 400000 | 60% |
Alpine.js | 2019/02/11 | 300000 | 70% |
Stimulus | 2018/06/03 | 150000 | 25% |
Solid | 2021/05/07 | 250000 | 80% |
- Svelte
<Table {items} dataTableOptions={{ searchable: false, sortable: false }} />
Filtering data #
Use the following example to enable filtering data based on a search query for each column. Enabling search for each individual data column is an advanced way of letting users browse complex data.
Name | Category | Brand | Price | Stock | TotalSales | Status |
---|---|---|---|---|---|---|
Apple iMac | Computers | Apple | $1,299 | 50 | 200 | In Stock |
Apple iPhone | Mobile Phones | Apple | $999 | 120 | 300 | In Stock |
Samsung Galaxy | Mobile Phones | Samsung | $899 | 80 | 150 | In Stock |
Dell XPS 13 | Computers | Dell | $1,099 | 30 | 120 | In Stock |
HP Spectre x360 | Computers | HP | $1,299 | 25 | 80 | In Stock |
Google Pixel 6 | Mobile Phones | $799 | 100 | 200 | In Stock | |
Sony WH-1000XM4 | Headphones | Sony | $349 | 60 | 150 | In Stock |
Apple AirPods Pro | Headphones | Apple | $249 | 200 | 300 | In Stock |
Asus ROG Zephyrus | Computers | Asus | $1,899 | 15 | 50 | In Stock |
Microsoft Surface Pro 7 | Computers | Microsoft | $899 | 40 | 100 | In Stock |
Samsung QLED TV | Televisions | Samsung | $1,299 | 25 | 70 | In Stock |
LG OLED TV | Televisions | LG | $1,499 | 20 | 50 | In Stock |
Canon EOS R5 | Cameras | Canon | $3,899 | 10 | 30 | In Stock |
Nikon Z7 II | Cameras | Nikon | $3,299 | 8 | 25 | In Stock |
Apple Watch Series 7 | Wearables | Apple | $399 | 150 | 500 | In Stock |
Fitbit Charge 5 | Wearables | Fitbit | $179 | 100 | 250 | In Stock |
Dyson V11 Vacuum | Home Appliances | Dyson | $599 | 30 | 90 | In Stock |
iRobot Roomba i7+ | Home Appliances | iRobot | $799 | 20 | 70 | In Stock |
Bose SoundLink Revolve | Speakers | Bose | $199 | 80 | 200 | In Stock |
Sonos One | Speakers | Sonos | $219 | 60 | 180 | In Stock |
Apple iPad Pro | Tablets | Apple | $1,099 | 50 | 150 | In Stock |
Samsung Galaxy Tab S7 | Tablets | Samsung | $649 | 70 | 130 | In Stock |
Amazon Echo Dot | Smart Home | Amazon | $49 | 300 | 800 | In Stock |
Google Nest Hub | Smart Home | $89 | 150 | 400 | In Stock | |
PlayStation 5 | Gaming Consoles | Sony | $499 | 10 | 500 | Out of Stock |
Xbox Series X | Gaming Consoles | Microsoft | $499 | 15 | 450 | Out of Stock |
Nintendo Switch | Gaming Consoles | Nintendo | $299 | 40 | 600 | In Stock |
Apple MacBook Pro | Computers | Apple | $1,299 | 20 | 100 | In Stock |
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import products from "./data/products.json";
import type { DataTableOptions } from "simple-datatables";
const filterOptions: DataTableOptions = {
tableRender: (data: any[], table: any, type: string) => {
if (type === "print") {
return table;
}
const tHead = table.childNodes[0];
const filterHeaders = {
nodeName: "TR",
attributes: {
class: "search-filtering-row"
},
childNodes: tHead.childNodes[0].childNodes.map((_th: any, index: number) => ({
nodeName: "TH",
childNodes: [
{
nodeName: "INPUT",
attributes: {
class: "datatable-input",
type: "search",
placeholder: `Filter column ${index + 1}`,
"data-columns": `[${index}]`
}
}
]
}))
};
tHead.childNodes.push(filterHeaders);
return table;
}
};
</script>
<Table items={products} dataTableOptions={filterOptions} />
Table pagination #
Pagination is enabled by default for all datatables, however, you can disable it by setting the option paging to false. Use the perPage option to specify how many data rows to show by default.
You can also set the perPageSelect option to set the selection options of the table.
ModelName | Developer | ReleaseDate | Parameters | PrimaryApplication |
---|---|---|---|---|
GPT-4 | OpenAI | March 2023 | 1 trillion | Natural Language Processing |
BERT | October 2018 | 340 million | Natural Language Understanding | |
DALL-E 2 | OpenAI | April 2022 | 3.5 billion | Image Generation |
T5 | October 2019 | 11 billion | Text-to-Text Transfer | |
GPT-3.5 | OpenAI | November 2022 | 175 billion | Natural Language Processing |
Codex | OpenAI | August 2021 | 12 billion | Code Generation |
PaLM 2 | May 2023 | 540 billion | Multilingual Understanding | |
LaMDA | May 2021 | 137 billion | Conversational AI | |
CLIP | OpenAI | January 2021 | 400 million | Image and Text Understanding |
XLNet | June 2019 | 340 million | Natural Language Processing | |
Meena | January 2020 | 2.6 billion | Conversational AI | |
BigGAN | September 2018 | Unlimited | Image Generation | |
Electra | March 2020 | 14 million | Natural Language Understanding | |
Swin Transformer | Microsoft | April 2021 | 88 million | Vision Processing |
GPT-NeoX-20B | EleutherAI | April 2022 | 20 billion | Natural Language Processing |
Ernie 3.0 | Baidu | July 2021 | 10 billion | Natural Language Processing |
Turing-NLG | Microsoft | February 2020 | 17 billion | Natural Language Processing |
Wu Dao 2.0 | Beijing Academy of AI | June 2021 | 1.75 trillion | Multimodal Processing |
Jukebox | OpenAI | April 2020 | 1.2 billion | Music Generation |
StyleGAN2 | NVIDIA | February 2020 | Unlimited | Image Generation |
FLAN | December 2021 | 137 billion | Few-shot Learning | |
GShard | June 2020 | 600 billion | Multilingual Understanding | |
AlphaFold | DeepMind | December 2020 | Unknown | Protein Folding |
GPT-J | EleutherAI | June 2021 | 6 billion | Natural Language Processing |
M6 | Alibaba | December 2020 | 10 billion | Multimodal Processing |
Megatron-Turing NLG | NVIDIA & Microsoft | October 2021 | 530 billion | Natural Language Processing |
DeepSpeed | Microsoft | February 2020 | Not disclosed | AI Training Optimization |
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import aimodels from "./data/aimodels.json";
import type { DataTableOptions } from "simple-datatables";
const paginationOptions: DataTableOptions = {
paging: true,
perPage: 5,
perPageSelect: [5, 10, 15, 20, 25],
sortable: false
};
</script>
<Table items={aimodels} dataTableOptions={paginationOptions} />
Selecting rows #
Use this example to enable the selection of rows by clicking anywhere one of the table row elements.
Use selectable
true and rowRender
option to enable multi selection. Use multiSelect
false to make single selection.
Name | ReleaseDate | NpmDownloads | Growth |
---|---|---|---|
Flowbite | 2021/25/09 | 269000 | 49% |
React | 2013/24/05 | 4500000 | 24% |
Angular | 2010/20/09 | 2800000 | 17% |
Vue | 2014/12/02 | 3600000 | 30% |
Svelte | 2016/26/11 | 1200000 | 57% |
Ember | 2011/08/12 | 500000 | 44% |
Backbone | 2010/13/10 | 300000 | 9% |
jQuery | 2006/28/01 | 6000000 | 5% |
Bootstrap | 2011/19/08 | 1800000 | 12% |
Foundation | 2011/23/09 | 700000 | 8% |
Bulma | 2016/24/10 | 500000 | 7% |
Next.js | 2016/25/10 | 2300000 | 45% |
Nuxt.js | 2016/16/10 | 900000 | 50% |
Meteor | 2012/17/01 | 1000000 | 10% |
Aurelia | 2015/08/07 | 200000 | 20% |
Inferno | 2016/27/09 | 100000 | 35% |
Preact | 2015/16/08 | 600000 | 28% |
Lit | 2018/28/05 | 400000 | 60% |
Alpine.js | 2019/02/11 | 300000 | 70% |
Stimulus | 2018/06/03 | 150000 | 25% |
Solid | 2021/05/07 | 250000 | 80% |
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import items from "./data/sample.json";
const selectRowsOptions = {
rowRender: (row: any, tr: any, _index: number) => {
if (!tr.attributes) {
tr.attributes = {};
}
if (!tr.attributes.class) {
tr.attributes.class = "";
}
if (row.selected) {
tr.attributes.class += " selected";
} else {
tr.attributes.class = tr.attributes.class.replace(" selected", "");
}
return tr;
}
};
</script>
<Table selectable {items} dataTableOptions={selectRowsOptions} />
Custom Cell Renderer #
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import type { DataTableOptions } from "simple-datatables";
// Define types for the render function parameters
interface CellNode {
nodeName: string;
attributes?: Record<string, string | number>;
childNodes?: (CellNode | TextNode)[];
}
interface TextNode {
nodeName: "#text";
data: string;
}
interface TableCell {
childNodes: (CellNode | TextNode)[];
data: any;
}
interface TableRow {
attributes?: Record<string, string>;
cells: TableCell[];
}
// Type the render functions properly
const renderIcon = function (data: any, _cell: TableCell, _dataIndex: number, _cellIndex: number): string {
if (data === "Latte") {
return `☕ ${data}`;
} else if (data === "Green tea") {
return `🍵 ${data}`;
}
return `🌿 ${data}`;
};
// Price column cell manipulation
const renderButton = function (data: any, cell: TableCell, dataIndex: number, _cellIndex: number): void {
cell.childNodes.push({
nodeName: "BUTTON",
attributes: {
"data-row": dataIndex,
class: "buy-now"
},
childNodes: [
{
nodeName: "#text",
data: "Buy Now!"
}
]
});
};
// Caffeinated column cell manipulation
const renderYesNo = function (data: any, cell: TableCell, _dataIndex: number, _cellIndex: number): void {
if ([true, false].includes(data)) {
cell.childNodes = [
{
nodeName: "SPAN",
attributes: {
class: data === true ? "caffeinated" : "uncaffeinated"
},
childNodes: [
{
nodeName: "#text",
data: data === true ? "Yes" : "No"
}
]
}
];
}
};
// Numbers with styling
const renderHighLow = function (data: any, cell: TableCell, _dataIndex: number, _cellIndex: number): void {
const cellTextNode = cell.childNodes[0];
const currencyNode: CellNode = {
nodeName: "SPAN",
attributes: {
class: "currency "
},
childNodes: [cellTextNode]
};
cell.childNodes = [currencyNode];
if (data < 0) {
currencyNode.attributes!.class += "currency--loss";
} else if (data > 0) {
currencyNode.attributes!.class += "currency--profit";
} else if (data === 0) {
currencyNode.attributes!.class += "currency--zero";
}
};
const data = {
headings: ["ID", "Drink", "Price", "Caffeinated", "Profit"],
data: [
[574, "Latte", 4.0, false, 0.0],
[984, "Herbal tea", 3.0, false, 0.56],
[312, "Green tea", 3.0, true, 1.72],
[312, "Latte", 3.0, true, -1.21],
[312, "Green tea", 3.0, false, 0.0],
[312, "Green tea", 3.0, false, 0.0],
[312, "Green tea", 3.0, true, 1.72],
[312, "Latte", 3.0, true, 1.72],
[312, "Green tea", 3.0, true, -1.21],
[312, "Green tea", 3.0, false, 0.0],
[312, "Green tea", 3.0, true, 1.72],
[312, "Green tea", 3.0, true, 1.72],
[312, "Latte", 3.0, false, 0.0],
[312, "Latte", 3.0, true, 1.72],
[312, "Green tea", 3.0, false, 0.0],
[312, "Green tea", 3.0, true, 1.72],
[312, "Latte", 3.0, false, 0.0],
[312, "Latte", 3.0, true, -1.21],
[312, "Latte", 3.0, true, 1.72],
[312, "Latte", 3.0, false, 0.0],
[312, "Latte", 3.0, false, 0.0],
[312, "Latte", 3.0, true, 1.72],
[312, "Green tea", 3.0, true, -1.21],
[312, "Green tea", 3.0, true, -1.21],
[312, "Green tea", 3.0, true, -1.21]
]
} as const;
const cellRendererOptions: DataTableOptions = {
data,
rowRender: (row: TableRow, tr: TableRow, _index: number) => {
if ([true, false].includes(row.cells[3].data)) {
if (!tr.attributes) {
tr.attributes = {};
}
if (!tr.attributes.class) {
tr.attributes.class = row.cells[3].data === true ? "yes" : "no";
} else {
tr.attributes.class += row.cells[3].data === true ? " yes" : " no";
}
}
},
columns: [
{
select: 0,
hidden: true,
type: "number"
},
{
select: 1,
render: renderIcon,
type: "string"
},
{
select: 2,
render: renderButton,
type: "number"
},
{
select: 3,
render: renderYesNo,
type: "boolean"
},
{
select: 4,
render: renderHighLow,
type: "number"
}
]
};
</script>
<Table dataTableOptions={cellRendererOptions} />
Export #
Name | ReleaseDate | NpmDownloads | Growth |
---|---|---|---|
Flowbite | 2021/25/09 | 269000 | 49% |
React | 2013/24/05 | 4500000 | 24% |
Angular | 2010/20/09 | 2800000 | 17% |
Vue | 2014/12/02 | 3600000 | 30% |
Svelte | 2016/26/11 | 1200000 | 57% |
Ember | 2011/08/12 | 500000 | 44% |
Backbone | 2010/13/10 | 300000 | 9% |
jQuery | 2006/28/01 | 6000000 | 5% |
Bootstrap | 2011/19/08 | 1800000 | 12% |
Foundation | 2011/23/09 | 700000 | 8% |
Bulma | 2016/24/10 | 500000 | 7% |
Next.js | 2016/25/10 | 2300000 | 45% |
Nuxt.js | 2016/16/10 | 900000 | 50% |
Meteor | 2012/17/01 | 1000000 | 10% |
Aurelia | 2015/08/07 | 200000 | 20% |
Inferno | 2016/27/09 | 100000 | 35% |
Preact | 2015/16/08 | 600000 | 28% |
Lit | 2018/28/05 | 400000 | 60% |
Alpine.js | 2019/02/11 | 300000 | 70% |
Stimulus | 2018/06/03 | 150000 | 25% |
Solid | 2021/05/07 | 250000 | 80% |
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import { Button } from "flowbite-svelte";
import { exportJSON, exportCSV, exportTXT, exportSQL } from "simple-datatables";
import items from "./data/sample.json";
let tableComponent: any;
const handleCSV = () => {
if (tableComponent?.dataTableInstance) {
exportCSV(tableComponent.dataTableInstance, {
download: true,
lineDelimiter: "\n",
columnDelimiter: ";"
});
}
};
const handleSQL = () => {
if (tableComponent?.dataTableInstance) {
exportSQL(tableComponent.dataTableInstance, {
download: true,
tableName: "export_table"
});
}
};
const handleTXT = () => {
if (tableComponent?.dataTableInstance) {
exportTXT(tableComponent.dataTableInstance, {
download: true
});
}
};
const handleJSON = () => {
if (tableComponent?.dataTableInstance) {
exportJSON(tableComponent.dataTableInstance, {
download: true,
space: 3
});
}
};
</script>
<Table bind:this={tableComponent} {items} />
<div class="mt-4 space-x-2">
<Button onclick={handleCSV}>Export CSV</Button>
<Button onclick={handleSQL}>Export SQL</Button>
<Button onclick={handleTXT}>Export TXT</Button>
<Button onclick={handleJSON}>Export JSON</Button>
</div>
Scroll Y #
Name | Category | Brand | Price | Stock | TotalSales | Status |
---|---|---|---|---|---|---|
Apple iMac | Computers | Apple | $1,299 | 50 | 200 | In Stock |
Apple iPhone | Mobile Phones | Apple | $999 | 120 | 300 | In Stock |
Samsung Galaxy | Mobile Phones | Samsung | $899 | 80 | 150 | In Stock |
Dell XPS 13 | Computers | Dell | $1,099 | 30 | 120 | In Stock |
HP Spectre x360 | Computers | HP | $1,299 | 25 | 80 | In Stock |
Google Pixel 6 | Mobile Phones | $799 | 100 | 200 | In Stock | |
Sony WH-1000XM4 | Headphones | Sony | $349 | 60 | 150 | In Stock |
Apple AirPods Pro | Headphones | Apple | $249 | 200 | 300 | In Stock |
Asus ROG Zephyrus | Computers | Asus | $1,899 | 15 | 50 | In Stock |
Microsoft Surface Pro 7 | Computers | Microsoft | $899 | 40 | 100 | In Stock |
Samsung QLED TV | Televisions | Samsung | $1,299 | 25 | 70 | In Stock |
LG OLED TV | Televisions | LG | $1,499 | 20 | 50 | In Stock |
Canon EOS R5 | Cameras | Canon | $3,899 | 10 | 30 | In Stock |
Nikon Z7 II | Cameras | Nikon | $3,299 | 8 | 25 | In Stock |
Apple Watch Series 7 | Wearables | Apple | $399 | 150 | 500 | In Stock |
Fitbit Charge 5 | Wearables | Fitbit | $179 | 100 | 250 | In Stock |
Dyson V11 Vacuum | Home Appliances | Dyson | $599 | 30 | 90 | In Stock |
iRobot Roomba i7+ | Home Appliances | iRobot | $799 | 20 | 70 | In Stock |
Bose SoundLink Revolve | Speakers | Bose | $199 | 80 | 200 | In Stock |
Sonos One | Speakers | Sonos | $219 | 60 | 180 | In Stock |
Apple iPad Pro | Tablets | Apple | $1,099 | 50 | 150 | In Stock |
Samsung Galaxy Tab S7 | Tablets | Samsung | $649 | 70 | 130 | In Stock |
Amazon Echo Dot | Smart Home | Amazon | $49 | 300 | 800 | In Stock |
Google Nest Hub | Smart Home | $89 | 150 | 400 | In Stock | |
PlayStation 5 | Gaming Consoles | Sony | $499 | 10 | 500 | Out of Stock |
Xbox Series X | Gaming Consoles | Microsoft | $499 | 15 | 450 | Out of Stock |
Nintendo Switch | Gaming Consoles | Nintendo | $299 | 40 | 600 | In Stock |
Apple MacBook Pro | Computers | Apple | $1,299 | 20 | 100 | In Stock |
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import products from "./data/products.json";
import type { DataTableOptions } from "simple-datatables";
const scrollyOptions: DataTableOptions = {
paging: false,
scrollY: "30vh",
rowNavigation: true,
tabIndex: 1
};
</script>
<Table items={products} dataTableOptions={scrollyOptions} />
AND Search #
Try to search for “blossom 2014” in the two boxes. The OR-search will give you results that contain “2014” OR “Blossom”, while the AND-search will only return results including both “2014” and “Blossom”.
The search item separator for the extension column is ”;” so that searching for “3147;5018” will return no results, but searching for “3147” or “5018” will return the row that contains that value.
Name | Id | City | Date | Percentage |
---|---|---|---|---|
Unity Pugh | 9958 | Curicó | 2005/02/11 | 37% |
Theodore Duran | 8971 | Dhanbad | 1999/04/07 | 97% |
Kylie Bishop | 3147;5018 | Norman | 2005/09/08 | 63% |
Willow Gilliam | 3497;4067 | Amqui | 2009/29/11 | 30% |
Blossom Dickerson | 5018 | Kempten | 2007/11/09 | 17% |
Elliott Snyder | 3925;4050 | Enines | 2006/03/08 | 57% |
Castor Pugh | 9488 | Neath | 2014/23/12 | 93% |
Pearl Carlson | 6231 | Cobourg | 2014/31/08 | 100% |
Deirdre Bridges | 1579 | Eberswalde-Finow | 2014/26/08 | 44% |
Daniel Baldwin | 6095 | Moircy | 2000/11/01 | 33% |
Phelan Kane | 9519 | Germersheim | 1999/16/04 | 77% |
Quentin Salas | 1339 | Los Andes | 2011/26/01 | 49% |
Armand Suarez | 6583 | Funtua | 1999/06/11 | 9% |
Gretchen Rogers | 5393 | Moxhe | 1998/26/10 | 24% |
Harding Thompson | 2824 | Abeokuta | 2008/06/08 | 10% |
Mira Rocha | 4393 | Port Harcourt | 2002/04/10 | 14% |
Drew Phillips | 2931 | Goes | 2011/18/10 | 58% |
Emerald Warner | 6205 | Chiavari | 2002/08/04 | 58% |
Colin Burch | 7457 | Anamur | 2004/02/01 | 34% |
Russell Haynes | 8916 | Frascati | 2015/28/04 | 18% |
Brennan Brooks | 9011;7563 | Olmué | 2000/18/04 | 2% |
Kane Anthony | 8075 | LaSalle | 2006/21/05 | 93% |
Scarlett Hurst | 1019 | Brampton | 2015/07/01 | 94% |
James Scott | 3008 | Meux | 2007/30/05 | 55% |
Desiree Ferguson | 9054 | Gojra | 2009/15/02 | 81% |
Elaine Bishop | 9160 | Petrópolis | 2008/23/12 | 48% |
Hilda Nelson | 6307 | Posina | 2004/23/05 | 76% |
Evangeline Beasley | 3820 | Caplan | 2009/12/03 | 62% |
Wyatt Riley | 5694 | Cavaion Veronese | 2012/19/02 | 67% |
Blossom Mccarthy | 3547 | Patan | 2014/23/06 | 9% |
Cairo Rice | 6273 | Ostra Vetere | 2016/27/02 | 13% |
Sylvia Peters | 6829 | Arrah | 2015/03/02 | 13% |
Kasper Craig | 5515 | Firenze | 2015/26/04 | 56% |
Leigh Ruiz | 5112 | Lac Ste. Anne | 2001/09/02 | 28% |
Athena Aguirre | 5741 | Romeral | 2010/24/03 | 15% |
Riley Nunez | 5533 | Sart-Eustache | 2003/26/02 | 30% |
Lois Talley | 9393 | Dorchester | 2014/05/01 | 51% |
Hop Bass | 1024 | Westerlo | 2012/25/09 | 85% |
Kalia Diaz | 9184 | Ichalkaranji | 2013/26/06 | 92% |
Maia Pate | 6682 | Louvain-la-Neuve | 2011/23/04 | 50% |
Macaulay Pruitt | 4457 | Fraser-Fort George | 2015/03/08 | 92% |
Danielle Oconnor | 9464 | Neuwied | 2001/05/10 | 17% |
Kato Carr | 4842 | Faridabad | 2012/11/05 | 96% |
Malachi Mejia | 7133 | Vorst | 2007/25/04 | 26% |
Dominic Carver | 3476 | Pointe-aux-Trembles | 2014/14/03 | 71% |
Paki Santos | 4424;4054 | Cache Creek | 2001/18/11 | 82% |
Ross Hodges | 1862 | Trazegnies | 2010/19/09 | 87% |
Hilda Whitley | 3514 | New Sarepta | 2011/05/07 | 94% |
Roth Cherry | 4006 | Flin Flon | 2008/02/09 | 8% |
Lareina Jones | 8642 | East Linton | 2009/07/08 | 21% |
Joshua Weiss | 2289 | Saint-Léonard | 2010/15/01 | 52% |
Kiona Lowery | 5952 | Inuvik | 2002/17/12 | 72% |
Nina Rush | 7567 | Bo'lhe | 2008/27/01 | 6% |
Palmer Parker | 2000 | Stade | 2012/24/07 | 58% |
Vielka Olsen | 3745 | Vrasene | 2016/08/01 | 70% |
Meghan Cunningham | 8604 | Söke | 2007/16/02 | 59% |
Iola Shaw | 6447 | Albany | 2014/05/03 | 88% |
Imelda Cole | 4564 | Haasdonk | 2007/16/11 | 79% |
Jerry Beach | 6801 | Gattatico | 1999/07/07 | 36% |
Garrett Rocha | 3938 | Gavorrano | 2000/06/08 | 71% |
Derek Kerr | 1724 | Gualdo Cattaneo | 2014/21/01 | 89% |
Shad Hudson | 5944 | Salamanca | 2014/10/12 | 98% |
Daryl Ayers | 8276 | Barchi | 2012/12/11 | 88% |
Caleb Livingston | 3094 | Fatehpur | 2014/13/02 | 8% |
Sydney Meyer | 4576 | Neubrandenburg | 2015/06/02 | 22% |
Lani Lawrence | 8501 | Turnhout | 2008/07/05 | 16% |
Allegra Shepherd | 2576 | Meeuwen-Gruitrode | 2004/19/04 | 41% |
Fallon Reyes | 3178 | Monceau-sur-Sambre | 2005/15/02 | 16% |
Karen Whitley | 4357 | Sluis | 2003/02/05 | 23% |
Stewart Stephenson | 5350 | Villa Faraldi | 2003/05/07 | 65% |
Ursula Reynolds | 7544 | Southampton | 1999/16/12 | 61% |
Adrienne Winters | 4425 | Laguna Blanca | 2014/15/09 | 24% |
Francesca Brock | 1337 | Oban | 2000/12/06 | 90% |
Ursa Davenport | 7629 | New Plymouth | 2013/27/06 | 37% |
Mark Brock | 3310 | Veenendaal | 2006/08/09 | 41% |
Dale Rush | 5050 | Chicoutimi | 2000/27/03 | 2% |
Shellie Murphy | 3845 | Marlborough | 2013/13/11 | 72% |
Porter Nicholson | 4539 | Bismil | 2012/22/10 | 23% |
Oliver Huber | 1265 | Hannche | 2002/11/01 | 94% |
Calista Maynard | 3315 | Pozzuolo del Friuli | 2006/23/03 | 5% |
Lois Vargas | 6825 | Cumberland | 1999/25/04 | 50% |
Hermione Dickson | 2785 | Woodstock | 2001/22/03 | 2% |
Dalton Jennings | 5416 | Dudzele | 2015/09/02 | 74% |
Cathleen Kramer | 3380 | Crowsnest Pass | 2012/27/07 | 53% |
Zachery Morgan | 6730 | Collines-de-l'Outaouais | 2006/04/09 | 51% |
Yoko Freeman | 4077 | Lidköping | 2002/27/12 | 48% |
Chaim Waller | 4240 | North Shore | 2010/25/07 | 25% |
Berk Johnston | 4532 | Vergnies | 2016/23/02 | 93% |
Tad Munoz | 2902 | Saint-Nazaire | 2010/09/05 | 65% |
Vivien Dominguez | 5653 | Bargagli | 2001/09/01 | 86% |
Carissa Lara | 3241 | Sherborne | 2015/07/12 | 72% |
Hammett Gordon | 8101 | Wah | 1998/06/09 | 20% |
Walker Nixon | 6901 | Metz | 2011/12/11 | 41% |
Nathan Espinoza | 5956 | Strathcona County | 2002/25/01 | 47% |
Blossom Cameron | 4836 | Fontaine-Valmont | 1999/02/07 | 24% |
Kyra Moses | 3796 | Quenast | 1998/07/07 | 68% |
Grace Bishop | 8340 | Rodez | 2012/02/10 | 4% |
Haviva Hernandez | 8136 | Suwałki | 2000/30/01 | 16% |
Alisa Horn | 9853 | Ucluelet | 2007/01/11 | 39% |
Zelenia Roman | 7516 | Redwater | 2012/03/03 | 31% |
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import andsearch from "./data/andsearch.json";
import type { DataTableOptions } from "simple-datatables";
const andsearchOptions: DataTableOptions = {
perPageSelect: [5, 10, 15, ["All", -1]],
columns: [
{
select: 1,
searchItemSeparator: ";",
ignorePunctuation: false
},
{
select: 2,
sortSequence: ["desc", "asc"]
},
{
select: 3,
sortSequence: ["desc"]
},
{
select: 4,
cellClass: "green",
headerClass: "red"
}
],
template: (options, dom) => `<div class='${options.classes.top}'>
<div class='${options.classes.dropdown}'>
<label>
<select class='${options.classes.selector}'></select> ${options.labels.perPage}
</label>
</div>
<div class='${options.classes.search}'>
<input class='${options.classes.input}' placeholder='OR search' type='search' title='${options.labels.searchTitle}'${dom.id ? ` aria-controls="${dom.id}"` : ""}>
<input class='${options.classes.input}' placeholder='AND search' type='search' data-and="true" title='${options.labels.searchTitle}'${dom.id ? ` aria-controls="${dom.id}"` : ""}>
</div>
</div>
<div class='${options.classes.container}'${options.scrollY.length ? ` style='height: ${options.scrollY}; overflow-Y: auto;'` : ""}></div>
<div class='${options.classes.bottom}'>
<div class='${options.classes.info}'></div>
<nav class='${options.classes.pagination}'></nav>
</div>`
};
</script>
<Table items={andsearch} dataTableOptions={andsearchOptions} />
DataTable Event Callbacks #
The DataTable component exposes callback props that allow you to hook into the underlying simple-datatables library events. These callbacks provide access to the table lifecycle and user interactions.
Initialization Events #
onInitStart
Called when table initialization begins. Useful for showing loading indicators.
typescriptonInitStart?: () => void
onInitComplete
Called when the table is fully initialized and ready for interaction.
typescriptonInitComplete?: (dataTable: DataTable) => void
onInitError
Called if table initialization fails.
typescriptonInitError?: (error: Error) => void
Data Events #
onRefresh
Called when the table data is refreshed.
typescriptonRefresh?: (dataTable: DataTable) => void
onUpdate
Called when the table is updated (e.g., after sorting or filtering).
typescriptonUpdate?: (dataTable: DataTable) => void
User Interaction Events #
onSort
Called when a column is sorted.
typescriptonSort?: (column: number, direction: string, dataTable: DataTable) => void
onSearch
Called when a search is performed.
typescriptonSearch?: (query: string, matched: any[], dataTable: DataTable) => void
onPage
Called when pagination changes.
typescriptonPage?: (page: number, dataTable: DataTable) => void
Selection Events (when selectable=true) #
onSelectRow
Called when a row is selected.
typescriptonSelectRow?: (rowIndex: number, event: Event, dataTable: DataTable) => void
onSelectAll
Called when all rows are selected.
typescriptonSelectAll?: (dataTable: DataTable) => void
onDeselectRow
Called when a row is deselected.
typescriptonDeselectRow?: (rowIndex: number, dataTable: DataTable) => void
onDeselectAll
Called when all rows are deselected.
typescriptonDeselectAll?: (dataTable: DataTable) => void
- Svelte
<script lang="ts">
import { Table } from "@flowbite-svelte-plugins/datatable";
import items from "./data/sample.json";
import type { DataTable } from "simple-datatables";
import { Spinner } from "flowbite-svelte";
let isTableLoading = true;
let tableInstance: DataTable | null = null;
function handleInitStart(): void {
console.log("Table initialization started");
isTableLoading = true;
}
function handleInitComplete(dataTable: DataTable): void {
console.log("Table ready:", dataTable);
isTableLoading = false;
}
function handleInitError(error: Error): void {
console.error("Table initialization failed:", error);
isTableLoading = false;
}
function handleSort(column: number, direction: string, dataTable: DataTable): void {
console.log(`Column ${column} sorted ${direction}`);
}
function handleSearch(query: string, matched: any[], dataTable: DataTable): void {
console.log(`Search: "${query}" found ${matched.length} results`);
}
function handleRowSelect(rowIndex: number, event: Event, dataTable: DataTable): void {
console.log(`Row ${rowIndex} selected`);
}
</script>
{#if isTableLoading}
<div class="loading-spinner">
<div class="h-8 w-8 animate-spin rounded-full border-b-2 border-blue-600"></div>
<span>Loading table...</span>
</div>
{/if}
<Table {items} bind:isLoading={isTableLoading} bind:dataTableInstance={tableInstance} onInitStart={handleInitStart} onInitComplete={handleInitComplete} onInitError={handleInitError} onSort={handleSort} onSearch={handleSearch} onSelectRow={handleRowSelect} selectable={true} dataTableOptions={selectRowsOptions} />
Component data #
The component has the following props, type, and default values. See types page for type information.