Search code examples
bokeh

Bokeh: textInput on_change function on widget doesn't work as expected


my short script looks like the following:

output_server('ts_sample.html')

count = 0
def update_title(attrname, old, new):
    global count
    count = count + 1

textInput = TextInput(title="query_parameters", name='fcp_chp_id', value='fcp_chp_id')
textInput.on_change('value', update_title)

curdoc().add_root(textInput)
p = figure( width=800, height=650,title="ts_sample",x_axis_label='datetime' )
p.line(np.array(data['date_trunc'].values, dtype=np.datetime64), data['latitude'], legend="test")
p.xaxis[0].formatter=bkmodels.formatters.DatetimeTickFormatter(formats=dict(hours=["%F %T"]))
show(curdoc())

It works, when bokeh server(bokeh serve) is running and I got the plotting, but on_change callback doesn't work as expected.

Assumed the value of textInput should be the content/string in the input box, but I changed it multiple times but the callback function update_title is never called (the count global variable is always 0). So apparently the underlying textInput.value is not changed, how can I change value attr and trigger the on_change function ?


Solution

  • Here's a simple TextInput example using a callback rather than .on_change(). This might be more helpful for beginners like me than the OP. I very slightly modified the slider example from

    http://docs.bokeh.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-model-property-events

    from bokeh.layouts import column
    from bokeh.models import CustomJS, ColumnDataSource, Slider
    from bokeh.models import TextInput
    from bokeh.plotting import figure, show
    
    x = [x*0.005 for x in range(0, 200)]
    y = x
    
    source = ColumnDataSource(data=dict(x=x, y=y))
    
    plot = figure(plot_width=400, plot_height=400)
    plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
    
    callback = CustomJS(args=dict(source=source), code="""
            var data = source.get('data');
            var f = cb_obj.get('value')
            x = data['x']
            y = data['y']
            for (i = 0; i < x.length; i++) {
                y[i] = Math.pow(x[i], f)
            }
            source.trigger('change');
        """)
    
    #slider = Slider(start=0.1, end=4, value=1, step=.1, title="power", callback=callback)
    #layout = vform(slider, plot)
    
    text_input = TextInput(value="1", title="power", callback=callback)
    layout = column(text_input, plot)
    
    show(layout)