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
Flowbite2021/25/0926900049%
React2013/24/05450000024%
Angular2010/20/09280000017%
Vue2014/12/02360000030%
Svelte2016/26/11120000057%
Ember2011/08/1250000044%
Backbone2010/13/103000009%
jQuery2006/28/0160000005%
Bootstrap2011/19/08180000012%
Foundation2011/23/097000008%
Bulma2016/24/105000007%
Next.js2016/25/10230000045%
Nuxt.js2016/16/1090000050%
Meteor2012/17/01100000010%
Aurelia2015/08/0720000020%
Inferno2016/27/0910000035%
Preact2015/16/0860000028%
Lit2018/28/0540000060%
Alpine.js2019/02/1130000070%
Stimulus2018/06/0315000025%
Solid2021/05/0725000080%
  • 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
Flowbite2021/25/0926900049%
React2013/24/05450000024%
Angular2010/20/09280000017%
Vue2014/12/02360000030%
Svelte2016/26/11120000057%
Ember2011/08/1250000044%
Backbone2010/13/103000009%
jQuery2006/28/0160000005%
Bootstrap2011/19/08180000012%
Foundation2011/23/097000008%
Bulma2016/24/105000007%
Next.js2016/25/10230000045%
Nuxt.js2016/16/1090000050%
Meteor2012/17/01100000010%
Aurelia2015/08/0720000020%
Inferno2016/27/0910000035%
Preact2015/16/0860000028%
Lit2018/28/0540000060%
Alpine.js2019/02/1130000070%
Stimulus2018/06/0315000025%
Solid2021/05/0725000080%
  • 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 iMacComputersApple$1,29950200In Stock
Apple iPhoneMobile PhonesApple$999120300In Stock
Samsung GalaxyMobile PhonesSamsung$89980150In Stock
Dell XPS 13ComputersDell$1,09930120In Stock
HP Spectre x360ComputersHP$1,2992580In Stock
Google Pixel 6Mobile PhonesGoogle$799100200In Stock
Sony WH-1000XM4HeadphonesSony$34960150In Stock
Apple AirPods ProHeadphonesApple$249200300In Stock
Asus ROG ZephyrusComputersAsus$1,8991550In Stock
Microsoft Surface Pro 7ComputersMicrosoft$89940100In Stock
Samsung QLED TVTelevisionsSamsung$1,2992570In Stock
LG OLED TVTelevisionsLG$1,4992050In Stock
Canon EOS R5CamerasCanon$3,8991030In Stock
Nikon Z7 IICamerasNikon$3,299825In Stock
Apple Watch Series 7WearablesApple$399150500In Stock
Fitbit Charge 5WearablesFitbit$179100250In Stock
Dyson V11 VacuumHome AppliancesDyson$5993090In Stock
iRobot Roomba i7+Home AppliancesiRobot$7992070In Stock
Bose SoundLink RevolveSpeakersBose$19980200In Stock
Sonos OneSpeakersSonos$21960180In Stock
Apple iPad ProTabletsApple$1,09950150In Stock
Samsung Galaxy Tab S7TabletsSamsung$64970130In Stock
Amazon Echo DotSmart HomeAmazon$49300800In Stock
Google Nest HubSmart HomeGoogle$89150400In Stock
PlayStation 5Gaming ConsolesSony$49910500Out of Stock
Xbox Series XGaming ConsolesMicrosoft$49915450Out of Stock
Nintendo SwitchGaming ConsolesNintendo$29940600In Stock
Apple MacBook ProComputersApple$1,29920100In 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-4OpenAIMarch 20231 trillionNatural Language Processing
BERTGoogleOctober 2018340 millionNatural Language Understanding
DALL-E 2OpenAIApril 20223.5 billionImage Generation
T5GoogleOctober 201911 billionText-to-Text Transfer
GPT-3.5OpenAINovember 2022175 billionNatural Language Processing
CodexOpenAIAugust 202112 billionCode Generation
PaLM 2GoogleMay 2023540 billionMultilingual Understanding
LaMDAGoogleMay 2021137 billionConversational AI
CLIPOpenAIJanuary 2021400 millionImage and Text Understanding
XLNetGoogleJune 2019340 millionNatural Language Processing
MeenaGoogleJanuary 20202.6 billionConversational AI
BigGANGoogleSeptember 2018UnlimitedImage Generation
ElectraGoogleMarch 202014 millionNatural Language Understanding
Swin TransformerMicrosoftApril 202188 millionVision Processing
GPT-NeoX-20BEleutherAIApril 202220 billionNatural Language Processing
Ernie 3.0BaiduJuly 202110 billionNatural Language Processing
Turing-NLGMicrosoftFebruary 202017 billionNatural Language Processing
Wu Dao 2.0Beijing Academy of AIJune 20211.75 trillionMultimodal Processing
JukeboxOpenAIApril 20201.2 billionMusic Generation
StyleGAN2NVIDIAFebruary 2020UnlimitedImage Generation
FLANGoogleDecember 2021137 billionFew-shot Learning
GShardGoogleJune 2020600 billionMultilingual Understanding
AlphaFoldDeepMindDecember 2020UnknownProtein Folding
GPT-JEleutherAIJune 20216 billionNatural Language Processing
M6AlibabaDecember 202010 billionMultimodal Processing
Megatron-Turing NLGNVIDIA & MicrosoftOctober 2021530 billionNatural Language Processing
DeepSpeedMicrosoftFebruary 2020Not disclosedAI 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
Flowbite2021/25/0926900049%
React2013/24/05450000024%
Angular2010/20/09280000017%
Vue2014/12/02360000030%
Svelte2016/26/11120000057%
Ember2011/08/1250000044%
Backbone2010/13/103000009%
jQuery2006/28/0160000005%
Bootstrap2011/19/08180000012%
Foundation2011/23/097000008%
Bulma2016/24/105000007%
Next.js2016/25/10230000045%
Nuxt.js2016/16/1090000050%
Meteor2012/17/01100000010%
Aurelia2015/08/0720000020%
Inferno2016/27/0910000035%
Preact2015/16/0860000028%
Lit2018/28/0540000060%
Alpine.js2019/02/1130000070%
Stimulus2018/06/0315000025%
Solid2021/05/0725000080%
  • 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
Flowbite2021/25/0926900049%
React2013/24/05450000024%
Angular2010/20/09280000017%
Vue2014/12/02360000030%
Svelte2016/26/11120000057%
Ember2011/08/1250000044%
Backbone2010/13/103000009%
jQuery2006/28/0160000005%
Bootstrap2011/19/08180000012%
Foundation2011/23/097000008%
Bulma2016/24/105000007%
Next.js2016/25/10230000045%
Nuxt.js2016/16/1090000050%
Meteor2012/17/01100000010%
Aurelia2015/08/0720000020%
Inferno2016/27/0910000035%
Preact2015/16/0860000028%
Lit2018/28/0540000060%
Alpine.js2019/02/1130000070%
Stimulus2018/06/0315000025%
Solid2021/05/0725000080%
  • 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.

References #