Search code examples
pythonbokehbokehjs

How to capture the result returned by a callback function call on a Bokeh TextInput widget?


I'm working on a Bokeh application which, among other widgets, has a TextInput and a MultiSelect. (Since Bokeh does not have a native Search widget, I try to build one that has a box for input and a box to display the results returned by a dB query based on the input field.)

The code for TextInput box is ask_fruit and MultiSelect is used to display the results returned by dB query. The callback function used by TextInput is db_query.

def SearchDisplay():
    ask_fruit = TextInput(value="Enter fruit name here",
                        title="Input box:"
                        )

    ask_fruit.on_change("value", db_query)

    available_fruits = MultiSelect(title=None,
                           value=["All"],
                           options=[]
                           )

    return [ask_fruit, available_fruits]



def db_query(attr, old, new):

    #conn = pyodbc.connect('fruit-db', autocommit=True)
    #curs = conn.cursor()
    #query = "select fruit_id from fruitdB"
    #curs.execute(query)
    #fruit_list = curs.fetchall()

    fruit_list = ["Fuji", "Gala", "McIntosh"] 

    return fruit_list

The question is how to populate the MultiSelect widget with results returned by the callback?

Is it possible to just do options=[ask_fruit.on_change("value", db_query)] in code for MultiSelect?

The action would look like this:

enter image description here


Solution

  • You need to set a new value for the .options property of the multi-select widger, and it will automatically be synced to the front end:

    from bokeh.io import curdoc
    from bokeh.layouts import widgetbox
    from bokeh.models.widgets import MultiSelect, TextInput
    
    # ------------------ WIDGETS -------------------- #
    
    ask_fruit = TextInput(
        value='Enter fruit name here',
        title='Input box:',
    )
    
    available_fruits = MultiSelect(
        title=None,
        value=[],
        options=[]
    )
    
    # ------------------ EVENTS ---------------------- #
    
    def db_query(attr, old, new):
    
        # [...]
    
        available_fruits.update(
            options=[
                ("foo", "Foo"), ("bar", "BAR"),
                ("baz", "bAz"), ("quux", "quux")
            ]
        )
    
    ask_fruit.on_change('value', db_query)
    
    def on_change_value_available_fruits(attr, old, new):
        print('-- VALUE CHANGED TO: {}'.format(new))
    
    available_fruits.on_change('value', on_change_value_available_fruits)
    
    curdoc().add_root(widgetbox(ask_fruit, available_fruits))