Skip to content

ReferenceLook things up as you need them.

Widgets and comms reference ​

The widget model that jupyter.widget(options) returns, and the comm API under jupyter.comm, with their arguments, return values and an example. Widgets and comms explains them with a full walk-through, including the view module. Examples that can run on their own show the output they produced; widgets run on the page.

This page is also a notebook. Its examples ran on the cdp-node kernel, and the output shown is what they produced.Download widgets-reference.ipynb · View on GitHub

Overview ​

A widget is an anywidget model: state that the kernel and its views share, and a view module that draws it. Use one for interactive output: controls, progress, a chart that updates.

A comm is the channel widgets are built on: messages both ways on a target name, with no shared state and no view. Use one to talk to a frontend extension that registered a target.

Widget model

MemberWhat it does
widget.get(key)The current value of a state key.
widget.set(key, value)Change one state key, or several at once, and sync the change to every view.
widget.fullState()The full state, as the frontend sees it: anywidget's model keys (_model_name, _view_name and the rest) and the widget's own.
widget.on(event, listener)Listen for state changes or custom messages from the views.
widget.off(event, listener)Remove a listener added with on.
widget.send(content, buffers?)Send a custom message to every view's model.on("msg:custom", ...).
widget.close()Close the model.

Comms

MemberWhat it does
jupyter.comm.open(targetName, data?, options?)Open a comm to a target the frontend registered.
jupyter.comm.registerTarget(targetName, handler)Accept comms the frontend opens on targetName.
jupyter.comm.unregisterTarget(targetName)Stop accepting new comms on targetName.
comm.send(data?, options?)Send a message to the frontend's end.
comm.close(data?, options?)Close the comm and tell the frontend.
comm.onMsg(handler)Handle messages from the frontend's end.
comm.onClose(handler)Handle the comm closing, from either end.

Widget model ​

An anywidget model, from jupyter.widget, synced with its frontend views. Display it to show a view; display it again for a second view of the same model.

jupyter.widget(options) returns it; see the jupyter reference.

State ​

The synced state, read and changed from the kernel.

widget.get(key) ​

ts
get(key: string): unknown;

The current value of a state key.

ParameterTypeRequiredDescription
keystringyesThe state key.

Returns unknown: Its value, or undefined.

ts
const w = jupyter.widget({ esm: "export default {}", state: { count: 0 } });
w.get("count"); // 0
0

widget.set(key, value) ​

ts
set(key: string, value: unknown): void;
set(changes: WidgetState): void;

Change one state key, or several at once, and sync the change to every view. Fires this model's own change listeners too. After close it changes the local state only.

ParameterTypeRequiredDescription
keystringnoThe state key.
valueunknownnoIts new value.
changesWidgetStatenoSeveral keys and their new values, instead of key and value.
ts
const w = jupyter.widget({ esm: "export default {}", state: { count: 0, label: "" } });
w.set("count", 1);
w.set({ count: 2, label: "two" });
ts
const progress = jupyter.widget({
  esm: `export default {
    render({ model, el }) {
      el.innerHTML =
        '<div class="progress-track"><div class="progress-fill"></div></div>' +
        '<div class="progress-label"></div>';
      const fill = el.querySelector(".progress-fill");
      const label = el.querySelector(".progress-label");
      const update = () => {
        const percent = Math.round(model.get("value") * 100);
        fill.style.width = percent + "%";
        label.textContent = model.get("message") + " (" + percent + "%)";
      };
      model.on("change:value", update);
      model.on("change:message", update);
      update();
    },
  };`,
  css: `
    .progress-track { width: 320px; height: 10px; border-radius: 5px; background: #e5e7eb; overflow: hidden; }
    .progress-fill { height: 100%; background: #2e6e64; transition: width 0.2s; }
    .progress-label { margin-top: 6px; font: 13px system-ui, sans-serif; color: #444; }
  `,
  state: { value: 0, message: "Starting" },
});
await jupyter.display(progress);

const files = ["january.csv", "february.csv", "march.csv", "april.csv", "may.csv"];
for (const [i, file] of files.entries()) {
  progress.set({ message: "Processing " + file, value: i / files.length });
  await new Promise((resolve) => setTimeout(resolve, 600)); // stand-in for real work
}
progress.set({ message: "Done", value: 1 });

Running from the saved notebook, with no kernel behind this page.

widget.fullState() ​

ts
fullState(): WidgetState;

The full state, as the frontend sees it: anywidget's model keys (_model_name, _view_name and the rest) and the widget's own.

Returns WidgetState: Every state key and its value.

