Spreadsheet extends DataGrid
An editable DataGrid — the virtualized counterpart to Spreadsheet.
Constructor
new Spreadsheet(options)
options
:
Object
optionalreadonly
:
function
optionalFunction called with each record to determine whether its row should render readonly (non-editable) cells. Resolved per-record before editing, pasting, or clearing. A column that is explicitly non-editable (editable: false) stays non-editable regardless; per-record readonly additionally makes otherwise-editable cells readonly.
data
:
Array
|
Promise.<Array>
optionalrecords (one DataGridRow per record); may be a promise of the array, or an array of per-record promises, in which case a loader can render while it resolves (see loading)
rowHeight
:
number
optionalestimated height for unmeasured rows
defaultColumnWidth
:
number
optionalwidth for columns without width
overscan
:
number
optionalextra rows mounted above/below the viewport
rowClass
:
function
optional(record) => class applied to each row element (string, token array, or State); re-evaluated each time a row mounts
empty
:
function
optional() => content rendered in the body when there are no rows
loading
:
function
optional() => content rendered in the body while data is still resolving (rows not yet built); removed once rows are in place
loadRecords
:
function
optional(records) => Promise batch loader called with the records of rows entering the window (overscan included), before their cells render. Hydrate the records in place (e.g. fetch and merge nested associations) and resolve when done; cells render once the batch settles. Mount-driven only: records accessed while off-screen (e.g. Spreadsheet copy across an off-screen range) are not loaded.
loadingRow
:
function
optional(record, row) => content rendered inside a row while loadRecords is resolving its record; replaced by cells once the load settles
content
:
string
|
HTMLElement
|
Array
|
Object
optionalcontent to append to element. Passed to Dolla's content
Instance Properties
cells
Every cell as a CellHandle (lazy, transient — see plan §1.1).
Focusable controls an editor may expose — used to find the control to focus and to tell a click on a real control apart from a stray click on the editor frame.
Row controllers currently in the window.
Static Properties
Attributes settable via constructor options. Each key is the attribute name and the value is a schema object describing how to handle it.
Example
static assignableAttributes = {
anchor: { type: 'HTMLElement', default: null, null: true },
placement: { type: 'string', default: 'bottom', null: false },
enabled: { type: 'boolean', default: true, null: false },
data: { type: 'array', default: [], null: false }
}Properties
type
:
string
|
Array.<string>
expected type(s): 'string', 'number', 'boolean', 'object', 'array', 'function', or a class/element name like 'HTMLElement'
default
:
*
default value when none is provided
null
:
boolean
whether null is an acceptable value
load
:
function
optionaloptional transform applied when reading the attribute value
Methods overridable via constructor options
Methods to auto-bind to this
Event names that can be bound via onEventName constructor options
CSS injected once per component via adoptedStyleSheets
CSS @layer name used to wrap the component's styles when injected
via adoptedStyleSheets. Set to a falsy value to disable layering.
Attributes to observe for changes. Triggers changed(attribute, was, now) and [attribute]Changed(was, now) callbacks.
Instance Methods
Make cells focusable, set once per physical element (pooled cells keep it).
Begin editing a cell.
The column's input(record, session) receives an editing session a custom
editor can use to control completion (it also carries cell, column, record,
floater, and value — the typed character seeding a type-to-edit):
session.commit({ move })— end the edit, re-render the cell, optionally move the active cellsession.cancel()— end the edit without applying the bound input's changesession.hold(promise)— defer the closing re-render until the promise settles (e.g. an async save), however the edit ends (commit, blur, Enter/Tab)
Keyboard: Enter (without Shift) and Tab commit and navigate. An editor that wants a
key for itself (e.g. Enter inserting a newline in a textarea) stops its propagation —
or calls preventDefault() — on keydown and the spreadsheet leaves it alone.
Editors may also dispatch a bubbling commit CustomEvent instead of using the
session: detail.move and detail.promise map to commit({ move }) and hold().
Listen for events on another element, automatically cleaned up when this component disconnects
Parameters
element
:
HTMLElement
element to listen on
eventType
:
string
event type
args
:
*
additional arguments passed to addEventListener
Publish the column tracks + total width as custom properties on the grid.
The header and every row inherit --dg-template-columns / --dg-width via
CSS, so column geometry has a single update point (call this after any
column width/order change) instead of writing the template on each row.
at()
CellHandle at (column, row); negative indices count from the end.
Called every time an observed attribute changes. Attribute must be listed in static watch.
Parameters
attribute
:
string
the attribute that changed
was
:
*
previous value
now
:
*
new value
Called when element is connected to the DOM
TSV for the selection. Resolves each column's record per row (so off-screen rows are included and resolver columns serialize their sub-record). Returns a Promise; it settles synchronously when records are already loaded.
End the active editing session — the single exit path for Enter/Tab, an editor's
session.commit()/session.cancel(), and the commit event. Hides the editor
floater (its hidden callback re-renders the cell once any held work settles and
fires cellChanged), then moves the active cell or returns focus to the edited one.
Parameters
options
:
Object
optionalmove
:
string
optionaldirection for Spreadsheet#moveActive ('up'/'down'/'left'/'right'); omitted, focus returns to the cell
Called when element is disconnected from the DOM
Make (col, row) the active cell: collapse the selection onto it, scroll it into view, and move focus to it — the programmatic equivalent of a plain left-click, and the shared path behind a click, an un-extended arrow/Tab move, and a right-click collapse. Argument order matches DataGrid#at.
Parameters
col
:
number
Column index (0-based)
row
:
number
Row index (0-based)
Returns
SpreadsheetCell
|
null
the focused cell, if currently mounted
Called once per instantiation, but only after element is connected to the DOM
Whether a record's row renders readonly (non-editable) cells.
Read the system clipboard and paste it into the current selection. Use this for
programmatic paste (e.g. a context-menu Paste action); the native paste event in
Spreadsheet#setupSelection handles ⌘V/Ctrl+V directly. When the async
Clipboard API or its permission is unavailable, fall back to Spreadsheet#renderPasteModal
which explains the keyboard shortcuts.
Query mounted cells by CSS selector → handles (off-screen cells can't match).
reflow()
Recompute body size + reposition after a height change (from the observer).
Remove element. Fires remove, calls optional callback, removes from DOM, then fires removed.
Parameters
callback
:
function
optionalasync callback called between remove and removed
Returns
KompElement
this
Show the empty content in the body when there are no rows; remove it otherwise.
Show/hide the loading content in the body.
Called with no argument from DataGrid#updateWindow, it's automatic: the
loader shows while data is still resolving (before DataGrid#initializeRows
has built this.rows) and is removed once rows are in place. Because rows are
initialized last (after the scaffold + first window paint), a grid with async
data renders its header and a loader immediately.
The app can also call it directly to override that automatic behavior — e.g. while
reloading data, when this.rows still holds the previous payload:
grid.renderLoadingState(true) // force the loader on before refetching
grid.data = fetchRecords() // ...reassign data / rebuild rows...
await grid.initializeRows()
grid.renderLoadingState(false) // force it off (or null → back to automatic)
grid.updateWindow()
Parameters
active
:
boolean
|
null
optionalforce on (true) / off (false); null or
omitting it restores automatic behavior (shown only until rows resolve). An
explicit value persists across the automatic no-arg calls from updateWindow.
Fallback shown when the clipboard can't be read programmatically — explains the ⌘C/⌘X/⌘V (or Ctrl) shortcuts the user can still use.
The border box around the selection range — solid normally, dashed (.copy)
while a copy is pending (the marquee).
slice()
Rectangular range of CellHandles between two handles (row-major).
Splice the column set in place (Array#splice semantics over this.columns), then
rebuild the dependent structure: column indices, column geometry, the published
--dg-* custom properties, and the header. Mounted rows are bound to the previous
columns by index, so the window is torn down and rebuilt — recycled cells re-bind
to the new column set on the next updateWindow.
Parameters
index
:
number
0-based position to start at
deleteCount
:
number
optionalcolumns to remove at index
Returns
Array.<DataGridColumn>
the inserted column controllers
One step from {row,col} in a direction, clamped to the grid.
Trigger an event on this element
Parameters
eventName
:
string
event name to trigger
args
:
*
additional arguments
Compute the [start, end] row index range to mount, including overscan.
Events
connect
Fired before the element is connected to the DOM (cancellable)
Fired after the element is connected to the DOM and initialized
Fired before the element is disconnected from the DOM (cancellable)
Fired after the element is disconnected from the DOM
remove
Fired before the element is removed (cancellable)
removed
Fired after the element is removed