ColumnDataSource.on_change() callback is not triggering

Hello Bokeh Community,

I am using a select widget to update data stored in a ColumnDataSource. I am trying to have a callback function run every time the ColumnDataSource’s data is changed, but it is currently not working.

Here is a simplified version of my code:

from bokeh.models import ColumnDataSource, Select
from bokeh.io import output_file, show
from bokeh.plotting import curdoc
from functools import partial

def update_cds_from_select(level, attr, old, new):
    data = map_state.data
    data['values'][level] =  new
    map_state.data = dict(data)
    
def cds_update_callback(attr, old, new):
    print('ColumnDataSource source was updated')

null_value = '---'

select_region_options = [null_value,'Northern', 'Eastern', 'Southern', 'Western']
select1 = Select(title='Region',options=select_region_options, value=null_value) 
select1.on_change('value', partial(update_cds_from_select, 0))

map_state_data = {'levels': ['NAME_1', 'NAME_2', 'NAME_3', 'NAME_4'],
              'values': [null_value, null_value, null_value, null_value]
              }
map_state = ColumnDataSource(map_state_data)
map_state.on_change('data', cds_update_callback)

curdoc().add_root(select1)

I’m hoping that someone more experienced can point out where I am going wrong. Thank you in advance!

By the time your code gets to the map_state.data = dict(data) line, the values are already the same since you have changed the data within the map_state.data object. Wrapping it in dict() doesn’t help because Bokeh checks for equality by value, not by reference.

In this particular case you can just replace the whole body of update_cds_from_select with:

map_state.patch(dict(values=[(level, new)]))

thank you so much! that fixed my issue.

1 Like