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.