🚀. Socket Launch Week Day 3:Socket Firewall Now Blocks Malicious VS Code and Open VSX Extensions.Learn more
Sign In

@isoftdata/svelte-table

Package Overview
Dependencies
Maintainers
12
Versions
127
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@isoftdata/svelte-table

latest
npmnpm
Version
2.12.4
Version published
Maintainers
12
Created
Source

Svelte Table

For the Pagination and Td components, See Pagination.md and Td.md.

Screenshot of the table component

Install

pnpm i @isoftdata/svelte-table

Breaking changes

2.0.0

  • Require Svelte 5
  • Slots -> Snippets
    • no-rows and footer-row had to be renamed to noRows and footerRow
    • Removed footer snippet/slot
  • Events -> Callbacks
  • columnInfo is now powered by runes instead of a writable store
    • Use columnInfo.current rather than $columnInfo to access its value
    • Type is now ColumnInfoRunicStore (a class) instead of ColumnInfoStore

A Note on Types

This component uses a generic type R to represent the type of a single row passed to the rows prop of this table. Then, R is extended by another type, IndexedRow, which includes the uuid and originalIndex properties. The original rows array you pass in will not be mutated, but the contents of filteredRows, sortedRows, and currentPageRows will be of type IndexedRow.

Props

NameTypeDescriptionDefault Value
borderedbooleanWhether the table is bordered or not.true
classstringAny extra classes to apply to the table.""
columnClickedMethod(column: Column, direction: SortDirection) => voidCalled when a column is clicked. Should update previousSortOrder, previousSortDirection, previousSortColumn, and sortedRows.defaultColumnClicked
columnHidingEnabledbooleanWhen enabled, the user will be able to right click a column header and hide/show it.false
columnPinningEnabledbooleanWhen enabled, the user will be able to right click a column header and pin or unpin it.false
columnResizingEnabledbooleanWhen enabled, the user will be able to drag on the edge of a column header and resize it.false
columnsArray<Column>The definition of the columns. See columns docs below.Required
currentPageNumbernumberThe current page number.1
currentPageRowsArray<IndexedRow>It's the current page of rows to show, computed based on sortedRows, currentPageNumber, and perPageCount. The table component will set this.sortedRows.slice(0, perPageCount)
filterstringThe filter string.""
filterColumnClassClassValueThe class for the filter column in the header row."col-lg-2 col-md-4 col-sm-6 align-self-end"
filterDisabledbooleanWhether the filter input is disabled or not.false
filterEnabledbooleanWhether to show the filter input above the table.false
filterLabelstringThe label for the filter input."Filter"
filterMethod(filter: string, rows: Array<R>, columns: Array<Column>) => Array<IndexedRow>A function that filters the rows based on the given filter string. Should return the rows that match the filter, with uuid (if not already specified in rows) and originalIndex properties added.defaultFilter
filterPlaceholderstringThe placeholder text for the filter input."Filter"
filterPropsArray<string> | falseAn array of strings that represent the properties to filter on. If false, uses all column properties.false
filterReadonlybooleanWhether the filter input is readonly or not.false
filteredRowsArray<IndexedRow>An array of objects that represent the filtered table rows. You probably don't need to interact with this.filterMethod("", rows, columns)
filterLazyboolean | numberThe laziness of the filter input. true means the value will update onchange, false means oninput. A millisecond number value indicates the delay from the last UI interaction(debouncing). Consider setting a numeric value if your filter change needs to make a network call.false
footersArray<FooterValue>Values to display in the footer. Calculated automatically by the Table component.[]
rowMatchesFilterMethod(filter: string, row: R, props: Array<RowProperties<R>>) => booleanA function that determines whether the a given row matches the filter. Useful if you want to change how rows are matched by the filter without overriding the whole filterMethod. See Custom Filter Logic for more detailsundefined
headerColumnClassClassValueWhen the filter is enabled, a header slot will be inserted to the area to the left of the filter input. This is the column class for that yield's parent div."col"
headerRowClassClassValueThe class for the table header row."form-row mr-auto"
hideButtonClassClassValueAny other classes to add the the "hide" dropdown button.""
hoverbooleanWhether the table will highlight the hovered row.true
idPropK | "uuid"Property on the objects in the rows Array that uniquely identifies the row. Used for lazy sorting."uuid"
lastClickedIdForRangenumber | IndexedRow[keyof R | "uuid"] | undefinedThe last clicked ID for the range selection mode.undefined
lazySortbooleanWhen true, the table will only be resorted when the user clicks on a column header (not in real time as data changes). See idProp.false
multiSelectEnabledbooleanWhether to allow selecting multiple rows at a timetrue
localStorageKeystring | undefinedIf specified, the localstorage key where user-modified column info such as visibility and resizing are savedundefined
parentClassClassValueCSS class(es) to apply to the <table>'s parent div.""
parentStylestringCSS style(s) to apply to the <table>'s parent div.""
perPageCountnumberThe number of rows to display per page. Enables pagination if > 00
responsivebooleanWhether the table is responsive or not.false
rowsArray<R>An array of objects that represent the table rows.Required
rowSelectionIdPropK | "uuid"The property to use as the unique identifier for each row in the row selection feature."uuid"
rowSelectionRequiresModKeybooleanWhether the row selection feature requires a modifier key or not.false
selectionEnabledbooleanWhether the row selection feature is enabled or not.false
selectionMode"SINGLE" | "RANGE" | nullThe selection mode for the row selection feature. When multiSelectEnabled is true, both selection modes will allow you to select multiple rows.null
showFilterLabelbooleanWhether the filter label is shown or not.false
showFooterbooleanDefines if a <tfoot> should be shown. See footers slot below.false
size"sm" | ""The size of the table."sm"
sortedRowsArray<IndexedRow>The rows, but sorted based on sortColumn and sortDirection, and optionally filtered(See filter options below). The table component will set this.filteredRows
sortDirection"ASC" | "DESC"The direction of the current sort."ASC"
stickyHeaderbooleanWhether the table header will stay at the top when scrolling the table.false
stripedbooleanWhether the table is striped or not.true
tableIdstringThe unique identifier of the table.uuid()
totalItemsCountnumberThe total number of items in the data set. Necessary for serverside pagination and sorting since the rows array won't have every item for every page.0
treebooleanWhen true, enables a bunch of tree-specific features. Required if you want to use TreeRows.false
columnResizingEnabledbooleanWhether the user is allowed to resizing table columnsfalse

