Hi, I would like some help getting our Clustergrammer-GL library to work reactively on Observable. This example Trying to make Clustergrammer-GL Reactive / Nicolas Fernandez / Observable shows a pre-calculated hierarchically clustered dataset (JSON loaded as file attachment) being visualized using our library (big thanks to @john-guerra for help us get our library working on Observable). Clustergrammer-GL updates variables (e.g. cgm.param.int.mouseover.row.name) based on user interaction. However, these variable updates appear to be incompatible with Observable’s reactive updates (at least in the way I’m trying to implement them). I would like help understanding if/how I could have Observable reactively update variables based on user interaction with the Clustergrammer-GL visualization. Based on my reading, I think the solution might involve using views and setting up an input event.
We are currently able to get this type of behavior in Jupyter notebooks using: Clustergrammer2 widget library (which Clustergrammer-GL is a dependency), the widget bqplot, the dashboard library voila, and the hosting service MyBinder. See example: GitHub - cornhundred/citibike-clustergrammer2.
Any help or advice would be greatly appreciated and we would love to get this CitiBike example on Observable as well !
Clustergrammer-GL requires that the container be inserted into the DOM before initializing, and requires a globally-unique identifier for that container. If it didn’t have these requirements, it would be easier to initialize in Observable (where cells normally run with detached DOM elements, and only insert them into the DOM by returning a value at the end).
The most natural way to make Clustergrammer-GL reactive would be for it to emit custom events when things change. I did that manually by intercepting when some internal parameters are set, and by listening to browser native events (mousemove). But if Clustergrammer-GL emitted these events itself, it’d be more straightforward to expose those as reactive values in Observable using Generators.observe.
It’s best to avoid bundle.run in notebooks, as it isn’t very reliable. I re-attached the generated bundle to your notebook, but if you published an AMD- or UMD-compatible bundle to npm, then folks could require("clustergrammer-gl") and it would work out of the box.
Hope this helps! Please let us know if you have more questions.
Thank you for all the help @mbostock!! I see the state is now reactive, but I will have to do some homework to figure out how everything is working and see if I can make your recommended changes. I’ll let you know if I have any more questions!
Another quick question, I merged your changes to the notebook, but is there a way to see the previous suggestions?
Thanks, I see the changes but I do not see the suggestions/comments (little text boxes) from before. There was a suggestion/comment about not using bundle.run but I don’t see it after merging - it’s not a huge deal cause I think you said the same thing here in this thread.
Also, just a little suggestion - the color scheme for showing parent and fork changes is a little difficult for me to see (red/green colorblind).
Are you seeing an error loading clustergrammer-gl from the file attachment? That seems to work fine for me, although I also see you’re using bundle.run to load @octokit/rest, and that fails. So you might try attaching that as a file attachment, too.
But I’m getting an invalid module error with that file.
I followed the instructions to host my own local instance (https://github.com/Rich-Harris/packd#hosting-an-instance) and was able to bundle the package. This feels like a convoluted solution but it appears to work. I’ll update when I understand how to do this in a more streamlined manner (e.g. build the bundle automatically, add it into the package.json, have it hosted on a CDN).