pythonjupyter-notebookdatabricksipywidgetsdatabricks-notebook

Dynamically create and display ipywidgets, failing in databricks notebook


Goal: An array of ipywidgets, that can be extended through a button-click on the UI.

import ipywidgets as widgets
from IPython.display import display

# Keeps track of default and dynamically added widgets
widgets_list = [widgets.Text(value='Give me')]

w_out_widgets_list = widgets.Output()
# display defaults
w_out_widgets_list.append_display_data(widgets.HBox(widgets_list))  

def add_new_widget(b):
    with w_out_widgets_list:
        widgets_list.append(widgets.Text(value='more and '))
        w_out_widgets_list.clear_output()
        display(widgets.HBox(widgets_list))

w_new_widget = widgets.Button(description='Add Widget')
w_new_widget.on_click(add_new_widget)

display(widgets.VBox([w_out_widgets_list, w_new_widget]))

This is working as expected in my locally running jupyter notebook.

Within the databricks notebook, a strange behaviour is observable:

Not understood behavior within databricks

ipywidgets are on version 7.7.2 there.

Any ideas on what the cause of this behavior is?


Solution

  • My guess is, that the identification of currently active widget Output varied from databricks to local Jupyter Notebook.

    Wrapping the functionality in a class allows to recreate the expected behavior within databricks, too:

    import ipywidgets as widgets
    
    
    class App:
        def __init__(self):
            self.widgets_list = [widgets.Text(value="Give me")]
            self.w_new_widget = widgets.Button(description="Add Widget")
            self.w_new_widget.on_click(self.add_new_widget)
            self.app_out = widgets.Output()
            self.generate_layout()
    
        def generate_layout(self):
            self.app_out.clear_output()
            with self.app_out:
                display(widgets.VBox([widgets.HBox(self.widgets_list),
                                      self.w_new_widget]))
    
        def add_new_widget(self, *args):
            self.widgets_list.append(widgets.Text(value="more and "))
            self.generate_layout()
    
    
    app = App()
    display(app.app_out)