I’m working on a template that pulls values from a notebook. I call in each value from import for the notebook, and play it back out like this:
import {cookie, jar } from 'oBsCur3nMbrs'
then input these cells
cookie
jar
which wonderfully print out
chocolate
glass
Now, these are my data values / inputs - but I have values for 30 other people in other notebooks:
'1BsCur3nMbr'
'2BsCur3nMbrs'
'3BsCur3nMbrs'
'4BsCur3nMbrs'
...etc.
I tried to create another cell that names the notebook, populate it with values, and then to feed this value into an import
statement (aiming if this worked to create a toggle between different notebooks’ values):
membervalue = '1BsCur3nMbr'
import {cookie, jar } from membervalue
… but it failed [SyntaxError: Unexpected token
].
Is substitution of values into an import
statement even possible? If so, how?
Import statements cannot contain dynamic values. You’d have to utilize your own Runtime instance to import notebooks dynamically.
… Luckily Mike has already done the heavy lifting
1 Like
Thanks @mootari. I had caught that notebook when it came out and understood it to be an enhanced version of import ... with
(which I recall you suggested somewhere has some potential flaws). I didn’t realize the dataflow would help in this context. Certainly I can now toggle out the values thanks!
… Now I’m having trouble figuring out how to best manipulate these rendered cells. Currently I find it easiest to name and render them, then call the named cells into markdown [otherwise I’ve got some weird objects that I can get to play happily with md and html
cells]. Still, this gets weird, as the rendered objects are first visible in their cells then dragged across the DOM and relocated in my markdown fields on selection:
Any tips for streamlining this?
EDIT: Sorry - I saw you typing as I kept changing the notebook and answer.
At least for initial, you get a promise that returns a generator that yields a promise, which makes it rather awkward when you have to inline the value:
md`${await importCell('initial', value).then(gen => gen.next().value)}`
You’ll probably want to write a wrapper function around importCell()
that resolves a value completely before returning it.
With initial
there is another problem: The return value is an HTML element, so you can only anchor it once into the DOM (the reason why it disappears from the initial
cell).
To assign it to a reusable (i.e., consumable) value, I’d recommend one of these two approaches:
i = (await (await importCell('initial', value)).next().value).outerHTML
viewof i = Object.defineProperty(
await (await importCell('initial', value)).next().value,
'value',
{ get() { return this.outerHTML } }
)
You may also want to take a look at @j-f1’s fork:
https://observablehq.com/compare/cbe89acf8aadfc6d@136...d0bb058f650143a9@118
1 Like
Wow, this becomes rather complex rather quickly…
Thank you for your time and guidance in all of this!
You can simplify things by holding all imported values in a single cell. For example, if you change your select options to the full slug (e.g. "e695a608d52e208f"
to "d/e695a608d52e208f"
) you can do the following:
// import Jed's fork
import {importNotebook} from 'd0bb058f650143a9'
// Fetch and expose all data at once
data = {
const cells = ['initial', 'cookie', 'jar'];
const nb = await importNotebook(value);
return Promise.all(
cells.map(name => nb.cell(name).next().value.then(v => [name, v]))
).then(Object.fromEntries);
}
1 Like