When columnResizingEnabled is true, any <Td> component children will have a css rule of overflow: hidden; applied. This makes it a column sized so small that the text doesn't fit causes the text to truncate instead of clipping outside the bounds of the cell. This is intended behavior and how most table's with resizable columns work.

Advanced Props

You usually won't have to use these, but they're here just in case.

NameTypeDescriptionDefault Value
previousSortColumnColumn | undefinedThe previous sort column.undefined
previousSortDirection"ASC" | "DESC" | undefinedThe previous sort direction.undefined
previousSortOrderArray<IndexedRow & { order: number }>An array of objects that represent the previous sort order.[]
selectedRowIdsArray<string | number | R[K]>An array of strings, numbers, or objects that represent the selected row IDs.[]
sortColumnColumn | undefinedThe current sort column.undefined
columnInfoWritable<Record<string, Column & { visible: boolean }>>A store containing column metadata. Mostly used for tracking column visibility. Read-only.Handled by the component

Columns Definition

An Array of Objects, where the Objects have the following properties:

NameTypeDescription
align"left" | "right" | "center"Direction to align columns (and Tds in the column)
classClassValueSets the class of the column header.
defaultSortColumnbooleanWhen Svelte initalizes the view, this is the column that will be sorted by.
defaultSortDirection"ASC" | "DESC"'ASC' or 'DESC' are the only valid options. Defaults to 'ASC'
ellipsisbooleanWhether to apply text-overflow: ellipsis to the column
footerSee BelowFooter options for this column
formatter(value: unknown) => unknownA formatter function to use on this column. The return value will be shown in the td.
hideForPrintbooleanWhether to hide this column when printing
iconstringThe FontAwesome icon classes for the icon you want to display, without the leading fa-
iconLeftstringIf you want the icon to display to the left of the name, set this to true.
iconPrefixstringThe FA prefix to apply. Defaults to fas.
minWidthstringWill be passed in as the value for the CSS min-width property on the <th> style attribute.
namestringThe name of the column as it will be displayed in the table column header
numericbooleanWhen true, right aligns the column (and Tds in the column) and applies font-variant-numeric: tabular-nums;
propertystringThe property name of the column. Must map to a property in the objects defined in rows(see above)
sortType"ALPHA_NUM" | "STANDARD" | falseHow to sort this column. Default is STANDARD. ALPHA_NUM is better for mixed number and letter columns. false will disallow sorting this column.
titlestringThe th's title
unhidablebooleanWhether to disallow hiding the column.
widthstringWill be passed in as the value for the CSS width property on the <th> style attribute.
wrapbooleanIf true, will allow column names to wrap.