ts
const w = jupyter.widget({ esm: "export default {}", state: { count: 0 } });
w.fullState(); // { _model_name: "AnyModel", _model_module: "anywidget", ..., count: 0 }
{
  _model_name: 'AnyModel',
  _model_module: 'anywidget',
  _model_module_version: '*',
  _view_name: 'AnyView',
  _view_module: 'anywidget',
  _view_module_version: '*',
  _view_count: null,
  _esm: 'export default {}',
  _anywidget_id: 'cdp-kernel.widget',
  count: 0
}

Events ​

State changes and custom messages from the views.

widget.on(event, listener) ​

ts
on(event: `change:${string}`, listener: (value: unknown, previous: unknown) => void | Promise<void>): void;
on(event: "change", listener: (changes: WidgetState) => void | Promise<void>): void;
on(event: "msg:custom", listener: (content: unknown, buffers: Uint8Array[]) => void | Promise<void>): void;

Listen for state changes or custom messages from the views. change:key gets the new and previous value; change gets all the changed keys; msg:custom gets a view's model.send content.

ParameterTypeRequiredDescription
eventdepends on the overload: see the signaturesyeschange:<key>, change or msg:custom.
listenerdepends on the overload: see the signaturesyesCalled for each event; may be async.
ts
const w = jupyter.widget({ esm: "export default {}", state: { count: 0 } });
w.on("change:count", (value, previous) => console.log(previous, "->", value));
w.on("msg:custom", (content) => console.log("view sent", content));
ts
const temperature = jupyter.widget({
  esm: `export default {
    render({ model, el }) {
      const slider = document.createElement("input");
      slider.type = "range";
      slider.min = "-20";
      slider.max = "40";
      const label = document.createElement("span");
      const update = () => {
        slider.value = String(model.get("celsius"));
        label.textContent = " " + model.get("celsius") + " °C is " + model.get("fahrenheit") + " °F";
      };
      slider.oninput = () => {
        model.set("celsius", slider.valueAsNumber);
        model.save_changes();
      };
      model.on("change:celsius", update);
      model.on("change:fahrenheit", update);
      update();
      el.append(slider, label);
    },
  };`,
  state: { celsius: 20, fahrenheit: 68 },
});

temperature.on("change:celsius", (celsius) => {
  temperature.set("fahrenheit", Math.round((Number(celsius) * 9) / 5 + 32));
});

temperature;

As the kernel left it after the docs build sent a slider move to 30 from the view. Running from the saved notebook, with no kernel behind this page.

widget.off(event, listener) ​

ts
off(event: string, listener: (...args: never[]) => unknown): void;

Remove a listener added with on.

ParameterTypeRequiredDescription
eventstringyesThe event it was added for.
listener(...args: never[]) => unknownyesThe same function.
ts
const w = jupyter.widget({ esm: "export default {}", state: { count: 0 } });
const log = (value: unknown) => console.log(value);
w.on("change:count", log);
w.off("change:count", log);

Custom messages ​

Messages to the views that aren't state; on("msg:custom", ...) receives theirs.

widget.send(content, buffers?) ​

ts
send(content: unknown, buffers?: Uint8Array[]): void;

Send a custom message to every view's model.on("msg:custom", ...).

ParameterTypeRequiredDescription
contentunknownyesJSON content.
buffersUint8Array[]noBinary buffers. Default [].
ts
const w = jupyter.widget({ esm: "export default {}" });
w.send({ type: "reset" });
ts
const dice = jupyter.widget({
  esm: `export default {
    render({ model, el }) {
      const button = document.createElement("button");
      button.textContent = "Roll 3 dice";
      button.onclick = () => model.send({ count: 3 });
      const result = document.createElement("span");
      result.style.marginLeft = "12px";
      result.style.fontSize = "24px";
      model.on("msg:custom", (message) => {
        result.textContent = message.faces + "  (total " + message.total + ")";
      });
      el.append(button, result);
    },
  };`,
});

dice.on("msg:custom", (content) => {
  const { count } = content as { count: number };
  const rolls = Array.from({ length: count }, () => 1 + Math.floor(Math.random() * 6));
  dice.send({
    faces: rolls.map((n) => "⚀⚁⚂⚃⚄⚅"[n - 1]).join(" "),
    total: rolls.reduce((a, b) => a + b, 0),
  });
});

dice;

As the kernel left it after the docs build sent a click from the view. Running from the saved notebook, with no kernel behind this page.

Closing ​

widget.close() ​

ts
close(): void;

Close the model. Its views stop syncing.

ts
const w = jupyter.widget({ esm: "export default {}" });
w.close();

Properties ​

PropertyTypeDescription
idstringThe model id (the comm id).
closedbooleanWhether the model has been closed.

Comms ​

jupyter.comm opens comms and accepts the ones the frontend opens; each is a Comm object.

jupyter.comm ​

