✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

Callback not picking up value from dcc.Input

I saw this: Updating a dropdown menu's contents dynamically

But wanted an input box that would update a dropdown that follows.

So I wrote:

# -*- coding: utf-8 -*-
"""
@author; 
"""
from dash import Dash
from dash.dependencies import Input, Output
from Dashboard.utils.Dash_fun import apply_layout_with_auth
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import dash_html_components as html
from mongoengine import connect
#from app import db
from app.models import (
    CNFFoodName, CNFConversionFactor, CNFNutrientAmount,
        CNFYieldAmount, CNFRefuseAmount
)
connect('cnf')

url_base = '/dash/shiny/'

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

colors={
        'background': 'white',
        'text': 'black'
}
#todo: import data to be used here?
#CNFFoodNames = db.CNFFoodName
food_name_query_set = CNFFoodName.objects(description__exists=True)
food_names_arr = []
#arr of food names
for food in food_name_query_set:
    food_names_arr.append(food['description'])

#dict of food_description: units
foodnameDict = {}
'''
layout = html.Div([
    html.H1("hello world")
])
'''
layout=html.Div([
    html.Label(
        "1. Choose Ingredient"
    ),

    html.Div([
        dcc.Input(
            id="search_ingredient", type="text",
            autoComplete=True, autoFocus=True,
            list="food_names", placeholder=food_names_arr[3333]
        ),
    ]),

    html.Datalist(
        id="food_names", children=[
            html.Option(value=food) for food in food_names_arr
        ]
    ),
    html.Br(),

    html.Label(
        "2. Amount Units"
    ),

    html.Div([
        dcc.Dropdown(
            id="units-dropdown",
            ),
    ]),
    html.Br(),
    html.Label(
        "3. Quantity"
    ),
    dcc.Input(
        id="numerical-amount", type="number",
        autoComplete=False, debounce=True
    ),
    html.Br(),
    html.Button(
        "Add Ingredient", id='submit-ingredient',
    ),
    html.Button(
        "Remove Ingredient", id="cancel-ingredient",
    ),
    html.P(
        "Number of servings contained"
    ),
    html.Div(
        id="test_out"
    )
])

def Add_Dash(server):
    app = Dash(server=server, url_base_pathname=url_base,
               external_stylesheets=external_stylesheets)
    # external_stylesheets=[dbc.themes.BOOTSTRAP])
    apply_layout_with_auth(app, layout)

    @app.callback(
        [Output('units-dropdown', 'options'),
         Output('test-out', 'children')],
        [Input('search-ingredient', 'value')]
    )
    def update_dropdown(ingredient):
        #get food_id
        food_id = -1
        for food in food_name_query_set:
            if food['description'] == ingredient:
                food_id=food['id']

        # get units
        conversions=CNFConversionFactor.objects.filter(food=food_id)
        measure_names = []
        for c in conversions:
            measure_names.apppend(c.measure.name)
        print(f'measure_names')
        # return a list of dicts?
        foodnameDict={ingredient:measure_names}

        return [{'label':unit, 'value':unit} for unit in foodnameDict[ingredient]], \
            f'you chose {ingredient}'

    return app.server

But it’s not outputting anything to the div at the bottom with id="test-out" nor is it updating the dropdown.
Why is this so?

I tried a toy example and have the same problem

layout = html.Div([
    html.Div([
            dcc.Input(id='test-input', placeholder='', type='text')
        ]),
    html.Div(
        id="test_out"
    )
])

def Add_Dash(server):
    app = Dash(server=server, url_base_pathname=url_base,
               external_stylesheets=external_stylesheets)
    application = app.server
    # external_stylesheets=[dbc.themes.BOOTSTRAP])
    apply_layout_with_auth(app, layout)

    @app.callback(
        [Output('test-out', 'children')],
        [Input('test-input', 'value')]
    )
    def test_input(word):
        return f'you wrote {word}'

Ok, I can copied someone’s code and can get a small toy example working but went back to my own and it’s not working again. So it must be one of the attributes I’m giving dcc.Input.
toy example that worked:

layout = html.Div([

    dcc.Input(id='input_text'),
    html.Br(),
    html.Div(
        id="target",
    )
])

@app.callback(
        Output('target', 'children'),
        [Input('input_text', 'value')]
    )
    def test_input(word):
        return f'you wrote {word}'

Your layout has test_out whereas the callback uses test-out - perhaps it’s as simple as that? If you can run the app with debug=True then problems like that should show errors pointing in the right direction.