The Column type is generic. If you pass the type of one of your rows to it, then the property property will be strongly to properties of that object. This is optional for backwards compatability reasons.

Passing your row type to the Column type allows for better intellisense for column properties.

Below are the properties of the footer object

NameTypeDescription
fn"COUNT" | "AVG" | "SUM"A function to call on each row when calculating that column's footer.
altPropertystringIf you want to compute footers off a different property than column.property, specify it here.
formatCurrencybooleanIf true, will format the column as currenty.
requiredValueunknownIf specified, only column values matching this value will be included in calculations

You can also pass a custom callback function to footer.fn, which changes some of the property types as shown below. The properties that are not repeated below behave the same whether you use a built-in or custom reducer fn.

NameTypeDescription
fn(previousValue: FooterReducerValue<R>, currentValue: FooterReducerValue<R>) => FooterReducerValue<R>A function to call on each row when calculating that column's footer. currentValue is the value of row[property] or row[altProperty] if specified.
initialValueFooterReducerValue<R>The initial value of the reducer function.

FooterReducerValue is a union of string, number, and the property types of the row object

Snippets

NameArgs TypeDescription
children[{ row: R & { originalIndex: number; uuid: string }; index: number; visibleColumnsCount: number }]This represents one row of the table
header[]Only available if filterEnabled is true. This yields inside the first column of a <div class="form-row"></div> above the table. The 2nd column contains the filter input itself.
noRows[{ visibleColumnsCount: number }]Shown when rows.length === 0
body[{ rows: Array<R & { originalIndex: number; uuid: string }> }]If you want to specify all of the contents of the tbody yourself, you can do so here. Specifying anything for this slot will prevent the "default" and "noRows" slot from being rendered.
footerRow[{ footers: Array<FooterValue> }]If showFooter is enabled, This is the tr where the footer values are shown.

Callbacks

  • pageChange - Fired when the page changes. ({ pageNumber: number }) => void

Methods

There are a couple methods you can access by calling them on the Table component instance, which you can access using bind:this.

  • rowClick(row: IndexedRow): void - handles the logic for clicking on and selecting rows
  • setPageVisibleByItemId({ id, keyName }: { id: number | string; keyName: K }) - Given an item's id, and a keyName, sets the current page to be the one containing that item
  • expandRow(rowId: (typeof selectedRowIds)[0], expanded = true) - Tree mode only. Expands a row given its id.
  • setColumnVisibility(columnProperties: Array<string> | string, visible: boolean) - Sets the visibility of the specified column(s)
  • setColumnVisibilityWatch(columnProperties: Array<string> | string, getVisible: () => boolean) - Sets the visibility of the specified column(s) whenever the value of getVisible changes. Call this in onMount or an effect.

Context

A handful of values are set as context of the component so they're accessible to their children.

  • selectedRowIds - same as listed under Props
  • columnInfo - Map of column properties to column definitions (Record<string, Column & { visible: boolean }>)

Examples

There are three ways to use this component, with the difference lying in which slots are specified, which affects how table body is rendered. They are listed in order from "most automatic" to "most manual".

Method 1 : "Full Auto" (No Default or "body" slots)

For this method, all you have to do is specify the rows and columns props on the Table, and do not specify anything for the default slot. For each column in each row, the table component will render a td, getting the value from that column's property prop, applying any formatter function if specified for that column.

This is the simplest method, and will work for most use cases that don't need to insert any extra HTML into the tds.

<Table
	{rows}
	{columns}
/>

You can still specify other slots, for example, "no-rows" and "header", just not the default slot.

<Table
	{rows}
	{columns}
