import as viewof etc.

I am probably missing something obvious here.

How do I import an interaction like Inputs.range()?

I might be missing the answer in Introduction to Imports / Observable / Observable but I don’t think I see exactly what I mean.

For example, is there a grammatical version of import {selectProjection as imported_selectProjection} from "@washpostgraphics/state-plane-selector" that gives an interactive viewof slider with an output useable in the new notebook?


Core question above. Not trying to make this over-broad but some related questions:

What is the most efficient or idiomatic way to pull in several elements?

In other words is it wrongheaded to think that I can treat a group of notebooks with elements I want to cite/combine/customize roughly like a cell of Python imports in a Jupyter notebook?

Should multiple dependencies be avoided past a point? Is it generally prudent to plan on some form of fork-combine-refactor-then-import-from-restaged-source or is it more common to link to the original(s) for updates?

When importing, is there a way to peek at or expand-text-to-a-copy-of the source implementation without referring to the source notebook?

On the other side of things, what is the best way to write for reusability and flexible importing?

Add the viewof prefix:

import {viewof selectProjection as imported_selectProjection} from "@washpostgraphics/state-plane-selector"

then create a cell containing

viewof imported_selectProjection

It doesn’t really matter. Even if you specify imports from the same notebook in multiple cells, they will still only cause a single fetch. E.g.

import {color} from "@observablehq/demo"
import {object} from "@observablehq/demo"

still gets compiled to

  main.define("module 1", async () => runtime.module((await import("/@observablehq/demo.js?v=4")).default));
  main.define("color", ["module 1", "@variable"], (_, v) => v.import("color", _));
  main.define("object", ["module 1", "@variable"], (_, v) => v.import("object", _));

Not at all! Observable recently added lazy loading for imports. Prior to that any imports would be loaded statically, regardless of whether they were actually referenced by any observed (i.e., active) cells. Now these dependencies will only be loaded if they are actually required by your imports.

No, because you’re not actually importing the cell contents, but the compiled source. However, you can quickly navigate to the source cell by clicking the link above your importing cell:
image

2 Likes

Sadly, many notebooks haven’t been created with reusability in mind. Unless they offer factory functions to instantiate elements, you’re essentially importing the same element over and over again, even if you specify your imports multiple times.

image

You can kind of import copies of a notebook. By modifiying the importing URL you can force each import to be considered as a separate ES module:

Use this technique at your own risk, and only as a last resort. Preferably you’d fork the notebook in question, modify it to make it reusable, and submit a suggestion to the original author.



I recommend that you split your remaining questions out into a separate topic, since they are largely unrelated to imports.

Will do, cheers!

Very helpful, thanks!

I really appreciate knowledgable people taking time to reply in depth to people like me, who are interesting in getting good enough at D3/Observable to make the kinds of things these tools (or more accurately, these types of communities) clearly make possible with time, but do-not-and-probably-will-never have a super solid JS/web foundation, and so are probably going to continue to do most work in Python/Jupyter and are constantly interweaving different levels of questions. I know it can be annoying to see a run-on post full of open-ended curiosity about how things are working/could work, but please know that thoughtful replies are GREATLY appreciated, read, and re-read.

1 Like

Thanks, I think I follow. To risk a bit of laziness–and mostly to try not to get too lost in the details–how do I spot instances of notebooks that “offer factory functions”? Will FFs be obvious syntactically or is it more of a larger pattern?

“URL&myCopy=N” tip is handy to know but as you recommend I will likely be forking/refactoring in most instances, so asking about FFs for this reason also–so I can aim for them when modifying.

Questions of all levels are welcome and appreciated! Please don’t take the brevity of my answers as a sign of impatience. :slight_smile:

Good (albeit complex) examples are the D3 charts. The question you can ask yourself is: Does this function create a new internal state, or does it reference state in some other cell? In the latter case we have no way to reset the state, and thus will likely not be able to create multiple instances of that feature.

Another aspect is composability and API surface. If you have a function that wraps complex functionality which may be considered opinionated, then you may want to give users a way to override or customize that functionality. This is also known as dependency injection.

To give a concrete example, my Signature helper lets you override several parts of its implementation via its options parameter, where the default values live in the same notebook:

function signature(fn, options = {}) {
  const {
    // [...]
    runTests = RUN_TESTS.promise,
    testRunner = defaultTestRunner,
    
    scope = DOM.uid('css-scope').id,
    css = signature_theme,
    formatter = defaultFormatter,
    
    signatureParser = defaultSignatureParser,
  } = options;
  // [...]
}

… and don’t forget to create a new topic for your remaining questions! I’m certain there are many people on this forum who would still like a chance to answer them. :slight_smile:

Very interesting. Thanks. I’ll chew on these examples a bit.

Will try to do this. Want to get a few more cells working first. Constantly envisioning complex visualizations I can’t personally realize in any reasonable amount of time…so the right level of fluency to try to attain vs just treating this as more of a social endeavor (‘I would like this to exist, does anyone out there feel like making it or perhaps has made it already?’) is a background consideration.

I’d still try to ask early on. People may be able to give you pointers, or even have links to notebooks that already implement part of what you’re trying to create.