0

I am trying to export a Jupyter notebook as a static website.

So far I had been using jupyter nbconvert --execute --to html without any problem.

However, I would like to include ipywidgets. The widget in question, ipywidgets.AppLayout, contains an IPython.core.display.HTML which is causing problems.

Here is the relevant part:

from ipywidgets import AppLayout
from ipywidgets import HTML, Layout, Dropdown, Output, Label, Button
from IPython.display import display, clear_output

widget_1 = Dropdown(
    options=[1,2,3,4],
    description='1:'
)
widget_2 = Dropdown(
    options=["A","B","C","D"],
    description='2:'
)

html_out = Output()
with html_out:
    display(df.loc[widget_1.value, widget_2.value].HTML())

# Notice that it's an HTML object:
#  type(df.loc[widget_1.value, widget_2.value].HTML())
#  IPython.core.display.HTML
#
# And that it was already in memory/isn't generated at that moment:
#  ...
#  def HTML(self):
#       return self.__HTML

button = Button(description='Display')

def on_button_clicked(b):    
    with html_out:
        clear_output(True)
        display(df.loc[widget_1.value, widget_2.value].HTML())
    
button.on_click(on_button_clicked)

app=AppLayout(
    left_sidebar=VBox([
        widget_1,
        widget_2,
        button
    ]),
    center=html_out
)

app

I have a pandas dataframe with objects of the same class in each cell. The objects have a method, HTML, that returns a IPython.core.display.HTML that had already been generated and is in memory. Here is the code to the method:

def HTML(self):
    return self.__HTML

I want to display that depending on the selected values from widget_1 and widget_2.

When running the notebook in JupyterLab, everything works well, but by exporting to HTML using the previous method the widgets don't render. I know this is expected behavior, but I wonder how I can obtain a working widget.

I tried using embed_minimal_html and it does generated most of the widget, including the default state of html_out but it can't be updated using the widgets.

from ipywidgets.embed import embed_minimal_html

embed_minimal_html('export.html', views=[app], title='Widgets export')

I then tried voila which renders the whole notebook (which is even better) but, again, the html_out is not updated with the widgets.

Finally, I've seen that JupyterLite can be used to make notebooks run on the web leveraging Pyodide, but in that case the whole notebook is interactive and I want a static notebook with interactive widgets, or no notebook at all, just the widgets.

Any idea how I can include those objects, that are already in memory, in order to have a working widget in the HTML?

EDIT1: Added mention to Voila

BBG
  • 73
  • 1
  • 9
  • 1
    As you acknowledge, it is expected behavior with ipywidgets that rely on an an active Python or Pyodide-based kernel. Eventually when Voila works with Pyodide, you'll be able to have interactive ipywidgets based on Pyodide without the rest of the notebook interface being visible. For now the easiest is to use Plotly because your widgets are just dropdowns from what I see. Plotly's widgets have javascript running behind them and so they stay interactive as 'static' notebooks in nbviewer. However, your dataframe won't be in memory here so you cannot switch to it. – Wayne Mar 10 '23 at 20:56
  • You can though use Voila via MyBinder to serve active sessions that have code running behind it. These can be shared as active Voila but not as html_out. You need Python to run the data handling you need. Voila via mybinder can do that. Or [appmode](https://github.com/oschuett/appmode) via mybinder. – Wayne Mar 10 '23 at 20:58
  • I perhaps forgot to specify, but my intention was not needing a server backend. Voila working with Pyodide does sound like something that would work. I was thinking if it wouldn't be possible to export the HTML snippets to a JSON and then use the widgets to select which object is loaded. Would something like that be possible? – BBG Mar 10 '23 at 21:11
  • You can try the calculator in appmode via MyBInder by [clicking here](https://gke.mybinder.org/v2/gh/fomightez/test_json_appmode/9a1d16ec3953269e17a3d58d2b9ea579157f8aaa?urlpath=apps%2Findex.ipynb). There's an issue for now where you need to add an additional file to get it to work vai MyBinder.org, see [here](https://stackoverflow.com/a/75597849/8508004). So most/ALL(?) Appmode examples in the documentation won't work. – Wayne Mar 10 '23 at 21:12
  • Voila will eventually work with Pyodide; however, as far as I know it doesn't yet. You'll need Python to interact with the dataframe in memory for what you are trying to do. Whether it is WASM-based or not is your issue. But your code needs Python to put the dataframe in the namespace. – Wayne Mar 10 '23 at 21:14
  • Actually today no appmode is working. Odd. I had it working the other day. – Wayne Mar 10 '23 at 21:15
  • There is an entire section in the ipywidgets documentation about embedding widgets into HTML, see [here](https://ipywidgets.readthedocs.io/en/8.0.2/embedding.html). However, as I've said what you seek in your particular example involves active Python to have the Pandas dataframe. – Wayne Mar 10 '23 at 21:22
  • I think it would be easier to remove Python completely from this for now. You can do what you seek purely with Plotly Javascript directly in HTML. See [Plotly JavaScript Open Source Graphing Library](https://plotly.com/javascript/). It has dropdown menu widgets you can bind to your plot, see [here](https://plotly.com/javascript/dropdowns/). – Wayne Mar 11 '23 at 14:26
  • Voila does work with Pyodide now, see [voila/jupyterlite = Voici](https://github.com/voila-dashboards/voici)!! – Wayne Mar 17 '23 at 17:36

1 Answers1

0

You mention you tried Voila and commented later that Voila working with Pyodide does sound like something that work work. Let me introduce you to ...

Voila/JupyterLite = VOICI : in-browser WASM & Python-backed dashboards

"Voici turns any Jupyter Notebook into a static web application"

See Voici in action running inside your own browser

There is a button/badge on the Voici demo page that you can click and try a demo running inside your browser right now. It is web assembly (WASM) based so there is no remote server. It is using a virtual machine inside your browser to run the Python backing the interactivity.
This is the direct link to the demo entry portal. Select a notebook to open it in Voici.

Wayne
  • 6,607
  • 8
  • 36
  • 93