>
	{#snippet noRows({ visibleColumnsCount })}
		<tr>
			<td
				class="text-center"
				colspan={visibleColumnsCount}>No rows here bro
			</td>
		</tr>
	{/snippet}
	{#snippet header()}
		<Input
			label="Items per page"
			class="mb-3"
			type="number"
			bind:value={perPageCount}
		/>
	{/snippet}
</Table>

Method 2 : "Semi Auto" (Default Slot)

For this method, you specify a single row's contents in the default slot, and access each row's value by adding let:row to the Table. These rows come from currentPageRows, so they've already been filtered, sorted, and paginated.

With this method, you can insert extra HTML into any of the td/Tds, but you have to specify them all yourself.

As above, you can still specify other slots when using this method.

<Table
	{rows}
	{columns}
>
	{#snippet children({ row })}
		<tr>
			<Td property="id">
				{row.id}
			</Td>
			<Td property="name">
				{row.name}
			</Td>
			<Td property="email">
				{row.email}
			</Td>
			<Td property="deleted">
				<Button color="danger" icon="trash">Delete<Button>
			</Td>
		</tr>
	{/snippet}
</Table>

Method 3 : "Full Manual" ("body" Slot)

With this method, you put anything you want to render in the tbody into the "body" snippet. You can access the currentPageRows with the rows property of the snippet, and the # of visible columns with visibleColumnsCount, as shown below.

This method is the most similar to how our Ractive table component works, and requires you to specify the whole contents of the tbody.

The contents of the "children" and "noRows" snippets will be ignored when using this method, but the "header" snippet will still work.

<Table
	{rows}
	{columns}
>
	{#snippet body({ rows, visibleColumnsCount })}
		{#each rows as row}
			<tr>
				<Td property="id">
					{row.id}
				</Td>
				<Td property="name">
					{row.name}
				</Td>
				<Td property="email">
					{row.email}
				</Td>
				<Td property="deleted">
					<Button color="danger" icon="trash">Delete<Button>
				</Td>
			</tr>
		{:else}
			<tr colspan={visibleColumnsCount}>No Rows.</td>
		{/each}
	{/snippet}
</Table>

Bonus Method: As a Tree Control

See TreeRow.

Extending

Guides on how to extend the Table component for various common use cases

Using the Table with server-side pagination/sorting/filtering

There is a fully-functioning demo at /serverside on the demo page.

To successfully use the Table component in a context where the server/API is handling the sorting/pagination/filtering, you'll want to ensure you do the following:

  • Pass the sortDirection, sortColumn, perPageCount, currentPageNumber, & totalItemsCount props.
  • Set the filterEnabled prop to false. Alternatively, if your backend API has the ability to filter by string input, you can leave it true and pass an async function to filterMethod prop that either sets the rows or performs a state change with the now-filtered rows.
  • Pass a pageChange callback.
  • Pass a columnClickedMethod function. This will be called whenever the user clicks on a column.
  • Make sure you pass false for the sortType property on the columns definition for any columns which lack sorting support by your backend API.
  • Don't use the let:rows method of handling the rows. Instead, use the "Full Manual" option without a let:rows declaration. Example:
<Table
	{rows}
	{columns}
	sortDirection={orderByDirection}
	sortColumn={columns.find(column => column.property === orderByColumn)}
	perPageCount={pageSize}
	{currentPageNumber}
	{totalItemsCount}
>
	{#snippet body({rows})}
		{#each rows as row}
			<tr>
				<!-- your Tds here -->
			</tr>
		{/each}
	{/snippet}
</Table

Custom Filter Logic

Various ways to change how the table filters rows, ordered by complexity.

filterProps

By default, the table will check the filter against every property in the columns array. If you want to match against a different set of properties, you can specify them with the filterProps prop.

<Table
	{rows}
	{columns}
	filterProps={['foo', 'bar']}
></Table>

rowMatchesFilterMethod

By default, the table will show any rows whose filterProps (or column properties) contain a substring of the filter string. If you want to override that logic, you can pass a rowMatchesFilterMethod.

In simple cases, you can just use the default method, and add your own logic as well:

function rowMatchesFilterMethod(filter: string, row: R, props: Array<RowProperties<R>>) {
	return table?.defaultRowMatchesFilter(...args) || someOtherLogic()
}

But you can use all your own logic too.

function rowMatchesFilterMethod(filter: string, row: R, props: Array<RowProperties<R>>) {
	return props.some(prop => {
		// ...
	})
}

filterMethod

If you really need to override some larger part of the filter logic, you can pass the filterMethod prop. This isn't recommended and is mostly a holdover from the original version of the component, but you can use it if you want to.

Column Resizing

Enable the columnResizingEnabled prop, and pass the localStorageKey prop if you want to save the column sizes (and whether it's shown/hidden) to localstorage. These values are also stored in the columnInfo store if you want to do something else with it.

See Also

TreeRow

To use this component as a tree control, add the tree prop to your Table, use the TreeRow Component.

Td

You can use the Td Component in your table to support hiding columns.

Pagination

The table component will handle the Pagination Component for you.

FAQs

Package last updated on 03 Jun 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts