Open-source project
handsontable/handsontable avatar
handsontable/handsontable

Handsontable: a spreadsheet-grade JavaScript grid with a licensing model to read carefully

JavaScript Data Grid / Data Table with a Spreadsheet Look & Feel. Works with React, Angular, and Vue. Supported by the Handsontable team ⚡

22,044 stars3,184 forksJavaScriptNOASSERTION

At a glance

What is it?
The data grid component behind editable internal tools, shipping version 18.1.1 with framework wrappers for React, Angular and Vue, 400 built-in formulas, and an entitlement key system that arrived in 18.1.0.
Who is it for?
Handsontable is a good fit when users need to type into cells, validate values, and work in bulk on records that already live in your database, and a bad fit for a read-only results table where the bundle and the licence are both overkill.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 19 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A grid built for editing records, not for displaying them

The README states the positioning in one line: a JavaScript Data Grid with a spreadsheet-like look and feel. The next paragraph explains why that matters. It is aimed at data-rich internal applications where users enter, edit, validate and process data from various sources, and it names the common cases as resource planning, inventory management, digital platforms and data modelling applications.

That framing explains the feature list, which runs to twenty-five linked capabilities. Editing comes first in practice: configurable selection, merged cells, frozen rows and columns, hiding rows and columns, a right-click context menu, and a right-click menu are all in the list. Then validation and formatting: data validation, conditional formatting, and 400 built-in formulas for calculation. Then bulk work: sorting, filtering, row pagination, and export to Excel.

The features that separate it from a plain table library are the ones about input method and locale. There is IME support, internationalization, right-to-left layout support, and a dedicated date and time cell type. IME support in particular is not a checkbox: it is the difference between a grid that works for anyone typing Japanese, Chinese or Korean text into a cell and one that mangles composition.

Accessibility and keyboard shortcuts are listed as features rather than afterthoughts, and Shadow DOM and Web Components support is there too, which matters when the grid has to live inside a design system built on web components rather than a plain div.

Installing the core package and mounting it on a container

The installation section splits by target. If you are using React, Angular or Vue, the README sends you to a dedicated wrapper repository path for each, and the core package is the fallback.

For the core JavaScript component, the documented install is one command:

bash
npm install handsontable

The README also names Yarn, a NuGet package and a CDN on jsdelivr as alternatives, which tells you the component is distributed for consumers who are not using npm at all.

The next step is a container element, and this is the part of the setup that gets skipped in blog posts:

html
<!-- Set the container's ID -->
<div id="handsontable-grid"></div>

The third step imports the constructor by name and looks up that element before instantiating. The README's snippet begins `new Handsontable(` and the constructor options object follows, which is where you hand over the data array and the column definitions. What matters for planning is that the grid owns a DOM node it fills itself, so the height has to come from somewhere: the container is empty in your markup, and the grid measures it.

One detail catches the eye in the badge row. The CI badge points at the `master` branch while the repository's default branch is `develop`, and the README's own links point at `master` paths in the tree. A repository that ships from `develop` and links from `master` is following the release branch convention, so if you are reading source on GitHub, know which branch you are looking at.

Version 18.1.x and what the fixes reveal about framework wrappers

The release history is short and specific. Version 18.1.0 shipped on 2026-09-01, 18.1.1-rc2 on 2026-09-14, and 18.1.1 on 2026-09-15. The repository's last push was on 2026-09-18, so this is a line with recent movement rather than a stable historical artifact.

The 18.1.0 notes are the more informative of the two. They add a `modifySinglePassLayout` hook that forces the previous measure-then-render layout path, which is a compatibility escape hatch rather than a feature. They add `selectionHandles`, draggable handles at the midpoint of each edge of a selected range, and a `moveCells` option for dragging a selection to a new location. They add Persian right-to-left support, an `intl-datetime` cell type with a native date-time picker and `Intl.DateTimeFormat` display, and a `preserveNumericLiteral` option on the numeric cell type that keeps exactly what you typed instead of normalising it.

`preserveNumericLiteral` is a small option with a large implication. A numeric cell that reformats `1.50` into `1.5` looks like a helpful touch and is a data corruption bug when the value is an identifier or a quantity where trailing zeros matter.

The 18.1.1 notes show what wrapper integration costs. One fix restores copying, cutting and pasting inside a grid embedded in a Salesforce Lightning Web Component. The other fixes a crash in the `filters` plugin that fired when a cell in a filtered column was edited, or the data was replaced while a filter was active, after `updateSettings()` was called with the `filters` option. The release note observes that this is exactly what the React and Angular wrappers do on every update, which is a candid admission that the wrapper lifecycle and the plugin lifecycle have to be kept in step.

The licence question is the one to settle before writing code

GitHub reports no standard licence identifier for this repository, which is the first thing worth noticing. The tree explains why: alongside `LICENSE.txt` there is a `handsontable-non-commercial-license.pdf`. This is a dual-licence arrangement, not an open source one.

Version 18.1.0 made the commercial side mechanical. The release notes state that support for entitlement license keys was added, and that a missing or invalid license key now blocks the grid with a modal that cannot be closed. That is a meaningful change in behaviour. A grid that refuses to render is a very different proposition from one that logs a warning, and it means a team deploying Handsontable has to hold a valid key for whatever tier they are on before the component works at all.

