Skip to content

Table Methods ​

Methods on the object returned by useTable(...).init().

typescript
const table = await useTable(page.locator('#my-table'), config).init();

→ API: Config Options · API: SmartRow


Lifecycle ​

init ​

Signature ​

typescript
init(options?: { timeout?: number }): Promise<TableResult<T>>

Parameters ​

  • options - Optional timeout for header resolution (default: 3000ms)

Resolves column headers and prepares the table for use. Must be called before any sync methods (getRow, getRowByIndex). Async methods auto-initialize if needed.

typescript
const table = await useTable(locator, config).init();
const table = await useTable(locator, config).init({ timeout: 5000 });

isInitialized ​

Signature ​

typescript
isInitialized(): boolean

Returns true if init() has completed successfully.

typescript
if (!table.isInitialized()) await table.init();

isEmpty ​

Signature ​

typescript
isEmpty(): boolean

Returns true when init() succeeded through the emptyState path: header resolution failed, but the configured empty-state locator was visible. Row operations still throw on an empty table, so check this before calling them.

typescript
await table.init();
if (table.isEmpty()) {
  await expect(page.getByText('No results')).toBeVisible();
  return;
}

currentPageIndex ​

Signature ​

typescript
currentPageIndex: number

0-based index of the page currently rendered in the DOM. Maintained by the library during pagination, bringIntoView(), and reset().

Treat it as read-only. Assigning it manually can desync the pagination path planner, and logs a warning (since v6.22.0). It may become read-only in v7.

typescript
await table.findRows({ Status: 'Active' }, { maxPages: 3 });
console.log(table.currentPageIndex); // e.g. 2

reset ​

Signature ​

typescript
reset(): Promise<void>

Resets table state (clears cached page position) and calls the onReset strategy if configured. Use after iteration to restore the table to its first page.

typescript
await table.reset();

revalidate ​

Signature ​

typescript
revalidate(): Promise<void>

Re-scans headers and rebuilds the column map without resetting pagination state. Use when columns change visibility or order dynamically (e.g., after toggling column visibility).

typescript
await table.revalidate();

Row Access ​

getRow ​

Signature ​

typescript
getRow(
  filters: Record<string, FilterValue>,
  options?: { exact?: boolean }
): SmartRow<T>

Finds a row on the current page only by column filters. Returns synchronously — does not paginate. Because the sync path can't compute a real index, the returned row's rowIndex is undefined (so bringIntoView() is limited); use findRow when you need a row with an accurate rowIndex.

typescript
const row = table.getRow({ Name: 'John Doe' });
const email = await row.getCell('Email').innerText();

WARNING

getRow only searches the currently visible page. Use findRow to search across pages.

→ Guide: Find Rows


getRowByIndex ​

Signature ​

typescript
getRowByIndex(
  index: number
): SmartRow<T>

Parameters ​

  • index - 0-based position within the current render window

Gets a row by its 0-based position in the currently-rendered DOM — synchronous, no scroll.

For button-paginated tables this is the i-th row on the current page. For virtualized tables the render window shifts as you scroll, so getRowByIndex(i) returns whatever row currently sits at DOM position i, not the logical/absolute row i in the dataset once the list has scrolled. To iterate virtualized rows by their logical identity, use map / findRows with a dedupe strategy.

Resolution is lazy: an out-of-range index returns a SmartRow whose operations fail when it is used, rather than throwing here.

typescript
// i-th row currently rendered (e.g. row 0 of the current page)
const firstRow = table.getRowByIndex(0);

findRowByIndex ​

Signature ​

typescript
findRowByIndex(
  index: number,
  options?: { maxPages?: number, signal?: AbortSignal }
): Promise<SmartRow<T>>

Parameters ​

  • index - 0-based logical/data-model row index
  • options - maxPages bounds how far to scroll/paginate (defaults to config.maxPages).

Returns the row with a specific logical (data-model) index, scrolling or paginating to reach it. Unlike getRowByIndex, which returns whatever sits at a DOM position, this finds the true row index in the dataset on virtualized tables.

