---
title: "A diagram from a table"
description: "You can draw a table as a Mermaid flowchart, with one row per step."
canonical_url: "https://tiptap-docs.lin52025i.qzz.io/diagrams/flow-diagrams/from-table"
---

# A diagram from a table

You can draw a table as a Mermaid flowchart, with one row per step.

## Quick start

This needs the `chart.linkTables` option, as a [chart that follows a table](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables.md)
does. Take this table:

| Step        | Next             | Team      | Label             | Shape    |
| ----------- | ---------------- | --------- | ----------------- | -------- |
| Order in    | Check stock      | Sales     |                   | start    |
| Check stock | Pack, Back order | Warehouse | in stock, missing | decision |
| Pack        | Invoice          | Warehouse |                   |          |

Place the selection in the table and call:

```ts
editor.commands.insertDiagramFromTable({
  columns: { step: 'Step', next: 'Next', lane: 'Team', label: 'Label', shape: 'Shape' },
  title: 'Order process',
})
```

One undo takes back an edit of the table and the update of the diagram together.

## How the table is read

`columns` maps each role to a column, by its header text (ignoring case) or by its position from 0. Without `columns`, the extension guesses the roles from headers such as Step, Task, Next,
Then, Team, Owner, Label, Condition and Shape. When no header names `step` and `next`, it takes
the first remaining columns for them. It uses each column once.

