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 simple-datatables
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} />
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>
Component data #
The component has the following props, type, and default values. See types page for type information.