manzt / anywidget

reusable widgets made easy
https://anywidget.dev
MIT License
488 stars 38 forks source link

Using ipywidgets.embed on an anywidget widget throws a JavaScript error #339

Closed juba closed 1 year ago

juba commented 1 year ago

Hi,

I'm having trouble trying to save a widget created with anywidget to an HTML file with ipywidgets.embed.embed_minimal_html().

Here is a simple example:

import anywidget
import traitlets

class CounterWidget(anywidget.AnyWidget):
    _esm = """
    export function render({ model, el }) {
      let getCount = () => model.get("count");
      let button = document.createElement("button");
      button.classList.add("counter-button");
      button.innerHTML = `count is ${getCount()}`;
      button.addEventListener("click", () => {
        model.set("count", getCount() + 1);
        model.save_changes();
      });
      model.on("change:count", () => {
        button.innerHTML = `count is ${getCount()}`;
      });
      el.appendChild(button);
    }
    """
    _css = """
    .counter-button { background-color: #ea580c; }
    .counter-button:hover { background-color: #9a3412; }
    """
    count = traitlets.Int(0).tag(sync=True)

counter = CounterWidget()
counter.count = 42
counter

from ipywidgets.embed import embed_minimal_html

embed_minimal_html("/tmp/out.html", views=[counter])

Once opened in a browser, the resulting HTML file throws a JavaScript error:

Class null not found in module @jupyter-widgets/base@2.0.0

I'm not sure if it is a problem related to anywidget or if I don't use this feature correctly. I'm using anywidget 0.6.5.

Many thanks for all your work !

manzt commented 1 year ago

Thanks for opening this issue. I just had a look, and it seems the _esm and _css traits are considered defaults, which embed_minimal_html explicitly ignores when serializing state.

The error message you got doesn't seem to be helpful at all in resolving this issue, but I had the following work:

embed_minimal_html("/tmp/out.html", views=[counter], drop_defaults=False)

Can you let me know if this resolves your issue?

juba commented 1 year ago

Fantastic, I can confirm it solves the issue for my use case.

Many thanks !