I have debug mode on and just edited test_out to test-out in the layout but the input box just does not elicit any action at all.
They are Dash apps embedded in a Flask app and my other Dash app (I have four of them embedded) debugs fine and the input box works.
But that one has no attributes like the toy example.

Which sucks because I want to use debounce, placeholder, etc.

and of course list connected to datalist to show some of the possible choices as users type.

I fixed my spelling error in append but the top input connected to data list is still not working although the data list options appear in the input box and I can select them.

I added a toy input box near the bottom of the page that does work, it outputs the input text and I can debug.

# -*- coding: utf-8 -*-
"""
@author; Nobu Kim
"""
from dash import Dash
from dash.dependencies import Input, Output
from Dashboard.utils.Dash_fun import apply_layout_with_auth
import dash_core_components as dcc
import dash_bootstrap_components as dbc
import dash_html_components as html
from mongoengine import connect
#from app import db
from app.models import (
    CNFFoodName, CNFConversionFactor, CNFNutrientAmount,
        CNFYieldAmount, CNFRefuseAmount
)
connect('cnf')

url_base = '/dash/shiny/'

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

colors={
        'background': 'white',
        'text': 'black'
}
#todo: import data to be used here?
#CNFFoodNames = db.CNFFoodName
food_name_query_set = CNFFoodName.objects(description__exists=True)
food_names_arr = []
#arr of food names
for food in food_name_query_set:
    food_names_arr.append(food['description'])

#dict of food_description: units
foodnameDict = {}

layout=html.Div([
    html.Label(
        "1. Choose Ingredient"
    ),
    html.Div([
        dcc.Input(
            id="search_ingredient",
            list="food_names", placeholder=food_names_arr[3333],
            #debounce=True, #value=food_names_arr[0]
        ),
    ]),

    html.Datalist(
        id="food_names", children=[
            html.Option(value=food) for food in food_names_arr
        ]
    ),
    html.Br(),

    html.Label(
        "2. Amount Units"
    ),

    html.Div([
        dcc.Dropdown(
            id="units-dropdown",
            ),
    ]),
    html.Br(),
    html.Label(
        "3. Quantity"
    ),
    dcc.Input(
        id="numerical-amount", type="number",
        autoComplete=False, debounce=True
    ),
    html.Br(),
    html.Button(
        "Add Ingredient", id='submit-ingredient',
    ),
    html.Button(
        "Remove Ingredient", id="cancel-ingredient",
    ),
    html.P(
        "Number of servings contained"
    ),
    html.Div([
        dcc.Input(id='test-input'
        ),
    ]),
    html.Div(
        id="test-out"
    ),
    html.Div(
        id="target"
    )

])
"""
layout = html.Div([

    dcc.Input(id='input_text'),
    html.Br(),
    html.Div(
        id="target",
    )
])
"""


def Add_Dash(server):
    app = Dash(server=server, url_base_pathname=url_base,
               external_stylesheets=external_stylesheets)
    #application = app.server
    # external_stylesheets=[dbc.themes.BOOTSTRAP])
    apply_layout_with_auth(app, layout)

    @app.callback(
        Output('target', 'children'),
        [Input('test-input', 'value')]
    )
    def test_input(word):
        return f'you wrote {word}'

    @app.callback(
        Output('units-dropdown', 'options'),
        Output('test-out', 'children'),
        Input('search-ingredient', 'value')
    )
    def update_dropdown(value):
        #get food_id
        food_id = -1
        for food in food_name_query_set:
            if food['description'] == value:
                food_id=food['id']

        # get units
        conversions=CNFConversionFactor.objects.filter(food=food_id)
        measure_names = []
        for c in conversions:
            measure_names.append(c.measure.name)
        print(f'measure_names')
        # return a list of dicts?
        foodnameDict={value:measure_names}

        return [{'label':unit, 'value':unit} for unit in foodnameDict[value]], \
            f'you chose {value}'

    return app.server


"""
    html.Div([
        dcc.Input(
            id="search_ingredient", type="text",
            autoFocus=True,
            list="food_names", #placeholder=food_names_arr[3333],
            debounce=True, value=food_names_arr[0]
        ),
    ]),

    html.Datalist(
        id="food_names", children=[
            html.Option(value=food) for food in food_names_arr
        ]
    ),
"""

oh my god! I did it again and now it’s working.

not search_ingredients but search-ingredients

1 Like