jupyter.comm: open comms, and accept comms the frontend opens.

jupyter.comm.open(targetName, data?, options?) ​

ts
open(targetName: string, data?: { [key: string]: unknown }, options?: CommSendOptions): Comm;

Open a comm to a target the frontend registered.

ParameterTypeRequiredDescription
targetNamestringyesThe frontend's target name.
data{ [key: string]: unknown }noData sent with the open message. Default {}.
optionsCommSendOptionsnoMetadata and binary buffers.

Returns Comm: The kernel's end of the comm.

ts
const comm = jupyter.comm.open("my.target", { hello: 1 });
comm.onMsg((m) => console.log(m.data));

jupyter.comm.registerTarget(targetName, handler) ​

ts
registerTarget(targetName: string, handler: (comm: Comm, msg: CommMessage) => void | Promise<void>): void;

Accept comms the frontend opens on targetName. Registering the same name again replaces the handler.

ParameterTypeRequiredDescription
targetNamestringyesThe target name the frontend opens comms on.
handler(comm: Comm, msg: CommMessage) => void | Promise<void>yesCalled with the new comm and its open message.
ts
jupyter.comm.registerTarget("echo", (comm) => comm.onMsg((m) => comm.send(m.data)));

jupyter.comm.unregisterTarget(targetName) ​

ts
unregisterTarget(targetName: string): void;

Stop accepting new comms on targetName. Comms already open stay open.

ParameterTypeRequiredDescription
targetNamestringyesThe target to remove.
ts
jupyter.comm.unregisterTarget("echo");

Comm object ​

One end of a Jupyter comm channel, from jupyter.comm.open or a target handler.

comm.send(data?, options?) ​

ts
send(data?: { [key: string]: unknown }, options?: CommSendOptions): void;

Send a message to the frontend's end. Does nothing once closed.

ParameterTypeRequiredDescription
data{ [key: string]: unknown }noThe message's JSON data. Default {}.
optionsCommSendOptionsnoMetadata and binary buffers.
ts
const comm = jupyter.comm.open("my.target");
comm.send({ ping: true }, { buffers: [new Uint8Array([1, 2, 3])] });

comm.close(data?, options?) ​

ts
close(data?: { [key: string]: unknown }, options?: CommSendOptions): void;

Close the comm and tell the frontend. Its onClose handlers start right away, without being awaited. Does nothing once closed.

ParameterTypeRequiredDescription
data{ [key: string]: unknown }noData sent with the close message. Default {}.
optionsCommSendOptionsnoMetadata and binary buffers.
ts
const comm = jupyter.comm.open("my.target");
comm.close({ reason: "done" });

comm.onMsg(handler) ​

ts
onMsg(handler: (msg: CommMessage) => void | Promise<void>): void;

Handle messages from the frontend's end. A handler runs like a cell: its output goes to the notebook, and an exception shows on stderr.

ParameterTypeRequiredDescription
handler(msg: CommMessage) => void | Promise<void>yesCalled with each message; may be async.
ts
const comm = jupyter.comm.open("my.target");
comm.onMsg(({ data, buffers }) => console.log(data, buffers.length));

comm.onClose(handler) ​

ts
onClose(handler: (msg: CommMessage) => void | Promise<void>): void;

Handle the comm closing, from either end.

ParameterTypeRequiredDescription
handler(msg: CommMessage) => void | Promise<void>yesCalled with the close message; may be async.
ts
const comm = jupyter.comm.open("my.target");
comm.onClose(() => console.log("closed"));

Properties ​

PropertyTypeDescription
idstringThe comm id, shared with the frontend's end.
targetNamestringThe target the comm was opened on.
closedbooleanWhether either end has closed the comm.

Types ​

WidgetOptions ​

Options for jupyter.widget.

PropertyTypeRequiredDescription
esmstringyesThe anywidget view module, as source: export default { render({ model, el }) { ... } }. A ${...} inside a template literal here is filled in by the kernel, not the browser: escape it as \${...}.
cssstringnoCSS for the view.
stateWidgetStatenoThe initial synced state. Uint8Array and ArrayBuffer values travel as binary buffers. Default {}.

CommMessage ​

A comm message as a handler receives it.

PropertyTypeRequiredDescription
data{ [key: string]: unknown }yesThe message's JSON data.
metadata{ [key: string]: unknown }yesThe message's metadata.
buffersUint8Array[]yesBinary buffers sent with the message.

CommSendOptions ​

Options for sending, opening or closing a comm.

PropertyTypeRequiredDescription
metadata{ [key: string]: unknown }noMetadata for the message. Default {}.
buffersUint8Array[]noBinary buffers sent with the message. Default [].

MIT license. Parts are ports of Deno's Jupyter kernel, © the Deno authors.