4

I'm using interactive ipywidget dropdown to filter a certain amount of datas and to plot graph with plotly.

My problem is on the update of the dropdown widget : here is a simplified example :

    import ipywidgets as widgets
from ipywidgets import *
from IPython.display import display, clear_output, HTML

def update_drop2(*args):
    if Drop1.value=='R':
        Drop2.options = {'un':'1','trois':'3','quatre':'4'}
    if Drop1.value=='B':
        Drop2.options = {'un':'1','trois':'3','quatre':'4'}
    if Drop1.value=='G':
        Drop2.options = {'deux':'2','quatre':'4','trois':'3'}

def action(*args):
    print('action')


Drop1 = widgets.Dropdown(
        options = {'red':'R','blue':'B','green':'G'},
        value = 'R',
        description='Drop1 :',
        disabled=False,
        continuous_update=False,
        style = {'description_width': 'initial'}
        )

Drop2 = widgets.Dropdown(
        options = {'un':'1','deux':'2','trois':'3'},
        value = '3',
        description='Drop2 :',
        disabled=False,
        continuous_update=False,
        style = {'description_width': 'initial'}
        )

display(Drop1,Drop2)

Drop1.observe(update_drop2,'value')
Drop2.observe(action,'value')

drop1 changes the options of drop2. any change of drop1 (and drop2 should launch an action (here just a print for the exemple)

  • when the list of options of drop2 is different and changed by drop1, drop2.value is automatically set up at the first value of the new list, even if the value chosen is already present in the previous list. Is there an option to keep this value if it's still available on the new list? (exemple : choose drop1 = R, drop2 = 'trois and then do drop1='G' : drop2 is automaticaly set up at'2'. Choose drop1 = R, drop2 = 3 and then do drop1='B' : drop2 remain at'3')

  • if i try to force drop2.value after the update of drop2.options, that make 2 changes of drop2 = 2 actions... i couldn't figure out a way to avoid it..so in addition, sometimes i have a repetition of the action and sometimes i have no actions...

Thanks for your help

1 Answers1

0

The code below should fix both of your problems:

import ipywidgets as widgets
from ipywidgets import *
from IPython.display import display, clear_output, HTML

out = widgets.Output()

def action(*args):
    with out:
        print('action')
        

def update_drop2(*args):
        temp = Drop2.value
        Drop2.unobserve(action, 'value')
        
        if Drop1.value=='R':
            Drop2.options = {'un':'1','trois':'3','quatre':'4'}
        if Drop1.value=='B':
            Drop2.options = {'un':'1','trois':'3','quatre':'4'}
        if Drop1.value=='G':
            Drop2.options = {'deux':'2','quatre':'4','trois':'3'}
        
        if str(temp) in Drop2.options.values():
            Drop2.value = temp
        
        Drop2.observe(action, 'value')
        action()

Drop1 = widgets.Dropdown(
        options = {'red':'R','blue':'B','green':'G'},
        value = 'R',
        description='Drop1 :',
        disabled=False,
        continuous_update=False,
        style = {'description_width': 'initial'}
        )

Drop2 = widgets.Dropdown(
        options = {'un':'1','deux':'2','trois':'3'},
        value = '3',
        description='Drop2 :',
        disabled=False,
        continuous_update=False,
        style = {'description_width': 'initial'}
        )

display(Drop1, Drop2, out)

Drop1.observe(update_drop2,'value')
Drop2.observe(action, 'value')
  1. I added the Output widget to actually display the output.

  2. To fix your first bullet point one might use a temporary variable temp to check if the value of Drop2 is contained in the dictionary of Drop2.options and change the value accordingly if needed. The change in Drop2.value happens, because the dictionary is ordered since python 3.7.

  3. To fix your second bullet point, i.e. to not have double calls when changing the Drop1.value, which might also change the Drop2.value and Drop2.options, one can unobserve Drop2 in the function update_drop2 and at the end observe it again.