🏠 back to Observable

How to update a value from js in embedded observablehq notebook?

#1

I followed the guide on embedding notebooks but due to some quirks (bugs?) of third-party library I have to force an update of a cell.

How in observable I can programmatically change the variable and force the dependency graph to recompute?

#2

Hello. Did you figure out how to do it? @alfa07

#3

This would be easier to answer with a concrete code / website example. But let me try anyways.

Suppose you have the following code (copied from the runtime docs) to embed a notebook using the v3 runtime:

import {Runtime, Inspector} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@4/dist/runtime.js";
import define from "https://api.observablehq.com/@tmcw/hello-world.js?v=3";

const runtime = new Runtime();
const main = runtime.module(define, Inspector.into(document.body));

If the cell you want to redefine is named name, then you can redefine it from scratch using the redefine method:

const v = main.redefine("name", inputs, definition);

You’ll have to have defined an array inputs (containing the names of the dependencies of your cell) and a function definition, though. You can copy these from the v3 module source of your notebook (the file at https://api.observablehq.com/XXX.js?v=3).

There’s also a way to redefine the variable without copying and pasting inputs and definition, but it relies on some internal properties. The idea is to first get the old variable object from the _scope Map of the main module and then trigger a redefinition using the properties of the old variable:

const v0 = main._scope.get("name");
const v = main.redefine("name", v0._inputs, v0._definition);

There’s a way to do it for notebooks embedded using the v1 runtime as well, (the main difference is you have to grab the module object from the runtime returned by Runtime.load) but you should probably upgrade to v3…

2 Likes
#4

Using the API of the Observable Runtime, you can re-define a variable (aka, a cell) … forcing it, and all of its dependent cells to recompute.

So, using V3 of the Runtime format:

import {Runtime, Inspector} from "https://cdn.jsdelivr.net/npm/@observablehq/runtime@4/dist/runtime.js";
import notebook from "https://api.observablehq.com/@tmcw/hello-world.js?v=3";

const runtime = new Runtime();
const main = runtime.module(notebook, name => {
  // Observer code goes here...
);

Then, later on in your code:

main.redefine("myVariable") ....

Whoops, @bgchen beat me to the punch! Might as well stop typing…

2 Likes
#5

You guys are awesome! Thanks a lot! @bgchen @jashkenas