Interactive tables¶
add_table() renders a static HTML table. When you want the reader to sort,
filter, paginate, group, edit, or download the data, use add_tabulator() —
backed by Tabulator (bundled, MIT-licensed). It needs
the Tabulator plugin:
from montin import Deck, Plugins
deck = Deck(title="Report", plugins=[Plugins.Tabulator()])
slide = deck.add_slide("Sales")
slide.add_tabulator(df, header_filter=True)
It takes the same inputs as add_table — a dict of columns, a list[list]
(first row = headers), a pandas DataFrame, a CSV/TSV string, or a path to a
CSV/TSV file:
slide.add_tabulator("data/sales.csv") # a file path
slide.add_tabulator({"Name": [...], "Age": [...]})
slide.add_tabulator(my_dataframe)
Common options¶
These cover the whole table and are passed straight to add_tabulator():
Option |
Default |
What it does |
|---|---|---|
|
|
Column sizing: |
|
|
Collapse overflowing columns into an expandable row on narrow widths. |
|
|
Page size (an int) — enables paging and a row counter. |
|
|
|
|
|
A column name (or list) to group rows under collapsible headers. |
|
|
Add a filter input to every column header. |
|
|
Column name(s) pinned while scrolling horizontally. |
|
|
Number of rows pinned to the top. |
|
|
Let the reader drag columns to reorder them. |
|
|
Remember the reader’s sort/filter/column tweaks across reloads (opt-in). |
|
|
A list of |
|
|
A fixed height (e.g. |
Note
Persistence is off by default. When enabled (persistence=True), each
table remembers the reader’s sort/filter/column tweaks in the browser
(localStorage), keyed by an id derived from the deck title, slide, cell, and
column structure. It’s off by default because a saved layout can outlive the
data it described — change the table (or open a different report from disk, where
file:// shares one storage bucket) and the restored layout no longer matches,
rendering the table broken. Folding the column structure into the key avoids the
worst of that, but opt in only for stable reports a reader returns to.
Per-column behaviour — columns=¶
Formatters, editors, calculations, freezing, and header filters are per column.
Pass columns= a list of Tabulator column definitions;
each is matched to your data by title (or field) and merged over the
auto-generated column, so you only specify what you change:
slide.add_tabulator(df, columns=[
{"title": "Revenue", "formatter": "money",
"formatterParams": {"symbol": "$"}, "bottomCalc": "sum"},
{"title": "Margin", "formatter": "progress", "bottomCalc": "avg"},
{"title": "Rating", "formatter": "star", "formatterParams": {"stars": 5}},
{"title": "Reviewed","formatter": "tickCross", "editor": True},
])
Useful column keys:
Formatters:
money,image,link,html,tickCross,color,star,progress,rownum,buttonTick,buttonCross— via"formatter"/"formatterParams".Editing:
"editor"("input","number",Truefor a checkbox, …) makes a column editable — handy for marking rows already double-checked.Calculations:
"topCalc"/"bottomCalc"("sum","avg","min","max","count") add a calculation row.Layout:
"frozen","widthGrow","widthShrink","headerFilter","headerVertical".Column groups (multi-line headers): nest columns under a group with a
"columns"key:{"title": "Q1", "columns": [{"title": "Jan", ...}, ...]}.
Grouping, editing & download¶
Anything else — options=¶
add_tabulator() exposes the common cases; the full Tabulator option set is
available through options=, a dict merged verbatim into the constructor (and
taking precedence over the keyword options). Use it for the long tail:
slide.add_tabulator(df, options={
"movableRows": True, # drag to reorder rows
"history": True, # undo/redo of edits
"rowHeader": {"formatter": "rowSelection"},
"locale": "pt-br", # localisation
"langs": {"pt-br": {...}},
})
Spreadsheet mode, multi-sheet workbooks, nested tables, range selection, and
interaction history are all reachable this way — see the
Tabulator docs. Excel (xlsx) download needs
an extra library (SheetJS) that Montin does not bundle, so download covers
csv and json only.
Offline & themes¶
Like every plugin, Tabulator is bundled (offline) or loaded from a CDN — see
Plugins and Security & offline use. It works under
Security(block_external=True). The table styling follows the deck theme
automatically; Plugins.Tabulator(theme="light") / "dark" forces a specific
look.