preline
Version:
Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.
429 lines (329 loc) • 15.9 kB
Markdown
# Datatables
Datatables solutions for massive datasets.
[](https://www.npmjs.com/package/@preline/datatable) [](https://opensource.org/licenses/MIT) [](https://preline.co/plugins/datatables.html)
## Contents
- [Overview](#overview)
- [Installation](#installation)
- [Basic usage](#basic-usage)
- [CSS](#css)
- [Configuration Options](#configuration-options)
- [JavaScript API](#javascript-api)
- [Events](#events)
- [Common Patterns](#common-patterns)
- [License](#license)
## Overview
The Datatables component provides a powerful data table interface with sorting, searching, pagination, and row selection capabilities. It integrates with DataTables.net for advanced table functionality.
**Key Features:**
- Column sorting
- Search functionality
- Pagination
- Row selection (single and multiple)
- Customizable paging controls
- Integration with DataTables.net
- Programmatic control via JavaScript API
- Event system for table interactions
## Installation
To get started, install DataTable plugin via npm, else you can skip this step if you are already using Preline UI as a package.
```bash
npm i jquery datatables.net-dt @preline/datatable
```
### CSS
Use [`@source`](https://tailwindcss.com/docs/functions-and-directives#source-directive) to register the plugin's JavaScript path for Tailwind CSS scanning, then [`@import`](https://tailwindcss.com/docs/functions-and-directives#import-directive) the plugin's CSS files into your Tailwind CSS file.
```css
@import "tailwindcss";
/* @preline/datatable */
@source "../node_modules/@preline/datatable/*.js";
@import "./node_modules/@preline/datatable/variants.css";
@import "./node_modules/@preline/datatable/theme.css";
.dt-layout-row:has(.dt-search),
.dt-layout-row:has(.dt-length),
.dt-layout-row:has(.dt-paging) {
display: none !important;
}
```
### JavaScript
Include the JavaScript that powers the interactive elements near the end of your `</body>` tag:
```html
<script src="./node_modules/jquery/dist/jquery.min.js"></script>
<script src="./node_modules/datatables.net-dt/js/dataTables.dataTables.min.js"></script>
<script src="./node_modules/@preline/datatable/index.js"></script>
```
### Manual Initialization
Use the `non-auto` entry if you need manual initialization. In this mode, automatic initialization on page load is not included, so the component should be initialized explicitly.
```html
<script src="./node_modules/jquery/dist/jquery.min.js"></script>
<script src="./node_modules/datatables.net-dt/js/dataTables.dataTables.min.js"></script>
<script type="module">
import HSDataTable from "@preline/datatable/non-auto.mjs";
new HSDataTable(document.querySelector("#datatable"));
</script>
```
### Via Bundler
When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module. `jQuery` and `DataTable` are referenced as globals, so expose them on `window` before importing the plugin.
`@preline/datatable` is the auto-init entry: it scans the DOM and initializes matching elements automatically.
```js
import jQuery from "jquery";
window.jQuery = jQuery;
window.$ = jQuery;
import DataTable from "datatables.net";
window.DataTable = DataTable;
import "@preline/datatable";
```
`@preline/datatable/non-auto` is the manual entry: use it when you want explicit control over when initialization happens, either via `autoInit()` or by creating a specific instance yourself.
```js
import jQuery from "jquery";
window.jQuery = jQuery;
window.$ = jQuery;
import DataTable from "datatables.net";
window.DataTable = DataTable;
import HSDataTable from "@preline/datatable/non-auto";
HSDataTable.autoInit();
// Or initialize a specific element manually
const el = document.querySelector("#datatable");
if (el) new HSDataTable(el);
```
### TypeScript
This package ships with TypeScript type definitions. No additional `@types/` package is needed.
## Basic usage
The following example demonstrates the minimal HTML structure required for a datatable component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The table supports sorting, searching, and pagination.
```html
<div data-hs-datatable>
<table>
<thead>
<tr>
<th scope="col">
Name
<svg class="hidden hs-datatable-ordering-desc:block" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
<svg class="hidden hs-datatable-ordering-asc:block" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>
</th>
<th scope="col">
Age
<svg class="hidden hs-datatable-ordering-desc:block" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
<svg class="hidden hs-datatable-ordering-asc:block" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 15-6-6-6 6"/></svg>
</th>
<th scope="col" class="--exclude-from-ordering">
Action
</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Brown</td>
<td>45</td>
<td>
<button type="button">Delete</button>
</td>
</tr>
</tbody>
</table>
<div style="display: none;" data-hs-datatable-paging>
<button type="button" data-hs-datatable-paging-prev>
<span aria-hidden="true">«</span>
<span class="sr-only">Previous</span>
</button>
<div data-hs-datatable-paging-pages></div>
<button type="button" data-hs-datatable-paging-next>
<span class="sr-only">Next</span>
<span aria-hidden="true">»</span>
</button>
</div>
</div>
```
**Structure Requirements:**
- `data-hs-datatable`: Required on the container element
- Standard HTML `<table>` structure with `<thead>` and `<tbody>`
- Optional paging controls with `data-hs-datatable-paging`
- Optional search input with `data-hs-datatable-search`
- Optional row selection checkboxes
**Initial State:**
- Table displays all data
- Sorting is enabled on columns (unless excluded)
- Pagination controls are hidden if not needed
## CSS
Please add the following CSS to the head. This is necessary because Datatables.net does not allow to add custom markup with options disabled, such as `paging: false` or `searching: false`.
```html
<style>
.dt-layout-row:has(.dt-search),
.dt-layout-row:has(.dt-length),
.dt-layout-row:has(.dt-paging) {
display: none ;
}
</style>
```
## Configuration Options
### Data Options
> **Note:** Please note that this component requires the use of the [Datatables.net](https://datatables.net/) plugin. Most options available in the plugin are available in our wrapper.
Data options are specified in the `data-hs-datatable` attribute as a JSON object.
| Option | Target Element | Type | Default | Description |
| --- | --- | --- | --- | --- |
| `data-hs-datatable` | Container | - | - | Activate a Datatable by specifying on an element. Should be added to the container. |
| `:pageBtnClasses` | Inside `data-hs-datatable` | string | `"-"` | Sets the specified classes to each paging element inside the `data-hs-datatable-paging-pages`. |
| `:rowSelectingOptions.selectAllSelector` | Inside `data-hs-datatable` | string (CSS selector) | `"[data-hs-datatable-row-selecting-all]"` | A valid CSS selector (the element must be a checkbox or radio button), when the element is changed, all elements specified by `rowSelectingOptions.individualSelector` (or, if not specified, then `data-hs-datatable-row-selecting-individual`) on the current page will be changed. |
| `:rowSelectingOptions.individualSelector` | Inside `data-hs-datatable` | string (CSS selector) | `"[data-hs-datatable-row-selecting-individual]"` | A valid CSS selector (the element must be a checkbox or radio button), affects the change of the element specified in `rowSelectingOptions.selectAllSelector`, if not all elements are selected on the current page, then it switches to `unchecked` state, if vice versa, then in `checked`. |
**Example:**
```html
<div data-hs-datatable='{
"pageBtnClasses": "px-3 py-1 border rounded",
"rowSelectingOptions": {
"selectAllSelector": "#hs-select-all",
"individualSelector": ".hs-row-checkbox"
}
}'>
<!-- Table structure -->
</div>
```
### Class Options
CSS class modifiers use `--` prefix to control datatable behavior.
| Class Modifier | Target Element | Purpose |
| --- | --- | --- |
| `--exclude-from-ordering` | Table header (`<th>`) | A modifier that allows you to disable the ordering functionality in a column. Should be added to the thead column. |
### Required CSS Classes / Data Attributes
These data attributes define the structure and must be present for specific features to function.
| Data Attribute | Required On | Purpose |
| --- | --- | --- |
| `data-hs-datatable-search` | Input element | Defines which element will be responsible for searching in the datatable (must be an `input`). |
| `data-hs-datatable-page-entities` | Select element | Determines which element will be responsible for switching the number of elements on the page (must be a `select`, depends on the change event). |
| `data-hs-datatable-paging` | Container element | Defines a paging container, that contains pagination, next and previous buttons. |
| `data-hs-datatable-paging-prev` | Button element | Defines a previous button element. |
| `data-hs-datatable-paging-next` | Button element | Defines a next button element. |
| `data-hs-datatable-row-selecting-all` | Checkbox/Radio element | Defines a "Select all" checkbox/radio, if it's not specified in the `rowSelectingOptions.selectAllSelector` parameter. |
| `data-hs-datatable-row-selecting-individual` | Checkbox/Radio element | Defines a checkbox/radio that will be responsible for selecting a specific row if it is not specified in the `rowSelectingOptions.individualSelector` parameter. |
| `data-hs-datatable-info` | Container element | Defines an info container. |
| `data-hs-datatable-info-from` | Element | Defines an element that showing `start` number. |
| `data-hs-datatable-info-to` | Element | Defines an element that showing `end` number. |
| `data-hs-datatable-info-length` | Element | Defines an element that showing `recordsTotal` number. |
### Tailwind Modifiers
| Name | Description |
| --- | --- |
| `hs-datatable-ordering-asc:*` | A modifier that allows you to set Tailwind classes to elements inside `thead th` or `thead td` when ordering changes to `asc`. |
| `hs-datatable-ordering-desc:*` | A modifier that allows you to set Tailwind classes to elements inside `thead th` or `thead td` when ordering changes to `desc`. |
## JavaScript API
The `HSDataTable` object is available in the global `window` object after the plugin is loaded.
### Instance Methods
These methods are called on a datatable instance.
| Method | Parameters | Return Type | Description |
| --- | --- | --- | --- |
| `destroy()` | None | `void` | Destroys the datatable instance, removes all generated markup, classes, and event listeners. Use when removing datatable from DOM. |
### Static Methods
These methods are called directly on the `HSDataTable` class.
| Method | Parameters | Return Type | Description |
| --- | --- | --- | --- |
| `HSDataTable.getInstance(target, isInstance)` | `target`: `HTMLElement \| string` (CSS selector)<br>`isInstance`: `boolean` (optional) | `HTMLElement \| { id: string \| number, element: HSDataTable } \| null` | Returns the datatable instance or element associated with the target. If `isInstance` is `true`, returns collection item object `{ id, element }` where `element` is the `HSDataTable` instance. If `isInstance` is `false` or omitted, returns the DOM element (`HTMLElement`). Returns `null` if datatable instance is not found. |
### Usage Examples
**Example 1: Accessing DataTables.net instance**
```javascript
// Get the datatable instance
const instance = HSDataTable.getInstance('#hs-datatable', true);
if (instance) {
const { element } = instance;
// Access underlying DataTables.net instance
const { dataTable } = element;
if (dataTable) {
// Use DataTables.net methods
dataTable.search('query').draw();
}
}
```
**Example 2: Destroying datatable instance**
```javascript
const instance = HSDataTable.getInstance('#hs-datatable', true);
if (instance) {
const { element } = instance;
const destroyBtn = document.querySelector('#hs-destroy-btn');
destroyBtn.addEventListener('click', () => {
element.destroy();
});
}
```
**Example 3: Destroying datatable instance**
```javascript
const instance = HSDataTable.getInstance('#hs-datatable', true);
if (instance) {
const { element } = instance;
const removeBtn = document.querySelector('#hs-remove-btn');
removeBtn.addEventListener('click', () => {
// Clean up before removing from DOM
element.destroy();
// Now safe to remove the element
document.querySelector('#hs-datatable').remove();
});
}
```
## Events
> **Note:** Please note that this component requires the use of the [Datatables.net](https://datatables.net/) plugin. Most events available in the plugin are available in our wrapper.
Datatable instances emit events through the underlying DataTables.net instance. Access the DataTables.net instance via `element.dataTable` to listen to events.
**Common DataTables.net Events:**
- `draw` - When table is redrawn
- `order` - When column ordering changes
- `search` - When search is performed
- `page` - When page changes
- `select` - When row is selected
- `deselect` - When row is deselected
### Event Usage Example
```javascript
// Get datatable instance
const instance = HSDataTable.getInstance('#hs-datatable', true);
if (instance) {
const { element } = instance;
const { dataTable } = element;
if (dataTable) {
// Listen to draw event
dataTable.on('draw.dt', () => {
console.log('Table redrawn!');
// Perform actions after table redraws
// e.g., update UI, reinitialize plugins
});
// Listen to order event
dataTable.on('order.dt', () => {
console.log('Column ordering changed!');
});
// Listen to search event
dataTable.on('search.dt', () => {
console.log('Search performed!');
});
}
}
```
## Common Patterns
### Pattern 1: With Search
Add search functionality to the datatable.
```html
<input type="text" data-hs-datatable-search placeholder="Search...">
<div data-hs-datatable>
<!-- Table structure -->
</div>
```
### Pattern 2: With Row Selection
Enable row selection with checkboxes.
```html
<div data-hs-datatable>
<table>
<thead>
<tr>
<th>
<input type="checkbox" data-hs-datatable-row-selecting-all>
</th>
<!-- Other columns -->
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="checkbox" data-hs-datatable-row-selecting-individual>
</td>
<!-- Other cells -->
</tr>
</tbody>
</table>
</div>
```
### Pattern 3: Exclude Column from Ordering
Disable sorting on specific columns.
```html
<th scope="col" class="--exclude-from-ordering">
Actions
</th>
```
## License
Copyright (c) 2026 Preline Labs.
Licensed under the [MIT License](https://opensource.org/licenses/MIT).