A versatile table/datagrid component with built-in keyboard navigation for displaying and interacting with structured data. Use it for anything from simple read-only tables to fully interactive, spreadsheet experiences.
Approach
The grid leverages two approaches to maximize render performance including CSS Contain and Element Internal States Performance depends on the elements rendered within the grid itself. Average performance of 1000 rows and 4000 cells is around 250–300 ms in a typical application. Extra elements within cells add to the total render time. Use pagination or batch rendering to improve total initial render performance.
Best Practices
When rendering large datasets, using the appropriate techniques to maintain good performance matters. - Use pagination or lazy loading to reduce initial render time - Use virtual scroll or batch rendering to improve render performance - Use fixed width columns to improve render performance and reduce layout shift - Avoid duplication of elements within cells, example reuse a single tooltip for all cells vs creating a new tooltip for each cell
Infinite Scroll
Batch rendering allows you to dynamically add rows for improved performance. The grid dispatches a scrollboxend event when the user has scrolled to the end of the current scroll box. When the event occurs you can append more rows.
Lit Example
@customElement('batch-render-demo')
class BatchRenderDemo extends LitElement {
@state() rows = [];
render() {
return html`
<nve-grid style="--scroll-height: 400px" @scrollboxend=${() => this.#loadNextGroup()}>
...
${this.rows.map(row => html`<nve-grid-row>...</nve-grid-row>`)}
</nve-grid>
`
}
connectedCallback() {
super.connectedCallback();
this.#loadNextGroup();
}
#loadNextGroup() {
this.rows = [...this.rows, ...getNextBatch()];
}
}
Virtual Scroll
You can add Virtual Scroll using a virtual scroll package such as @lit-labs/virtualizer or @angular/cdk. When using a virtual scroll container apply the scroller attribute for the grid to know the assigned scrolling container.
Lit Example
@customElement('grid-virtual-scroll-demo')
class GridVirtualScrollDemo extends LitElement {
items = new Array(10000).fill('').map((_i, n) => ({ column: `${n}-0`, column1: `${n}-1`, column2: `${n}-2`, column3: `${n}-3` }));
render() {
return html`
<nve-grid>
<nve-grid-header>
<nve-grid-column>column</nve-grid-column>
<nve-grid-column>column</nve-grid-column>
<nve-grid-column>column</nve-grid-column>
<nve-grid-column>column</nve-grid-column>
</nve-grid-header>
<lit-virtualizer style="min-height: 300px" scroller .items=${this.items} .renderItem=${i => html`
<nve-grid-row style="width: 100%">
${Object.keys(i).map(key => html`<nve-grid-cell>${i[key]}</nve-grid-cell>`)}
</nve-grid-row>`}>
</lit-virtualizer>
</nve-grid>
`;
}
}