How to update observable.value from within a callback?

I have a d3 chart that is using d3.drag() to gather data on user mouse placement. Everytime the user drags on the chart I want to update the value of my cell to be watched with a viewof.

My problem is I can’t figure out what the best way to get the new cell.value out of the callback scope. In normal JS development I would set up an observable, but, I figure there is a way to do it in a notebook without starting observable-ception.

The following is an example notebook of what I am talking about.
https://beta.observablehq.com/@nstrayer/how-to-get-data-out-of-internal-callback

1 Like

We’re hoping to add pleasant support for mutable-and-reactive values shortly, that should make patterns like these more obvious and straightforward to write — but in the meantime, you can already do it, because you can change the value of your view.

Instead of:

      //const to_return = svg.node();
      //to_return.value = [];
      //yield to_return;

Try something like this:

      const to_return = svg.node();
      to_return.value = data; // Or whatever you want your updated value to be.
      to_return.dispatchEvent(new CustomEvent("input"));

This works because viewof cells are designed to update themselves and their values whenever they hear an "input" event. It’s the API for manually telling a view: update!

3 Likes

Right—I don’t think you need mutation for a case like this. It’s a natural fit for viewof where you have a DOM element that is your display (your view) and a corresponding JavaScript value. The only thing you need to implement a custom view is to dispatch an input event and assign to element.value.

Here’s an example of dragging in a canvas that exposes the drawn stroke:

https://beta.observablehq.com/@mbostock/draw-me

(This one requires a mouse… I should probably update it to use d3-drag but it’s nice to have no dependencies.)

2 Likes

Here’s a “Draw Me” example using d3-drag:

1 Like

All of these worked wonderfully! Thanks a ton. I knew I had seen something about a dispatching new event method but couldn’t remember where or how.