2

I created a form with two drop down menu's:

My goal is to make one dropdown dependent on the other dropdown.

This picture illustrates my goal and the current situation.

The sample code below can be run in Google Colab or Jupyter notebook to replicate the current situation.

#@title 
import ipywidgets as widgets
from ipywidgets import HBox, Label
from ipywidgets import Layout, Button, Box, FloatText, Textarea, Dropdown, Label, IntSlider
import time
import pandas as pd

#Create DF
df = df = pd.DataFrame(columns = ['Dropdown_column', 'Float_column'])
df

# Layout
form_item_layout = Layout(
    display='flex',
    flex_flow='row',
    justify_content='space-between',
)


button_item_layout = Layout(
    display='flex',
    flex_flow='row',
    justify_content='center',
    padding = '5%'
)


# Independent dropdown item

drop_down_input = 'Dropdown_input_1'

drop_down = widgets.Dropdown(options=('Dropdown_input_1', 'Dropdown_input_2'))

def dropdown_handler(change):
    global drop_down_input
    print('\r','Dropdown: ' + str(change.new),end='')
    drop_down_input = change.new

drop_down.observe(dropdown_handler, names='value')


# Dependent drop down

# Dependent drop down elements

dependent_drop_down_elements = {}
dependent_drop_down_elements['Dropdown_input_1'] = ['A', 'B']
dependent_drop_down_elements['Dropdown_input_2'] = ['C', 'D', 'E'] 

# Define dependent drop down

dependent_drop_down = widgets.Dropdown(options=(dependent_drop_down_elements['Dropdown_input_1']))

def dropdown_handler(change):
    global drop_down_input
    print('\r','Dropdown: ' + str(change.new),end='')
    drop_down_input = change.new  
drop_down.observe(dropdown_handler, names='value')



# Button

button = widgets.Button(description='Add row to dataframe')
out = widgets.Output()
def on_button_clicked(b):
    global df
    button.description = 'Row added'
    time.sleep(1)
    with out:
      new_row = {'Dropdown_column': drop_down_input, 'Float_column': float_input}
      df = df.append(new_row, ignore_index=True)
      button.description = 'Add row to dataframe'
      out.clear_output()  
      display(df)
button.on_click(on_button_clicked)

# Form items

form_items = [         
    Box([Label(value='Independent dropdown'),
         drop_down], layout=form_item_layout),
    Box([Label(value='Dependent dropdown'),
         dependent_drop_down], layout=form_item_layout)
         ]

form = Box(form_items, layout=Layout(
    display='flex',
    flex_flow='column',
    border='solid 1px',
    align_items='stretch',
    width='30%',
    padding = '1%'
))
display(form)
display(out)

Is this possible? If so, can you explain how?

1 Answer 1

3

You can do this by setting a if statement in your dropdown_handler function that checks if the value chosen in your independent dropdown is Dropdown_input_1 or Dropdown_input2. Still in the dropdown_handler, you can then modify accordingly the options arguments to either dependent_drop_down_elements['Dropdown_input_1'] or dependent_drop_down_elements['Dropdown_input_2'].

See code below:

import ipywidgets as widgets
from ipywidgets import HBox, Label
from ipywidgets import Layout, Button, Box, FloatText, Textarea, Dropdown, Label, IntSlider
import time
import pandas as pd

#Create DF
df = df = pd.DataFrame(columns = ['Dropdown_column', 'Float_column'])
df

# Layout
form_item_layout = Layout(
    display='flex',
    flex_flow='row',
    justify_content='space-between',
)


button_item_layout = Layout(
    display='flex',
    flex_flow='row',
    justify_content='center',
    padding = '5%'
)


# Independent dropdown item

drop_down_input = 'Dropdown_input_1'
drop_down = widgets.Dropdown(options=('Dropdown_input_1', 'Dropdown_input_2'))


# Dependent drop down
# Dependent drop down elements
dependent_drop_down_elements = {}
dependent_drop_down_elements['Dropdown_input_1'] = ['A', 'B']
dependent_drop_down_elements['Dropdown_input_2'] = ['C', 'D', 'E'] 

# Define dependent drop down

dependent_drop_down = widgets.Dropdown(options=(dependent_drop_down_elements['Dropdown_input_1']))

def dropdown_handler(change):
    global drop_down_input
    print('\r','Dropdown: ' + str(change.new),end='')
    drop_down_input = change.new
    #If statement checking on dropdown value and changing options of the dependent dropdown accordingly
    if change.new=='Dropdown_input_2':
       dependent_drop_down.options=dependent_drop_down_elements['Dropdown_input_2']
    elif change.new=='Dropdown_input_1':
        dependent_drop_down.options=dependent_drop_down_elements['Dropdown_input_1']
drop_down.observe(dropdown_handler, names='value')

# Button

button = widgets.Button(description='Add row to dataframe')
out = widgets.Output()
def on_button_clicked(b):
    global df
    button.description = 'Row added'
    time.sleep(1)
    with out:
      new_row = {'Dropdown_column': drop_down_input, 'Float_column': float_input}
      df = df.append(new_row, ignore_index=True)
      button.description = 'Add row to dataframe'
      out.clear_output()  
      display(df)
button.on_click(on_button_clicked)

# Form items

form_items = [         
    Box([Label(value='Independent dropdown'),
         drop_down], layout=form_item_layout),
    Box([Label(value='Dependent dropdown'),
         dependent_drop_down], layout=form_item_layout)
         ]

form = Box(form_items, layout=Layout(
    display='flex',
    flex_flow='column',
    border='solid 1px',
    align_items='stretch',
    width='30%',
    padding = '1%'
))
display(form)
display(out)

As an example, this is what the output looks like when you pick Dropdown_input_2 on the first widget:

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! The if statement helped me on the right way! I slightly adapted the code to make it more scalable: if change['type'] == 'change': dependent_drop_down.options=dependent_drop_down_elements[change.new] Now, it keeps taking the right value from the dictionary list also if I increase the dictionary list.
Happy to hear! Consider marking your question as answered by clicking on the green tick next to my answer if you are satisfied with my answer. Thx!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.