Ipywidgets: Changing options of Select widget triggers Callback

Created on 27 Sep 2018  路  5Comments  路  Source: jupyter-widgets/ipywidgets

@jasongrout we should have a way to change the options of a Select widget without triggering the callback function. Whenever the options are changed for the widget the value attribute is automatically set which forces the callback to be triggered. See code below;

from ipywidgets import Select

# callback
def cb(change):
    print(change)

# widget
s_w = Select(value=None, options=['a','b'])
s_w.observe(cb, names='value')

# triggers no callback
s_w.value = None
# triggers callback
s_w.options = ['1', '2', '3']

Most helpful comment

@crahan my workaround has been to utilize the .unobserve method before updating the options.

s_w.unobserve(cb, 'value')
s_w.options = ['1','2','3']
s_w.observe(cb, 'value')

All 5 comments

Thanks!

As a dev note, I think we should special-case the code at https://github.com/jupyter-widgets/ipywidgets/blob/master/ipywidgets/widgets/widget_selection.py#L205-L212 so that if nothing is selected (as in the above code, where we explicitly set the value to None), we don't force a new selection.

I'm currently running into this issue. I'm writing a file browser widget. As soon as I click a folder entry in the list it triggers the callback function that configures the options with the new folder contents (as expected). However, the first option is always being selected and triggers a callback, making the code go into a loop as long as the automatically selected entry is a folder.

I'd be very interested in any potential workarounds until a more permanent solution is available.

@crahan my workaround has been to utilize the .unobserve method before updating the options.

s_w.unobserve(cb, 'value')
s_w.options = ['1','2','3']
s_w.observe(cb, 'value')

@nickpollari that is awesome! Thank you so much. Everything's working as expected now. I added a s_w.value = None to make sure nothing is marked as selected.

dircontent.unobserve(on_dircontent_select, names='value')
dircontent.options = get_dir_contents(path,showhidden=False)
dircontent.observe(on_dircontent_select, names='value')
dircontent.value=None

Here's a screenshot of the final result.

Screenshot 2019-04-04 at 21 41 39

Was this page helpful?
0 / 5 - 0 ratings