| Role    | Required | Cell holds                                                                                                   | Becomes                    |
| ------- | -------- | ------------------------------------------------------------------------------------------------------------ | -------------------------- |
| `step`  | Yes      | The step's name                                                                                              | A node                     |
| `next`  | Yes      | The steps that follow, separated by commas                                                                   | Arrows to those steps      |
| `lane`  | No       | A lane name                                                                                                  | A `subgraph` with the step |
| `label` | No       | Arrow labels, separated by commas                                                                            | Text on the arrows         |
| `shape` | No       | A shape name, see [Shapes](https://tiptap-docs.lin52025i.qzz.io/diagrams/flow-diagrams/from-table.md#shapes) | The node's shape           |

- A step named only in a `next` cell is drawn too.
- A `label` cell gives one label per next step when the counts match. Otherwise, every arrow gets
  the whole cell.
- With `header: 'none'`, `columns` must give positions.

### Shapes

| Shape         | Cell text                             |
| ------------- | ------------------------------------- |
| Box           | `box`, `rect`, `task`                 |
| Rounded box   | `rounded`, `round`                    |
| Stadium       | `start`, `end`, `stadium`, `terminal` |
| Diamond       | `decision`, `diamond`, `gateway`      |
| Circle        | `circle`, `event`                     |
| Parallelogram | `data`                                |
| Cylinder      | `database`                            |
| Subroutine    | `subroutine`                          |

Any other text gives a box.

## When the table changes

- **Renaming a step** in its row renames it in every `next` cell too, so its arrows stay. Names
  are compared ignoring case and the spaces around them.
- **Emptying a step cell**, or giving it another step's name, is not a rename. The `next` cells
  stay as they are.
- **Changing a lane cell** moves that one step to another lane. To rename a lane in every row,
  use [`renameDiagramLane`](https://tiptap-docs.lin52025i.qzz.io/diagrams/flow-diagrams/from-table.md#renamediagramlane). Lanes are compared by their text without the
  spaces around it, case included.
- **Removing a column** that the link names keeps the diagram as it is, until the column is back.
- **Changing the source** with `updateFlowDiagram` ends the link, as `detachDiagramFromTable`
  does.
- **Double-clicking a shape** does not edit its text. The text belongs to the table.

## Stored in the document

| Where                        | What                                    |
| ---------------------------- | --------------------------------------- |
| The diagram's `options.link` | `{ tableId, columns, header?, range? }` |
| The table                    | A `chartTableId`                        |

Read the link with `flowDiagramLink(diagram)`, or as `link` in `listDiagrams()`, which also
returns the lanes as `lanes`. `updateLinkedTable` changes how the table is read.

## Commands

### insertDiagramFromTable

Inserts a flowchart drawn from the table at the selection, or at `table`.

```ts
editor.commands.insertDiagramFromTable({
  columns: { step: 'Step', next: 'Next', lane: 'Team' },
  title: 'Order process',
})

// A table without a header, without its last row
editor.commands.insertDiagramFromTable({
  header: 'none',
  range: { rows: { to: -2 } },
  columns: { step: 0, next: 1 },
})
```

| Option    | Type                                    | Description                                                                                                                                                        |
| --------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `columns` | `{ step, next, lane?, label?, shape? }` | Header texts or positions from 0. Guessed from the header when left out                                                                                            |
| `header`  | `'none'`                                | Reads every row as a step. Without it, the first row is the header                                                                                                 |
| `range`   | `{ rows }`                              | Reads only some rows, as for [`insertLinkedChart`](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables.md#insertlinkedchart). `range.columns` does not apply |
| `table`   | `number`                                | The table's position. Defaults to the table at the selection                                                                                                       |
| `title`   | `string`                                | The diagram's title                                                                                                                                                |
| `below`   | `boolean`                               | `false` inserts the diagram above the table. Default `true`                                                                                                        |

Returns `false` when a named column is not in the table, when the table has fewer than two
columns, when the selection is outside a table, or when `chart.linkTables` is off.

### linkDiagramToTable

Draws an existing diagram from a table, replacing its source, and makes it follow that table.

```ts
editor.commands.linkDiagramToTable({ table: tablePos, columns: { step: 'Step', next: 'Next' } })
```

It takes `table`, `columns`, `header?` and `range?` as `insertDiagramFromTable` does, and `pos?`
for a diagram other than the selected one.

### detachDiagramFromTable

Stops a diagram from following its table. The source stays, and you can edit it.

```ts
editor.commands.detachDiagramFromTable({ removeTable: true })
```

| Option        | Type      | Description                                                                                                                         |
| ------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `pos`         | `number`  | The diagram's position. Defaults to the selected diagram                                                                            |
| `removeTable` | `boolean` | Also removes the table, unless another chart or diagram follows it. It works like `setChartLayout({ layout: 'chart' })` for a chart |

Returns `false` for a diagram that follows no table.

### renameDiagramLane

Renames a lane in every row of the table, also in rows outside `range`. The diagram follows in
the same undo step.

```ts
editor.commands.renameDiagramLane({ lane: 'Warehouse', name: 'Warehouse North' })
```

| Option | Type     | Description                                              |
| ------ | -------- | -------------------------------------------------------- |
| `lane` | `string` | The lane's current name                                  |
| `name` | `string` | The new name                                             |
| `pos`  | `number` | The diagram's position. Defaults to the selected diagram |

Returns `false` for a diagram that follows no table, for a link without a `lane` column, for a
lane that no cell names, and for an empty `name`.

## Without an editor

These functions from `@tiptap-pro/extension-diagrams/core` do the work of the commands on the
cell texts of a table, such as on a server. `rows` is the cell texts, header row first unless
`read.header` is `'none'`.

| Function                                          | Returns                                                                                                               |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `tableToMermaid(rows, columns, read?)`            | The flowchart source, or `null` when a named column is missing                                                        |
| `guessTableDiagramColumns(header)`                | `columns` guessed from the header row, or `null` for fewer than two columns                                           |
| `tableStepRenames(before, after, columns, read?)` | `{ renames, firstRow, nextColumn }`. `renames` maps each old name (lower-cased, trimmed) to the new one, or is `null` |
| `stepRenameEdits(text, renames)`                  | The `{ from, to, text }` replacements for one `next` cell                                                             |
| `tableDiagramLanes(rows, columns, read?)`         | The lanes, in the order they appear                                                                                   |
| `tableLaneCells(rows, columns, read, lane)`       | The `{ row, column }` of every cell below the header that names `lane`                                                |