The row is reached by, in order:

  1. a currently-mounted row whose logical index matches
  2. strategies.viewport.scrollToRow (random-access jump), if configured
  3. advancing pages (on infinite-scroll tables, a "page" is a scroll step), up to maxPages

Requires strategies.resolveRowIndex; throws if it isn't configured. Also throws if the row can't be reached — it never falls back to a different row.

typescript
const row = await table.findRowByIndex(250, { maxPages: 50 });
await expect(row.getCell('ID')).toHaveText('250');

findRow ​

Signature ​

typescript
findRow(
  filters: Record<string, FilterValue>,
  options?: { exact?: boolean, maxPages?: number, signal?: AbortSignal }
): Promise<SmartRow<T>>

Parameters ​

  • filters - The filter criteria to match
  • options - Search options including exact match and max pages. signal cancels the page scan; the call rejects with signal.reason.

Searches for a single matching row across pages. Paginates automatically. Returns the first match.

typescript
const row = await table.findRow({ Email: 'john@example.com' });
const row = await table.findRow({ Status: 'Active' }, { maxPages: 10 });

→ Guide: Find Rows


findRows ​

Signature ​

typescript
findRows(
  filters?: Record<string, FilterValue>,
  options?: { exact?: boolean, maxPages?: number, useBulkPagination?: boolean, signal?: AbortSignal }
): Promise<SmartRowArray<T>>

Parameters ​

  • filters - The filter criteria to match (omit or pass {} for all rows)
  • options - Search options (exact, maxPages). useBulkPagination defaults to false: pages advance one at a time via goNext so no intermediate page is skipped. Set it to true to opt into goNextBulk (faster, but skips the rows on jumped-over pages). signal cancels the page scan; the call rejects with signal.reason.

Searches for all matching rows across pages. Pass empty filters {} or omit to collect every row.

Returned rows can be read individually, sequentially, or with different column selections, even when the table's concurrency is 'synchronized'. The array's toJSON() helper reads rows sequentially to avoid competing viewport moves. For coordinated column scrolling across virtualized rows, use map(({ row }) => row.toJSON(), { concurrency: 'synchronized' }).

typescript
const activeRows = await table.findRows({ Status: 'Active' });
const allRows = await table.findRows();

→ Guide: Find Rows


Iteration ​

forEach ​

Signature ​

typescript
forEach(
  callback: (ctx: RowIterationContext<T>) => void | Promise<void>,
  options?: RowIterationOptions
): Promise<void>

Parameters ​

  • callback - Function receiving
  • options - maxPages, concurrency, dedupe, useBulkPagination

Iterates every row across all pages. Runs sequentially by default. Call stop() in the callback to halt early. In sequential mode no rows after the one that called it are visited; in parallel mode the rest of the current page may still run.

typescript
await table.forEach(async ({ row, stop }) => {
  const status = await row.getCell('Status').innerText();
  if (status === 'Archived') stop();
  await row.getCell('Checkbox').click();
});

→ Guide: Iterate Rows


map ​

Signature ​

typescript
map<R>(
  callback: (ctx: RowIterationContext<T>) => R | Promise<R>,
  options?: RowIterationOptions
): Promise<R[]>

Parameters ​

  • callback - Function receiving
  • options - maxPages, concurrency, dedupe, useBulkPagination

Transforms every row across all pages into a value. Runs sequentially by default (since v6.22.0), which is safe for callbacks that click, fill, or open popovers. Pass concurrency: 'parallel' for read-only extraction when speed matters.

typescript
// Default (sequential) — safe for UI interactions
const results = await table.map(async ({ row }) => {
  await row.getCell('Actions').locator('button').click();
  return page.locator('.dialog .title').innerText();
});

// Read-only — opt into parallel
const emails = await table.map(
  ({ row }) => row.getCell('Email').innerText(),
  { concurrency: 'parallel' }
);

→ Guide: Iterate Rows


toArray ​

Signature ​

typescript
toArray<R = Record<string, unknown>>(
  callback?: (ctx: RowIterationContext<T>) => R | Promise<R>,
  options?: RowIterationOptions
): Promise<R[]>

Parameters ​

  • callback - Optional map function. Defaults to ({ row }) => row.toJSON().
  • options - Same options as map().

