This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/document-authoring/editing-content/tables.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. Tables

A table is block-level content, like a paragraph. Inside a transaction, use addTable() to add a table and build it from rows and cells.

Each table cell contains block-level content, so cell text lives in a paragraph inside the cell.

Before you start, make sure the Document Authoring library is installed and running in your app. If you haven’t set it up yet, refer to the getting started guide.

The examples omit error handling. Add it before you use this code in production.

Understand new table content

Before you build a table, note these behaviors:

  • A new table from addTable() starts with one empty cell.
  • Every row and cell you add already contains one empty paragraph.
  • addRow() sizes the new row to the table’s current column count, so appended rows already have the right number of cells.

Set a cell’s text on its existing paragraph instead of adding a new one. This helper does that and is reused throughout this guide:

function setCellText(cell, text) {
const [block] = cell.blocklevels(); // A cell always starts with one paragraph.
if (block && block.type === 'paragraph') {
block.asTextView().setText(text);
}
}

Build a table

A new table already contains one empty row. Remove that row first, and then add one row for each record. Pad each row’s cells up to the column count while the first row establishes the width. Then set each cell’s text:

const currentDoc = editor.currentDocument();
await currentDoc.transaction(async ({ draft }) => {
const table = draft.body().content().addTable();
table.removeRow(0); // Remove the empty row the new table came with.
const data = [
['Region', 'Revenue'],
['EMEA', '1.2M'],
['APAC', '0.8M'],
];
for (const rowValues of data) {
const row = table.addRow();
while (row.cells().length < rowValues.length) {
row.addCell();
}
rowValues.forEach((value, column) => setCellText(row.cells()[column], value));
}
return true;
});

Read a table

Find tables in the block-level content by checking their type. Then walk through rows() and cells(). A cell’s text is in its first paragraph:

await currentDoc.transaction(async ({ draft }) => {
for (const blockLevel of draft.body().content().blocklevels()) {
if (blockLevel.type !== 'table') continue;
for (const row of blockLevel.rows()) {
const values = row.cells().map((cell) => {
const [firstBlock] = cell.blocklevels();
return firstBlock?.type === 'paragraph'
? firstBlock.asTextView().getPlainText()
: '';
});
console.log(values.join(' | '));
}
}
return false;
});

Add and remove rows

Use addRow() to append a row sized to the table’s columns. Then set text on the row’s existing cells. Use removeRow() to remove the row at an index:

await currentDoc.transaction(async ({ draft }) => {
for (const blockLevel of draft.body().content().blocklevels()) {
if (blockLevel.type !== 'table') continue;
const row = blockLevel.addRow();
setCellText(row.cells()[0], 'LATAM');
setCellText(row.cells()[1], '0.3M');
blockLevel.removeRow(0); // Remove the first row.
break;
}
return true;
});

Add and remove columns

A table doesn’t have a column object. A column is the cell at the same position in each row.

To add a column, add a cell to every row. Each new cell includes an empty paragraph. To remove a column, call removeCell() at the same index on every row:

await currentDoc.transaction(async ({ draft }) => {
for (const blockLevel of draft.body().content().blocklevels()) {
if (blockLevel.type !== 'table') continue;
for (const row of blockLevel.rows()) {
setCellText(row.addCell(), '—');
}
break;
}
return true;
});

Learn more

Text and formatting
Format text inside cells.

Programmatic editing
Learn how transactions work and how to use the document model.