Multiple inputs to one output

I’m attempting expand on the code for the following plotly visualization.

from dash import Dash, dcc, html, callback, Input, Output

my_fruits_list = [{'apple':'red'}, {'banana':'yellow'}, {'watermelon':'green'}]

# simpler if converted to a simple dictionary for lookups.
fruit_color_map = {}
for fruit_dict in my_fruits_list:
    for fruit_name, color in fruit_dict.items():
        fruit_color_map[fruit_name.lower()] = color
# Now fruit_color_map will be: {'apple': 'red', 'banana': 'yellow', 'watermelon': 'green'}

app = Dash()

app.layout = html.Div([
    html.H1("My Fruit Color Finder"),

    dcc.Input(
        id='fruit-input',
        type='text',
        placeholder='Enter a fruit (e.g., apple)',
        value=''
    ),

    html.Br(),
    html.Div(id='color-output-div')
])

@callback(
    Output('color-output-div', 'children'),
    Input('fruit-input', 'value')
)
def update_output_div(input_value):

    if not input_value:
        return ""

    fruit_name_to_check = input_value.lower().strip()
    color = fruit_color_map.get(fruit_name_to_check)

    if color:
        return color
    else:
        return ""

# 5. Run the app
if __name__ == '__main__':
    app.run(debug=True)

In the sample code, you simply type in a fruit and the app provides a color. What I’m trying to achieve is adding an additional input, in this case a drop down menu, to filter additional information. For the sake of the example, it could be nutritional information for the fruit, like calories, sugar, or potassium and those would be three of the drop down options. It would be part of the same visualization as the fruit color finder (so the original filter would work on both), but obviously only the new information would be affected by the drop down.

This is a dash question not a Plotly question, moved this post to the #dash section of the forum. This a limited working example to help you understand / get started in setting this up.

from dash import Dash, dcc, html, callback, Input, Output

# 1. Enhanced Data Structure
# No need for my_fruits_list anymore, we can define the comprehensive data directly.
# Let's make up some data for calories, sugar (g), and potassium (mg)
fruit_data = {
    'apple': {
        'color': 'red',
        'calories': 95,
        'sugar': 19,
        'potassium': 107
    },
    'banana': {
        'color': 'yellow',
        'calories': 105,
        'sugar': 14,
        'potassium': 422
    },
    'watermelon': {
        'color': 'green',
        'calories': 86,  # Per wedge (approx 286g)
        'sugar': 17,
        'potassium': 320
    },
    'orange': {
        'color': 'orange',
        'calories': 62,
        'sugar': 12,
        'potassium': 237
    },
    'grape': { # Assuming a cup of grapes
        'color': 'purple/green',
        'calories': 104,
        'sugar': 23,
        'potassium': 288
    }
}

# Options for the dropdown menu
nutrient_options = [
    {'label': 'Calories', 'value': 'calories'},
    {'label': 'Sugar (g)', 'value': 'sugar'},
    {'label': 'Potassium (mg)', 'value': 'potassium'}
]

app = Dash(__name__)

app.layout = html.Div([
    html.H1("My Fruit Color & Nutrient Finder"),

    html.Label("Enter a fruit (e.g., apple, banana):"),
    dcc.Input(
        id='fruit-input',
        type='text',
        placeholder='Enter a fruit',
        value='' # Start with an empty value
    ),
    html.Br(),
    html.Br(),

    # Original output for color
    html.Div(id='color-output-div'),
    html.Br(),
    html.Hr(), # Add a horizontal rule for separation

    # New section for nutrient selection and display
    html.H3("Nutritional Information"),
    html.Label("Select a nutrient:"),
    dcc.Dropdown(
        id='nutrient-dropdown',
        options=nutrient_options,
        value=None, # Start with no nutrient selected, or choose a default like 'calories'
        placeholder="Select a nutrient",
        clearable=False # If you want the user to always have one selected after first choice
    ),
    html.Br(),
    html.Div(id='nutrient-output-div')
])

# Updated callback with two inputs and two outputs
@callback(
    Output('color-output-div', 'children'),
    Output('nutrient-output-div', 'children'),
    Input('fruit-input', 'value'),
    Input('nutrient-dropdown', 'value') # New input
)
def update_outputs(input_fruit, selected_nutrient):
    # Initialize outputs
    color_output_message = ""
    nutrient_output_message = ""

    if not input_fruit:
        # If no fruit is entered, clear both outputs
        return "", ""

    fruit_name_to_check = input_fruit.lower().strip()
    fruit_info = fruit_data.get(fruit_name_to_check)

    if fruit_info:
        # Display color information
        color_output_message = f"The color of {fruit_name_to_check.capitalize()} is {fruit_info['color']}."

        # Display nutrient information if a nutrient is selected
        if selected_nutrient:
            if selected_nutrient in fruit_info:
                nutrient_value = fruit_info[selected_nutrient]
                # Get the label for prettier display (e.g., "Calories" instead of "calories")
                nutrient_label = next((opt['label'] for opt in nutrient_options if opt['value'] == selected_nutrient), selected_nutrient)
                nutrient_output_message = f"{fruit_name_to_check.capitalize()} - {nutrient_label}: {nutrient_value}"
            else:
                # This case shouldn't happen if data is well-formed, but good for robustness
                nutrient_output_message = f"No '{selected_nutrient}' data available for {fruit_name_to_check.capitalize()}."
        else:
            nutrient_output_message = "Please select a nutrient to see its value."

    else:
        color_output_message = f"Fruit '{input_fruit}' not found in our database."
        # No need to show nutrient info if fruit is not found
        nutrient_output_message = ""

    return color_output_message, nutrient_output_message

if __name__ == '__main__':
    app.run(debug=True, port=4563)
2 Likes

funny!

1 Like

Sorry for the mislabeling.

But thank you for the code. Exactly what I needed. :slight_smile:

2 Likes