manzt/anywidget

send custom message with new `initialize` function does not work yet

Closed this issue · 3 comments

Based on this conversation on the anywidget discord serve: https://discord.com/channels/1178781616714297576/1179097547235663972/1203737093558370425

using the new initialize function to send data does not work yet.

import anywidget
import traitlets

class CustomMessageWidget(anywidget.AnyWidget):
    _esm = """
    function initialize({ model, el }) {
      model.on("msg:custom", msg => {
         console.log(`new message: ${JSON.stringify(msg)}`);
       });
    }
    export default { initialize };
    """

widget = CustomMessageWidget()
widget.send({ "type": "my-event", "foo": "bar" })

image

I'm not sure we will find a general solution for this:

The current workaround (with tools like ipython_blocking) are seemingly platform-specific (tied to a specific kernel) and not very stable (kafonek/ipython_blocking#15).

Another issue is that messages are never captured in the notebooks, only the traitlet state. The pattern of using some Python code to send messages one way and wait for responses from the front-end falls down when you want to export widgets to environment where there is no Python backend. For example, a static HTML export of a notebook won't work.

The best thing to do is to build up some internal state representation using the Model (i.e., traitlets). Using the model guarantees that the state will be 1.) ready when first rendering, and 2.) saved to the notebook history.

I've been thinking about this quite a bit, and I don't think blocking for messages is something we can do consistently (nor is what is ideal for Widgets).

I think folks run into this because custom messages are a quick and easy way to get your Python and JS to talk to each other, but a proper "widget" requires extracting shared state into a Model (via traitlets) that both the Python and JS side both are designed to update accordingly when it changes. You have to "think" a bit more upfront about the design and implementation, but it benefits the most users and has the most meaningful Python integration.

Custom messages should be reserved for side effects, or transient data.

I have recategorized this issue as documentation, because it underscores a broader need for educational materials around widgets as opposed to some magic implementation we can make. anywidget makes it easy to make Jupyter Widgets, but the information on how to implement such widgets or basic widget concepts are scattered and limited.

My dream would be to have an in browser tutorial like svelte, probably running pyodide with anywidget (and some custom components) to walk through some examples of concepts. Probably a massive undertaking, but man would it be sweet and a great way to learn!

My dream would be to have an in browser tutorial like svelte, probably running pyodide with anywidget (and some custom components) to walk through some examples of concepts. Probably a massive undertaking, but man would it be sweet and a great way to learn!

At a minimum, maybe one big JupyterLite notebook (i.e., "the tutorial"), but I'd really love to have something more guided and interactive (e.g., edit the JS source and it updates instantly, rather than inlining scripts and re-running cells).

But maybe the big "notebook" is the best place to start. We could reorganize that into something more guided in the future, and use it as a place to iron out what content is useful to teach. Would you be interested in helping with something like this @kolibril13?