0.3.1 - 2026-10-05
| Change | Who is affected | What to do |
|---|---|---|
| Cancelling the confirmation dialog leaves filter/sort/quick-filter state untouched | Code that relied on getState() reporting the new filter even after a cancel | The call is now a no-op; read getState() / getQuickFilter() to see what was applied |
A totalRows from fetchMeta that is not a non-negative integer is treated as 0 and logged | Servers returning the row count as a string or a fraction | Send an integer. Previously the tab froze as soon as the grid scrolled or repainted |
printGrid() warns about server rows that were not loaded | Tests that treat console warnings as failures | Use printGrid({ full: true }) to print everything |
Hidden columns are accepted by setFilter / setSort / setCellValue | Code that relied on those calls throwing for a hidden column | They now apply instead of throwing |
Columns the data no longer has disappear from getHiddenColumns() | Code that saves and restores the hidden list across changing column sets | Stale column names are cleaned up automatically |
Added
printGrid({ full: true }): fetches every row matching the current filters and sorts, slots the rows added withaddRow()in where they sit on screen, and returns aPromiseso you can await the filled print window. The default (full: false) prints only rows already loaded, as before, and now warns on the console about how many server rows were left out.- Behavior notes in the type declarations: when
startEditingthrows and when it returnsfalse(checkbox/buttoncolumns), thatsetCellValueignoreseditableCols, thatgetChangesthrows withoutrowKey, thatsetHeaderCheckboxdoes not fireonHeaderCheckboxChange, that an emptydataarray needscolumnDefs, and that filter/sort changes may show a confirmation dialog.
Fixed
- A
totalRowsof1.5,Infinity,NaN, a string, a negative number orundefinedfromfetchMetamade the browser tab stop responding. The value is now coerced to a non-negative integer and reported on the console, and row counts above two billion no longer stall. - With unsaved edits present,
setFilter/setFilterValues/setSort/removeSort/clearSort/setQuickFilterchanged the filter and sort state before the confirmation dialog, so after a cancelgetState()reported a condition the rows did not have.setQuickFilterwas worse: the cancelled value stayed recorded, so passing it again was skipped as “unchanged” and that search term could never be applied. setState({ hiddenColumns })on its own was ignored; hiding only took effect whencolumnswas passed in the same call.- Passing a hidden column to
setFilter/setFilterValues/setSort/setCellValue/setCellValuesthrewunknown field. Hiding a filtered column left that filter active but impossible to change, only to remove.setSelection/focusCell/startEditingstill throw, since they need a column position, but the message now tells you to callshowColumn()first. - A
rowHighlighterthat threw took down the whole frame. It is now isolated likecellBackground/cellDecorator: the error is logged and the row is drawn without a highlight. - An
onRenderthat threw let the exception escape drawing. Since the first paint happens while the grid is being created,new JHGrid(...)itself failed. The error is now logged and the grid works. - Errors raised while laying out columns or drawing the first frame were reported as
fetchMeta failed. The two phases are now separate and each reports its own cause. - A
pagination.pageSizebetween 0 and 1 produced a page size of 0 and anInfinitypage count. Values below 1 now fall back to the default of 50, like 0 already did. exportCsv({ full: true })requested pages forever against afetchDatathat ignores the requested page range and always returns a full page. It now stops at the known row count.printGrid({ full: true })left out the rows added withaddRow(). The default print includes them, so the same method produced a different set of rows depending onfull. They are now printed among the server rows, where they sit on screen. Rows a plugin collected instead carry no positions, so in that case they print in the order they arrived.exportCsv({ full: true })/printGrid({ full: true })still asked for the first page after the server reported a row count of 0, which was the one case afetchDatathat ignores the page range could still loop on. Once the first load is through, only the reported row count is requested.- The full scan behind row reordering (
rowReorder) and the color filter usedfetchMeta’stotalRowsunchecked, so a fraction,InfinityorNaNbroke it withInvalid array length. It is coerced to a non-negative integer, like the first load. - After the data’s column set changed, columns that no longer exist stayed in
getHiddenColumns()and could be brought back withshowColumn(). destroy()left the loaded-row cache and failed-chunk retry timers in place; both are released now (100 cached rows became 0). Requests already sent are still not cancelled, and their responses are discarded as before.
Performance
- Applying a saved row (
acknowledgeSave) and clearing a row’s edits cost time proportional to the number of edits in the whole grid; it is now proportional to the edited fields of that row. Acknowledging 2000 rows with 40,000 edited cells went from 2755ms to 343ms, measured by running the pre-fix and post-fix bundles in the same session. getState()no longer scans the full edit set once per added row. With 2000 added rows and 20,000 edited cells it went from 400ms to 2.3ms.- Clearing a deleted column’s edits uses the same index (16.9ms to 9.8ms with 40,000 edited cells), and leaves exactly the same edits behind as before.
- Removed the
rowHighlighterresult cache: it was rebuilt every frame and never reused, so it only allocated. The number of calls is unchanged (once per visible row per frame).
To check for regressions the pre-fix and post-fix bundles were measured in the same session; the post-fix figure is in brackets. 1,000,000 rows (3 renderers, 1200x600): 37.3ms (39.5ms) to initialize, 0.4ms (0.5ms) per repaint, 0.2ms (0.2ms) per scrollTo. 500,000 local rows: 12.2ms (13.7ms) to initialize, 114ms (118ms) to sort, 49ms (44ms) to filter. 40,000-cell bulk edit 37.5ms (36.7ms), getChanges 16.1ms (14.6ms), undo 17.6ms (14.7ms). All within measurement noise.