Dropdown widget: can't register py callback

Hi all,

Thanks for all the hard work on bokeh, it is an amazing tool that’s been incredibly helpful.

I came across an error trying to set up a Dropdown widget after (finally) updating to bokeh 2.3.1 from 1.4.0. I can’t seem to register a python callback fn to the widget using either the .on_change(‘value’, cb) or .on_click(cb) methods. The first results in an AttributeError (no ‘value’ property); the second returns a bokeh.events.MenuItemClick. I’d expect the selected value from the dropdown to be passed to the callback in the second case.

I’m running this through jupyter lab using output_notebook. Example below.

Meantime, the Select widget provides the same functionality and works with on_change. So just posting this FYI / in the likely case I’m doing something wrong in the setup.


from bokeh.io import show, output_notebook

def make_example():
    from bokeh.plotting import figure
    from bokeh.models import Dropdown
    from bokeh.layouts import column
    def modify_doc(doc):
        empty_plot = figure(plot_height=400, plot_width=300, 
                            title='Placeholder')  # just to provide some room
        drop = Dropdown(label='Select Month', 
                        menu=['All']+[str(i+1) for i in range(12)])
        # below works with Bokeh <= 1.4.0
        def drop_on_change_cb(attr, old, new):
            print('Dropdown value: ' + str(new))
        #drop.on_change('value', drop_on_change_cb)
            # 2.3.1: throws AttributeError: Dropdown.value property descriptor does not exist
        # attempt for Bokeh 2.3.1 - use on_click instead
        def drop_on_click_cb(new):
            # returns a bokeh.events.MenuItemClick as 'new' which cannot be parsed as str
            print('Dropdown value: ' + str(new))

        doc.add_root(column(drop, empty_plot))
    return modify_doc


drop_example = make_example()


Bokeh change how Dropdown buttons were handled in version 2.0 in order to be more consistent with other button events. See this answer on SO for how to extract the item from the event:

Or this example in the documentation.

D’oh - .item, of course.

Thanks Bryan!

Snippet with correct syntax in case it’s helpful later:

def drop_on_click_cb(event):
    print('Dropdown value: ' + str(event.item))
1 Like