# Lwc Datatable Advanced

> Advanced lightning-datatable — inline edit, custom cell types, infinite scroll, row errors. Triggers: datatable inline edit, custom cell type, onloadmore. NOT for first-time datatable setup — use lwc/lwc-data-table. NOT for fully custom virtual grids — use lwc/lwc-virtualized-lists.

- Skill: `pranavnagrecha/lwc-datatable-advanced` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds add pranavnagrecha/lwc-datatable-advanced`
- Raw SKILL.md: https://api.skillmd.com/api/skills/pranavnagrecha/lwc-datatable-advanced/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: PranavNagrecha (https://skillmd.com/u/pranavnagrecha)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/pranavnagrecha/lwc-datatable-advanced

---


# LWC Datatable Advanced

`lightning-datatable` ships with the patterns that turn it into a
real grid: inline edit with batched save, sortable columns, row
selection, row actions, infinite scroll via `onloadmore`, custom
cell types via subclassing, and row-level errors that highlight
specific cells. The hard part is composing them together without
fighting the framework.

The recurring shape is: rows come from `@wire(getRecords)` or an
Apex method, columns are a JS array with `editable: true` flags,
the user changes cells, the table emits `draftValues` on Save,
the controller calls `updateRecord` (one per row, in parallel) and
clears drafts on success / surfaces row-level errors on failure.
Infinite scroll layers on by setting `enable-infinite-loading`
and handling `onloadmore`. Custom cell types layer on by importing
`LightningDatatable` and extending it.

The mistakes are about state management. Engineers persist `data`
as an array reference and mutate it (LWC reactivity drops);
engineers don't dedupe row IDs across pages (infinite scroll
duplicates rows on hot reload); engineers fire `updateRecord`
sequentially in a loop and burn 30 seconds on 50 rows when they
could `Promise.all` the lot.

## Recommended Workflow

1. **Define columns as a class field, not in the template.** A
   JS array `columns = [{label, fieldName, type, editable, sortable}]`
   with `data` and `draftValues` is the canonical shape. Inline
   `<lightning-datatable columns={...}>` is harder to read.
2. **Bulkify the inline-edit save.** On `onsave`, build an array
   of `{fields: {Id, ...changedFields}}` from `event.detail.draftValues`,
   then `Promise.all(updateRecord(...))` them. Sequential saves
   make 50-row commits feel broken.
3. **Reset `draftValues` only after the save succeeds.** Setting
   `this.draftValues = []` on submit clears the drafts but loses
   the user's edits if the save fails mid-flight. Reset in the
   `then` of `Promise.all`.
4. **For sorting, decide client-side vs server-side up front.**
   Client-side: implement `sortBy` / `sortDirection` and mutate a
   local copy of `data`. Server-side: refetch with the new sort,
   reset infinite scroll. Mixing the two leads to inconsistent
   ordering after pagination.
5. **For infinite scroll, dedupe by row Id on every append.** A
   refresh or hot reload can cause the same row to be appended
   twice. `data = [...data, ...newRows.filter(n => !existing.has(n.Id))]`.
6. **Custom cell types: extend `LightningDatatable`.** Import
   `LightningDatatable` from `lightning/datatable`, register the
   custom type with a template. The template runs in the table's
   shadow DOM, not your component's — class names must come from
   SLDS or be set via `--slds-c-*` tokens.
7. **Show row-level errors via `errors` attribute.** Map
   `{rowId: {messages, fieldNames, title}}` after a failed save
   so the user sees the exact cell that failed.

## What This Skill Does Not Cover

- **Fully custom grids (AG Grid, Tabulator)** — use those libraries
  in their own LWC wrapper; outside this skill's scope.
- **Read-only datatables for fewer than ~50 rows** — plain
  `lightning-datatable` with no extensions is sufficient.
- **Tree grids** — see `lwc/lwc-tree-grid`.