Shorthand for map() followed by reset(). Iterates every row across all pages, applies the callback (defaults to row.toJSON()), then resets the table to page 1 — even if the callback throws. Accepts the same options as map.

typescript
// Every row as JSON
const rows = await table.toArray();

// Custom callback
const names = await table.toArray(({ row }) => row.getCell('Name').innerText());

→ Guide: Iterate Rows


filter ​

Signature ​

typescript
filter(
  predicate: (ctx: RowIterationContext<T>) => boolean | Promise<boolean>,
  options?: RowIterationOptions
): Promise<SmartRowArray<T>>

Parameters ​

  • predicate - Function receiving
  • options - maxPages, concurrency, dedupe, useBulkPagination

Collects rows matching an async predicate across all pages. Returns a SmartRowArray.

typescript
const highEarners = await table.filter(async ({ row }) => {
  const salary = await row.getCell('Salary').innerText();
  return parseInt(salary.replace(/\D/g, '')) > 50000;
});

→ Guide: Iterate Rows


Async iteration ​

The table implements AsyncIterable, so you can use for await...of for fine-grained control with break:

typescript
for await (const { row, rowIndex } of table) {
  if (await row.getCell('Status').innerText() === 'Archived') break;
}

→ Guide: Iterate Rows


Column Utilities ​

getHeaders ​

Signature ​

typescript
getHeaders(): Promise<string[]>

Returns the resolved column header names in order.

typescript
const headers = await table.getHeaders();
// ['Name', 'Email', 'Status', ...]

getHeaderCell ​

Signature ​

typescript
getHeaderCell(columnName: string): Promise<Locator>

Returns a Locator for the header cell of a named column.

typescript
const nameHeader = await table.getHeaderCell('Name');
await nameHeader.click(); // sort by Name

scrollToColumn ​

Signature ​

typescript
scrollToColumn(columnName: string): Promise<void>

Scrolls horizontally to bring a column into view. Prefers strategies.viewport.scrollToColumn when configured; otherwise scrolls the header cell with Playwright's scrollIntoViewIfNeeded().

typescript
await table.scrollToColumn('Notes');

countRows ​

Signature ​

typescript
countRows(filters?: Record<string, FilterValue>, options?: { exact?: boolean; maxPages?: number; signal?: AbortSignal }): Promise<number>

Returns the number of rows currently visible on the page. Does not paginate.

typescript
const count = await table.countRows();

mapColumn ​

Signature ​

typescript
mapColumn<R = string>(columnName: string, options?: RowIterationOptions): Promise<R[]>

Parameters ​

  • columnName - The name of the column to extract
  • options - Iteration options

Extracts all values for a single column across pages. More efficient than map + toJSON for single-column reads.

typescript
const statuses = await table.mapColumn('Status');
const counts = await table.mapColumn<number>('Count');

getColumnValues ​

Deprecated — use mapColumn (or map) instead. Will be removed in v7.0.0.

Signature ​

typescript
getColumnValues(columnName: string, options?: RowIterationOptions): Promise<string[]>

Parameters ​

  • columnName - The name of the column to extract
  • options - Iteration options

Extracts all values for a single column as strings. Convenience wrapper around mapColumn.

typescript
// Preferred:
const names = await table.mapColumn('Name');
// Deprecated:
const namesLegacy = await table.getColumnValues('Name');

Sorting ​

sorting.apply ​

Signature ​

typescript
sorting: {
  apply(columnName: string, direction: 'asc' | 'desc'): Promise<void>;
  getState(columnName: string): Promise<'asc' | 'desc' | 'none'>;
}

Parameters ​

  • columnName - The name of the column to check.

Applies the configured sorting strategy to a column.

typescript
await table.sorting.apply('Name', 'asc');
await table.sorting.apply('Created At', 'desc');

→ API: Strategies — sorting


Diagnostics ​

generateConfig ​

Signature ​

typescript
generateConfig(): Promise<void>

Dumps table HTML and TypeScript type definitions to help generate PST configuration. Intentionally throws an error containing the prompt — copy the output and pass it to an AI assistant.

typescript
await table.generateConfig();