Migrating to v6
Version 6 is a major release. It removes the last runtime dependency, replaces frozen panes with pinning and sticky docking, keeps hidden columns in the column array, and drops the CommonJS build. This page is the complete list of breaking changes between 5.20.2 and 6.0.0, with what to change for each one.
Work through the sections that match what your application uses. Most applications only need Installing v6, Frozen panes become pinning, Columns: the hidden property and Styling and themes. The later sections matter if you subclass grid classes, write custom plugins, or test the grid's DOM.
AI agents can use the SlickGrid v6 migration skill alongside this guide.
Installing v6
ESM only (PRs #1310, #1343)
The CommonJS build is gone. dist/cjs is no longer published, and the package main now points at ./dist/esm/index.mjs.
- Use
import { SlickGrid } from 'slickgrid'.require('slickgrid')only works where Node supportsrequire()of ES modules. - The IIFE build in
dist/browser(the globalSlicknamespace) is unchanged.
Node.js version (PR #1344)
engines.node is now ^20.19.0 || >=22.12.0 (it was >=18.0.0).
dist/ is no longer committed (PR #1312)
The built files are published to npm only.
- Load the files from npm or an npm CDN, for example
https://cdn.jsdelivr.net/npm/slickgrid@6/dist/browser/slick.grid.jsor unpkg. - GitHub raw URLs,
cdn.jsdelivr.net/gh/...URLs, git dependencies and submodules no longer containdist/. - If you build SlickGrid yourself, the build script is now
npm run build(it wasnpm run build:prod).
SortableJS is gone (PRs #1242–#1244)
The grid now uses native browser drag and drop, and the package has no runtime dependencies.
- Remove any
<script>tag that loadsSortable, and any global assignment such aswindow.Sortable = Sortable. - If your application uses
sortablejsitself, add it as a direct dependency. - Column reordering (
enableColumnReorder) and draggable grouping keep working without new configuration. The Draggable Grouping API changes are listed under Plugins and controls.
Removed exports
| Removed | Replacement |
|---|---|
FieldType constant (PR #1314) | The string values, such as 'number' and 'date'. import { FieldType } from 'slickgrid' now fails at runtime. |
OnBeforeAppendCellEventArgs type (PR #1320) | None; see onBeforeAppendCell. |
FilterCspFn and FilterWithCspCachingFn types (PR #1325) | FilterFn<T>. |
Frozen panes become pinning and sticky docking
PR #1302. Version 6 removes frozen panes. The grid has one scrollable viewport, and the pinning option docks columns and rows at its edges. You can now pin columns on the right as well as the left, pin rows at the top and bottom at the same time, and make columns and rows sticky, so that they dock at an edge only while scrolling would hide them.
const gridOptions = {
- frozenColumn: 1,
- frozenRow: 2,
+ pinning: {
+ columns: { left: 1 },
+ rows: { top: [0, 1] },
+ },
};Options
| v5 | v6 |
|---|---|
frozenColumn: N | pinning: { columns: { left: N } }. The boundary is the same, but it now counts visible columns only. |
frozenRow: N | pinning: { rows: { top: [0, …, N-1] } } |
frozenRow: N, frozenBottom: true | pinning: { rows: { bottom: [len-N, …, len-1] } } |
frozenRightViewportMinWidth | Removed. Use docking.maxColumnViewportWidthPercent. |
skipFreezeColumnValidation | skipPinningValidation |
invalidColumnFreezePickerMessage, invalidColumnFreezeWidthMessage | invalidColumnPinningPickerMessage, invalidColumnPinningWidthMessage |
invalidColumnFreezePickerCallback, invalidColumnFreezeWidthCallback | The shared errorCallback (PR #1318) |
throwWhenFrozenNotAllViewable | Removed, with no throwing variant. |
All error messages now go through the single errorCallback. The individual messages stay configurable through invalidColumnPinningPickerMessage, invalidColumnPinningWidthMessage and invalidColumnPinningSequenceMessage:
const gridOptions = {
- invalidColumnFreezePickerCallback: (msg) => alert(msg),
- invalidColumnFreezeWidthCallback: (msg) => alert(msg),
+ errorCallback: (msg) => alert(msg),
};Methods
| v5 | v6 |
|---|---|
getFrozenColumnId() | getPinnedColumns() |
validateColumnFreezeWidth(), validateSetColumnFreeze() | validateColumnPinning() |
getFrozenRowOffset(), calculateFrozenColumnIndexById() | Removed; row offsets are internal. |
setColumns(columns) | Now returns a boolean. It returns false, and changes nothing, when it rejects the pinning of the new columns. It also writes pinned onto the columns from options.pinning. |
There is one viewport and one canvas, so the pane getters return one element:
getCanvasNode()andgetViewportNode()ignore their arguments.getHeader()with no argument returns one element, not an array.getTopPanels()returns one panel.getPreHeaderPanelRight()returns the same element asgetPreHeaderPanelLeft().getCanvases(),getViewports(),getHeaderRow()andgetFooterRow()return one entry where they returned left and right pairs.
Column reordering across the pinned boundary is not possible; pin or unpin the column explicitly. The Grid State plugin does not persist frozenColumn; store pinning from grid.getOptions() instead.
CSS classes and DOM
- Removed: the
.slick-paneand.slick-pane-*classes,.slick-viewport-right,.slick-viewport-bottom,.grid-canvas-right,.grid-canvas-bottomand.slick-header-right. - Removed: the
frozenclass on header, header-row and footer cells. Use.slick-column-pinned-left,.slick-cell-pinned-leftand their-rightand-edgevariants. slick-viewport-top slick-viewport-leftandgrid-canvas-top grid-canvas-leftremain on the single viewport and canvas..slick-header-columns-right,.slick-headerrow-columns-rightand.slick-footerrow-columns-rightstill exist, but only as the right-pinned band wrappers inside a.slick-docking-chromerow, not as a second pane.- New wrappers (
.slick-header-root,.slick-content-root,.slick-header-containerand.slick-preheader-container) break direct-child selectors such as.slick-pane-header > .slick-header.
See Pinning and sticky docking for the full feature guide.
Columns: the hidden property
PR #1299. Version 6 keeps all columns at all times. To hide a column, set hidden: true on it instead of removing it from the array. This makes show and hide reversible and keeps each column's settings while it is hidden.
- Do not filter columns out of the array to hide them. Set
hiddeninstead. getColumns()returns every column, including hidden ones. UsegetVisibleColumns()to read only the visible ones.- Use
grid.updateColumnById('id', { hidden: true })followed bygrid.updateColumns()to toggle a column. - Column Picker and Column Menu
onColumnsChanged:columnsnow holds the visible columns only (it held all of them), andallColumnsisgrid.getColumns(). Toggling callsupdateColumnById()andupdateColumns(), notsetColumns(visible), and the last visible column can no longer be unchecked. - Row and Hybrid selection: full-row ranges end at the last visible column.
- SlickState: the saved column state includes
hidden. On restore, columns missing from the saved state are kept withhidden: trueinstead of being dropped.
Column objects are copied (mixinDefaults)
The mixinDefaults grid option now defaults to false (it was true). The grid applies the column defaults to copies of your column objects, not to the objects themselves.
Code that keeps a reference to a column object and mutates it no longer affects the grid:
- columns[2].hidden = true;
- grid.updateColumns();
+ grid.updateColumnById(columns[2].id, { hidden: true });
+ grid.updateColumns();Read the grid's own columns with getColumns() or getColumnById(), change them with updateColumnById(), or set mixinDefaults: true to keep the v5 behaviour.
Grid rendering and behaviour
rowTopOffsetRenderType is removed (PR #1319)
Remove the option from your configuration, whether its value was 'top' or 'transform'. Row Detail and RowSpan no longer need an explicit 'top' setting.
const gridOptions = {
- rowTopOffsetRenderType: 'top',
rowHeight: 25,
};Ordinary rows are positioned with transform: translateY(25px) instead of top: 25px. RowSpan host rows and the rows they cover now carry the .slick-rowspan class and keep top positioning, so spanning cells and pinned columns stack correctly. Update tests and CSS that read a row's top.
Scroll rendering (PR #1320)
scrollRenderThrottlingdefaults to0(it was10), so large vertical jumps render synchronously. Set a positive delay, such as10, to keep timer throttling.- Horizontal scrolling now renders on the next animation frame, even with
forceSyncScrolling. In 5.20.2 it rendered synchronously. It also re-renders only after scrolling about 80% of the viewport width (it was 20px), andonViewportChangedfires before the new cells are rendered.
onBeforeAppendCell is removed
The per-cell onBeforeAppendCell event and its OnBeforeAppendCellEventArgs type are removed. Return classes from a formatter instead:
const formatter = (_row, _cell, value) => ({
text: String(value),
addClasses: value > 50 ? 'high-value' : '',
});Plain-text formatter results skip the sanitizer
A formatter result that is a plain string, with no < or &, is now written with textContent and does not go through the sanitizer. Markup and strings with entities still use the sanitizer. Do not use a sanitizer as a general text transformation hook.
Context menu event
onContextMenu now also fires when you right-click the canvas outside a cell, with { row: -1, cell: -1 }. In 5.20.2 it fired over cells only, with empty args; it now passes { row, cell }. Check for -1 if your handler assumes a cell.
Keyboard
Grid keyboard handling reads e.key instead of e.which or keyCode. Synthetic keyboard events in tests must set key. F2 now opens the editor of the active cell.
Events: unsubscribe() with no handler
PR #1345.
SlickEvent.unsubscribe()with no argument now removes every handler. It used to remove nothing. As a result,destroy()of GridMenu, CellMenu, ContextMenu, Resizer, RowDetailView, DraggableGrouping and DataView now really drops the subscriptions to their own events. Subscribe again if you reuse an instance.- Do not call
grid.onXxx.unsubscribe()without a handler unless you mean to remove everyone's handlers. Use aSlickEventHandlerto remove only your own. notify()runs over a copy of the handler list. A handler unsubscribed during a notify is skipped, and one subscribed during a notify runs from the next notify.
Copy and paste: the async Clipboard API
PR #1270. SlickCellExternalCopyManager now uses the browser's asynchronous Clipboard API (navigator.clipboard) instead of a hidden textarea.
- The Clipboard API needs a secure context (HTTPS or localhost). Paste also needs clipboard-read permission, and it now completes asynchronously.
- Removed options:
bodyElementandclipboardPasteDelay. - New options:
clipboardWriteOverrideandclipboardReadOverride. Use them where the Clipboard API is unavailable or the host application manages the clipboard. - Keys are detected with
e.key, and the IEwindow.clipboardDatapath is gone. - Copy calls
preventDefault(). Clipboard errors are logged instead of thrown. - The
onPasteCellsrange ends at the last column actually pasted, and CRLF counts as one row delimiter. - Subclasses:
_createTextBox(),_bodyElementandkeyCodesare removed._decodeTabularData(grid, clipText)now takes the clipboard text instead of a textarea, andhandleKeyDown()isasync.
See the CellExternalCopyManager reference for details.
Column autosizing
PR #1328.
- Content autosizing samples the first 200 rows by default, in every column mode (
autoSize.rowSelectionCountwas 100). ContentIntelligentnumber and string columns used to read every row. They now read the rows chosen by the column's ownrowSelectionModeandrowSelectionCount, so the first 200 by default. SetautoSize.rowSelectionMode: RowSelectionMode.AllRowson a column to read every row again.- TypeScript: the autosize settings are typed as unions of their constants instead of
string. This coversautosizeColsMode, theautosizeColumns()argument, andautoSize.autosizeMode,rowSelectionMode,rowSelectionModeOnInit,valueFilterModeandwidthEvalMode. Misspelt values become compile errors. Code that uses the constants (GridAutosizeColsMode.FitColsToViewport,ColAutosizeMode.Locked, ...) or their literal values needs no change. A value held in astringvariable, for example one read from configuration, needs a type assertion such asvalue as ColAutosizeModeValue. The new*Valuetypes are exported for this. autoSize.rowSelectionModeOnInitwas typedbooleanbut holds aRowSelectionModevalue; it is now typed as one.GridAutosizeColsMode,ColAutosizeMode,RowSelectionMode,ValueFilterModeandWidthEvalModeare declaredas const.
Removed deprecated code
Replace these before upgrading.
DataView filtering
PR #1325. DataView filtering and aggregation are CSP-safe without runtime code generation. Remove inlineFilters and useCSPSafeFilter from DataView options; neither needs a replacement. The unused FilterCspFn and FilterWithCspCachingFn type aliases are also removed. Use FilterFn<T> for the predicate passed to setFilter().
Subclasses of SlickDataView must update references to these protected methods:
| Previous method | Replacement |
|---|---|
compileFilterCSPSafe() | filterItems() |
compileFilterWithCachingCSPSafe() | filterItemsWithCaching() |
compileAccumulatorLoopCSPSafe() | compileAccumulatorLoop() |
DataView fastSort()
The IE-specific fastSort(field, ascending) method and the protected fastSortField are removed. Use sort(comparer, ascending) instead:
dataView.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0), true);reSort() continues to reapply the comparer and direction passed to sort().
Menu and column picker options
- Grid Menu: use
commandItemsandcommandTitlein place ofcustomItemsandcustomTitle, nested entries included. RemoveresizeOnShowHeaderRow; flexbox handles header sizing. - Header Menu: use
header.menu.commandItemsin place ofitems, nested entries included. - Header Menu
itemVisibilityOverrideanditemUsabilityOverridecallbacks receive the command list directly inargs.menu, asHeaderMenuCommandItemCallbackArgsdeclares. Changeargs.menu.itemstoargs.menu. - The top-level grid options
columnPickerTitle,forceFitTitleandsyncResizeTitleare removed. SetcolumnTitle,forceFitTitleandsyncResizeTitleundercolumnPicker. - Column Menu and Column Picker: rename
setColumnVisibiliy()tosetColumnVisibility().
Other removals
- Column
excludeFromQueryis removed (PR #1314). - The Resizer plugin's
resizeGrid()always returns a Promise; the fallback for browsers without Promise support is gone. MouseWheelinteractions no longer fall back towindow.event.- IE-specific stylesheet and global-event fallbacks are removed.
Plugins and controls
Draggable Grouping
getSetupColumnReorder()returns{ columnReorderDragInstance }, an object with adestroy()method. In 5.20.2 it returned the SortableJS instances{ sortableLeftInstance, sortableRightInstance }.- The protected
_droppableInstance,_sortableLeftInstance,_sortableRightInstance,destroySortableInstances()andaddDragOverDropzoneListeners()are removed. - The drag ghost is
.slick-header-column-drag-ghost;.slick-sortable-placeholderis no longer applied.
Row Detail View
PR #1319. The plugin renders one .slick-row-detail-container.row-detail-{id} panel directly in the grid canvas. Each panel sits over the padding rows reserved below its parent and stays within the visible viewport width while scrolling horizontally. The panel itself is the content mount point.
- Removed containers and classes:
.dynamic-cell-detail,.detail-container,.innerDetailView_{id},.detailViewContainer_{id}and.cellDetailView_{id}. - The panel carries the plugin's
line-height: 13px, which the removed content wrapper used to set, so every top-level element of a template inherits it. Override it on.slick-row-detail-container. - Panels are recreated as rows leave and re-enter the rendered range.
- The formatter no longer returns
insertElementAfterTarget, and thehandleScroll()signature changed.
- .dynamic-cell-detail .innerDetailView_{id}
+ .slick-row-detail-container.row-detail-{id}Grid Menu
PR #1323.
- The button is wrapped in a flexbox
.slick-gridmenu-container, and the header is no longer sized withcalc(100% - Npx). Review custom CSS that positions.slick-gridmenu-buttonor overrides header widths. menuWidthdefaults to12pixels, plus 2 pixels of spacing, and acts as a minimum: an icon class wider than that widens the slot instead of being clipped.iconButtonContainer: 'preheader'needs a.slick-preheader-panel.
Custom Tooltip
PR #1316.
- Tooltips no longer have an arrow. The
hideArrowoption and the.tooltip-arrow,.arrow-up,.arrow-downand.arrow-{left,center,right}-alignclasses are removed. - The content now goes into a child
.tooltip-bodyelement (seebodyClassName). - A custom
classNameis appended toslick-custom-tooltipinstead of replacing it. - A missing
asyncPostFormatteror a rejectedasyncProcessis logged instead of thrown.
The plugin can now also show tooltips on elements outside the grid; see Custom tooltips.
Header Menu, Cell Menu and Context Menu
PR #1347.
- Header Menu constructor options now override the defaults. Before,
minWidth,autoAlign,autoAlignOffsetandsubMenuOpenByEventpassed to the constructor were silently ignored. - Cell Menu and Context Menu: returning
falsefromonAfterMenuShownow closes the menu, as documented.
Editors
PR #1347.
- With
editorCellNavOnLRKeys, Left and Right move to the next cell only when the cursor is at the start or end of the text. Before, the grid always navigated, and Right fired one character early. isValueChanged()compares values as strings, so untouched number, date and yes/no fields no longer count as changed. TextEditor loads0as'0'.- LongTextEditor's protected
selectionStartfield is removed.
Accessibility
PR #1338. Most applications need no configuration changes, but custom accessibility integrations and DOM tests may need updates.
aria-rowindexandaria-rowcountcount the visible column-header and header-filter rows, and the add-new row when available. Data row indexes no longer start at 1.- The container has
aria-colcount(all columns, hidden ones included), and header and data cells havearia-colindex. - Selected cells have
aria-selected, and the primary sorted column hasaria-sort. - Built-in editors use the rendered column title as their accessible name, falling back to the column ID. Set
editorAriaLabelon a column for a different or translated name. - Checkbox Select Column: labels come from the
rowAriaLabelandselectAllAriaLabeloptions;rowAriaLabelnames every row checkbox alike, in place of the defaultSelect row N.aria-checkedis no longer rendered, andcreateCheckboxElement()gained anariaLabelparameter. - Header Buttons: the default
aria-labelisariaLabel || tooltip || command(it was always"Header Button"). Buttons are focusable, respond to Enter and Space, and no longer callactionwhen disabled. - Header menu buttons are focusable, with
aria-haspopupandaria-expanded, arrow, Home, End and Escape keys in the menu, and focus returned on close. Menu and header buttons show on keyboard focus. - Pager icons and row-detail toggles are focusable and respond to keys. Menu dividers have
role="separator"and disabled itemsaria-disabled. - The PercentCompleteBar, Checkbox and Checkmark formatters include text alternatives.
CheckmarkFormatterreturns<span role="img" aria-label="No"></span>for false values instead of an empty string. Update tests that compare formatter HTML. - Custom tooltips keep an element's existing
aria-describedbyreferences while the tooltip is shown.
For example, column and plugin options can provide application-specific labels in an IIFE application:
const columns = [{
id: 'title',
name: 'Title',
field: 'title',
editor: Slick.Editors.Text,
editorAriaLabel: 'Edit task title',
}];
const checkboxSelector = new Slick.CheckboxSelectColumn({
rowAriaLabel: 'Select task',
selectAllAriaLabel: 'Select all tasks',
});
columns.unshift(checkboxSelector.getColumnDefinition()); // the plugin's own column holds the checkboxes
const grid = new Slick.Grid('#myGrid', data, columns, { editable: true, enableCellNavigation: true });
grid.setSelectionModel(new Slick.RowSelectionModel({ selectActiveRow: false }));
grid.registerPlugin(checkboxSelector);For ESM, import SlickGrid, TextEditor, SlickRowSelectionModel and SlickCheckboxSelectColumn from slickgrid and use those names in place of Slick.Grid, Slick.Editors.Text, Slick.RowSelectionModel and Slick.CheckboxSelectColumn.
Styling and themes
Alpine theme variables (PR #1317)
All $alpine-* SASS variables are renamed to $slick-*, and all --alpine-* CSS custom properties to --slick-*, with the same suffixes and values:
// SASS
- $alpine-odd-row-color: #fbfbfb;
+ $slick-odd-row-color: #fbfbfb;
/* CSS */
body {
- --alpine-odd-row-color: #fbfbfb;
+ --slick-odd-row-color: #fbfbfb;
}jQuery UI class leftovers (PR #1313)
The remaining .ui-* classes are removed from the grid, controls and plugins. Rename them in your CSS and selectors:
| v5 | v6 |
|---|---|
.ui-state-default, .ui-state-hover, .ui-state-active | .slick-state-default, .slick-state-hover, .slick-state-active |
.ui-widget (grid container) | .slick-widget |
.ui-widget-content (rows) | .slick-widget-content |
.ui-icon-container (pager) | .slick-icon-container |
Resize handles and headers
- The default theme's column resize handle is 6px wide (it was 9px), sits at
right: 0(it was-5px) and hasz-index: 4. - The Alpine handle is 6px wide, with its separator line moved to
::before. Both themes add an::afterhover pill. - Alpine and the default theme style headers through
.slick-header-column.slick-state-default, so plain.slick-header-column { … }overrides can lose on specificity. The default theme also sets the header height, padding and background.
New SASS partial
The themes @use the new _slick-docking.scss. Copy it too if you copy individual .scss files into your project.
Subclasses: protected members
If you subclass SlickGrid or a plugin, these protected members changed:
trigger()became the publictriggerEvent(), with no alias (PR #1315).- The frozen-pane helpers are removed:
getFrozenColumnIdx,hasFrozenColumns,setFrozenOptions,setPaneVisibility,setPaneFrozenClasses,isFrozenRowIdx,isBottomBandRow,computeFrozenRowsHeightand_getContainerElement. - Also removed:
clearTextSelection,dirSideandLogColWidths.destroyAllElementsis renameddestroyElementReferences. - Cell Range Selector:
_rowOffset,_columnOffset,_isRightCanvasand_isBottomCanvasare removed. - The DataView, Clipboard, Draggable Grouping and LongTextEditor changes are listed in their own sections above.
New in v6
These additions are not breaking, but most of them replace something above.
- Pinning and sticky docking: the
pinning,stickyRows,docking,skipPinningValidation,errorCallback,invalidColumnPinningPickerMessage,invalidColumnPinningSequenceMessage,invalidColumnPinningWidthMessage,allowDragFromClosestandcolumnResizingDelayoptions; thepinnedandstickycolumn properties; thegetPinnedColumns(),setColumnPinning(),setColumnStickiness()andvalidateColumnPinning()methods; and theonHeaderMouseOver,onHeaderMouseOut,onHeaderRowMouseOver,onHeaderRowMouseOutandonHeaderKeyDownevents. - Hidden columns: the
spreadHiddenColspanoption and thegetColumnById(),getVisibleColumnIndex(),updateColumnById()andgetRowTop()methods. - Custom tooltips:
bodyClassName,repositionByMouseOverTarget,useRegularTooltipFromCellTextOnly,persistOnHover,autoHideDelay,observeAllTooltipsandobserveTooltipContainer. - Accessibility: the
editorAriaLabelcolumn property, the Checkbox Select ColumnrowAriaLabelandselectAllAriaLabeloptions, and the header buttonariaLabel.
All of them are in the Reference.