Tabulator Sortable Filterable Data Grid — Free JS Snippet

Tabulator Sortable Filterable Data Grid · Tables · Plain HTML, CSS & JS · Live preview

CategoryTables

What's included

Features

Sortable columns with a default initial sort
Header filters: text input, dropdown list and numeric minimum
One search box matching several columns using a nested OR filter group
Local pagination with a rows-per-page selector
Draggable and resizable columns
Money formatter and a custom status-badge formatter
Live match count from the rows passed to the dataFiltered event
Waits for tableBuilt before touching the API

About this UI Snippet

Tabulator Sortable Filterable Data Grid — HTML, CSS & JavaScript

Screenshot of the Tabulator Sortable Filterable Data Grid snippet rendered live

A plain HTML table is fine for twelve rows and hopeless for a real dataset. Users expect to sort by any column, filter to what they care about, page through the rest and rearrange the layout, and building all of that by hand is weeks of work. Tabulator is a dependency-free data-grid library that provides it from a configuration object. You describe the data and the columns, and it renders a grid with sorting, filtering, pagination, column dragging and resizing already wired up.

The configuration is worth reading closely, because most of the value is in options that are easy to overlook. layout: 'fitColumns' makes columns share the available width instead of overflowing. movableColumns lets users drag headers into their preferred order. pagination with paginationSizeSelector adds page controls and a rows-per-page menu. initialSort applies a starting order. Columns carry their own behaviour: a headerFilter of 'input' adds a text box under the header, 'list' adds a dropdown built from the values you pass, and a number filter with headerFilterFunc '>=' makes the salary filter mean "at least this much" rather than "exactly this".

The search box above the grid demonstrates the part of the filter API that is least obvious. setFilter accepts a list of conditions that are all ANDed together, but a nested array inside that list is an OR group. Passing one nested array containing a like-condition per column gives a single search box that matches a name, a role or a department, which is what people mean by "search". clearFilter(false) removes that search while leaving the header filters alone, and clearFilter(true) clears everything; both matter because header filters and programmatic filters are separate layers.

Modern Tabulator has one rule that trips up nearly everyone migrating from older versions: the table builds asynchronously, and calling data methods before it has finished silently does nothing or throws. The snippet respects that by wiring its count display to the tableBuilt and dataFiltered events, using the rows array that dataFiltered passes to its callback to report how many rows currently pass the filters. Cells can be rendered with formatters — the money formatter for salary, and a custom function that returns a coloured badge for status — so presentation lives in the column definition instead of a separate templating step. The data is generated deterministically so the grid looks the same on every load.

Step by step

How to Use

  1. 1
    Sort a columnClick a column header to sort ascending, again for descending. The grid opens sorted by name.
  2. 2
    Use header filtersType in the Name filter, choose a department from the dropdown, or enter a minimum salary.
  3. 3
    Search across columnsType in the search box above the grid. It matches names, roles and departments at the same time.
  4. 4
    Page and resizeUse the page controls and rows-per-page menu, drag a column header to reorder, and drag its edge to resize.
  5. 5
    Clear everythingPress Clear filters to remove the search and all header filters. The footer shows the match count.

Real-world uses

Common Use Cases

ADMIN
Admin panels and back offices
Give staff a sortable, filterable view of any dataset. For inline editing see the editable Tabulator grid.
Reports and data explorers
Let users slice a report by department, role or value without a server round trip.
Directories and HR tools
Search and filter a staff or customer directory with status badges.
Learning data-grid configuration
A compact tour of columns, formatters, filters and the build lifecycle.

Got questions?

Frequently Asked Questions

The table builds asynchronously. Call methods like setFilter or getData only after the tableBuilt event has fired.

Pass setFilter a nested array of conditions. A nested array is an OR group, so any matching column includes the row.

clearFilter(true) also clears header filters; clearFilter(false) removes only programmatic filters and leaves the header filters.

Set headerFilterFunc to ">=" on a number header filter so it compares with greater-or-equal instead of equality.

Listen for the dataFiltered event. Its second argument is the array of rows that passed, across every page, so its length is the match count.

Yes. Use ajaxURL with remote pagination and sorting, or fetch the data yourself and call setData.

Yes. Use the JSX, Vue, Angular or Tailwind export buttons on this page to convert the markup and styles. The behaviour comes from Tabulator, so in a framework project install it with npm install tabulator-tables (or react-tabulator) instead of the CDN tag, create it in useEffect / onMounted / ngAfterViewInit and wait for the tableBuilt event, and release it with destroy() when the component unmounts.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Ask an AI assistant like Claude to add row selection with bulk actions, export to CSV, or persistence of the sort and filter state in the URL.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a data grid with Tabulator 6 loaded from a CDN (script and CSS).

Requirements:
- Generate around 60 employee rows and define columns for name, department, role, salary, start date and status, with layout: 'fitColumns', movableColumns, pagination and a page-size selector.
- Add header filters: an input for name, a list for department and a numeric minimum for salary using headerFilterFunc '>='.
- Format salary with the money formatter and status with a custom function returning a coloured badge.
- Add a search box that calls setFilter with a single nested array (an OR group) across name, role and department, and a Clear button using clearFilter(true) and clearHeaderFilter().
- Wire a footer count to tableBuilt and dataFiltered, using the length of the rows array passed to the dataFiltered callback.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

<div class="tg-card">
  <div class="tg-bar">
    <div class="tg-search">
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
      <input id="tgSearch" type="search" placeholder="Search name, role or department..." aria-label="Search the table">
    </div>
    <button type="button" id="tgClear" class="tg-btn">Clear filters</button>
  </div>
  <div id="tgTable"></div>
  <div class="tg-foot" id="tgFoot" aria-live="polite"></div>
</div>