The README does not describe the tiers, and neither does the repository tree. Pricing details, the non-commercial terms and the entitlement key flow are on handsontable.com, and the project's own related search terms include pricing and free usage questions, which tells you where prospective buyers actually go to resolve this.

So the practical order of work is: install, mount, confirm the grid renders, then read the licence that matches your situation. If you are building an internal tool at a company with revenue, that is the commercial licence conversation, not the non-commercial PDF. Read both documents rather than assuming the presence of a source-available repository means you may use it freely.

What the repository reveals about how the project is built

The file tree is unusually informative for a component library, and most of what it shows is about process rather than code.

There are three separate test suites in the tree. `visual-tests/` runs screenshot comparison, `performance-tests/` has its own lint target in the root scripts, and `tests/` holds cross-version tests. Alongside them sit `evals/`, which suggests model-evaluated output is now part of the quality story, and `docs/tests/`. The root `package.json` shows `lefthook.yml` handling git hooks and `sonar-project.properties` wired to SonarCloud, with a quality gate badge in the README.

Then there is the AI tooling, which is more of the tree than most component libraries carry: `.ai/`, `.claude/`, `.cursor/`, `CLAUDE.md`, `AGENTS.md`, `context7.json` and `.mcp.json`. The root scripts include `sync-skills` for pushing skills to Cursor and a `test:tooling` target that runs `node --test` across seven separate `__tests__` directories, including `scripts/claude/__tests__` and `evals/__tests__`. A contributor is expected to have those tools configured before making a change.

Two more structural choices stand out. The package is a pnpm workspace with `pnpm-workspace.yaml` and `pnpm-lock.yaml`, while the root scripts are all written as `npm run`, and the build and publish steps delegate through a custom `bin/` toolchain with `all build` and `publish-all` variants. Wrappers live in `wrappers/`, and `examples/` has its own `package.json` and a Next.js app, so the demo applications are versioned with the library rather than living in a separate repository.

Where it competes, and where it does not

The comparison that comes up most often is against read-only grid libraries, and the difference is not polish but scope. A read-only table component renders what you give it. Handsontable manages editing state, validation, formula recalculation across a range, clipboard behaviour, selection ranges and a plugin system, all of which is real work that a display table does not do.

If you only need to show rows with sorting and a filter, that scope is a cost rather than a benefit, and it shows up in bundle size and in the amount of configuration a read-only grid would not need. The virtualization feature exists precisely because the grid renders spreadsheet-like rows, which is a rendering strategy a static table has no reason to adopt.

Where Handsontable earns its weight is the internal tool case. If a user is expected to paste fifty rows from a spreadsheet, fill a form grid, or correct values in place against a validation rule, the editing model is the requirement. The server-side data option exists for grids too large to load at once, and row pagination covers the same ground more simply.

The 18.1.0 entitlement change is the other thing that shifts the comparison. A free-for-evaluation grid you can drop into a prototype is one thing; a grid that renders a blocking modal without a key is another, and it puts Handsontable in the same category as the commercial grids rather than alongside the open source ones. That is a defensible business decision for a component with this much support behind it, and it is the single most important fact to know before choosing it.

Editorial conclusion

Handsontable is a good fit when users need to type into cells, validate values, and work in bulk on records that already live in your database, and a bad fit for a read-only results table where the bundle and the licence are both overkill. The feature list is longer than any comparable read-only grid, with 400 built-in formulas, virtualization and server-side data in the same package, and the three framework wrappers are maintained in the same repository rather than bolted on. The licensing is the part that needs a decision before you write code, because 18.1.0 added entitlement keys and a modal that blocks the grid when a key is missing or invalid, and the repository tree ships a non-commercial licence PDF alongside the licence text. Start from the npm install and the container div the README documents, then read the licence file that matches your use case on handsontable.com before you plan a rollout.

Frequently asked questions

Is Handsontable free to use?

It is source available rather than open source, and the repository ships both `LICENSE.txt` and a `handsontable-non-commercial-license.pdf`. Version 18.1.0 added entitlement license keys, and a missing or invalid key now blocks the grid with a modal that cannot be closed. Pricing tiers are documented on handsontable.com rather than in the repository.

What is the best JavaScript Data Grid for an editable table?

That depends on whether users need to type into cells. Handsontable is built for editing rather than display, with validation, 400 built-in formulas, merged cells, a context menu, virtualization, server-side data and Excel export, plus wrappers for React, Angular and Vue maintained in the same repository. For a read-only results table, a lighter component is usually the better answer.

How do I install Handsontable in a plain JavaScript project?

Run `npm install handsontable`, add an empty container element with an id such as `handsontable-grid`, then import the Handsontable constructor and instantiate it against that element with your data and column settings. Yarn, a NuGet package and a CDN on jsdelivr are also offered, and framework users are pointed to the React, Angular and Vue wrapper packages instead.

What changed in the 18.1 release line?

Version 18.1.0 added the `modifySinglePassLayout` hook, `selectionHandles`, a `moveCells` option, Persian right-to-left support, the `intl-datetime` cell type, the `preserveNumericLiteral` numeric option and entitlement license keys. Version 18.1.1 then fixed clipboard operations inside a Salesforce Lightning Web Component and a `filters` plugin crash that occurred when the React and Angular wrappers called `updateSettings()` with the filters option.

Official sources

  1. handsontable/handsontable on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/handsontable-handsontable.svg)](https://hysenlabs.com/projects/handsontable-handsontable)