Skip to main content

Display views

notebook.view() returns a NotebookView. Browser evaluation starts when an anywidget host mounts it.

import marimo as mo
import observablejs as obs

notebook = obs.Notebook(
obs.js(
"""
const threshold = view(Inputs.range(
[0, 1],
{label: "Threshold", step: 0.05, value: 0.5}
));
""",
key="threshold",
),
obs.js(
'html`<p>Threshold: <strong>${threshold}</strong></p>`',
key="readout",
),
)

view = notebook.view()
mo.ui.anywidget(view)

Host idioms

In marimo, wrap the view with mo.ui.anywidget(view). In JupyterLab, Jupyter Notebook, VS Code notebooks, and Google Colab, leave the view as the final cell expression or pass it to IPython.display.display.

Colab requires the third-party widget support described by anywidget.

One view per placement

One NotebookView can appear in one live location at a time. Create a separate view for each location.

chart_a = notebook.view("readout")
chart_b = notebook.view("readout")

mo.hstack([mo.ui.anywidget(chart_a), mo.ui.anywidget(chart_b)])

The views receive the same notebook values and supported browser inputs. Each keeps its own rendered output, progress, results, errors, and graph.

Evaluation lifecycle

Before display, both revision fields are None. Display starts revision 0 and sets pending=True. A revision finishes after every selected cell either succeeds or fails.

state = view.state
ready = (
not state.pending
and state.input_revision is not None
and state.settled_revision == state.input_revision
)

Python variable updates and browser inputs start a new revision when selected cells need to run again. Assigning a new theme restarts each open view. Create a new view for a different selection. Create a new notebook for a different cell definition or set of files. A restarted view clears its previous graph while work is pending.

Close views

view.close()
notebook.close()

view.close() stops one browser run and ignores any late results. notebook.close() closes every view created from that notebook. Repeated calls do nothing.

Cells that own browser resources should release them through Observable's invalidation promise:

obs.js(
"""
const controller = new AbortController();
invalidation.then(() => controller.abort());

const response = await fetch(dataUrl, {signal: controller.signal});
const records = await response.json();
"""
)

Continue with Select cells or Widget composition.