☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

CDS.js_on_change not called, but CDS.on_change is

Community Support
nicko
nicko

Hi,
I have a CDS which fires a python callback, but not the JS callback. I am under the impression that both should fire at the same event. In the example below when I modify a cell in the DataTable, the python callback is called, but the JS callback is not.

from bokeh.models import DataTable, ColumnDataSource, CustomJS, TableColumn
from bokeh.plotting import curdoc

source = ColumnDataSource(data = { 'x':[0,1,2,3], 'y':['a','b','c','d']})
columns = [TableColumn(field='x'), TableColumn(field='y')]
data_table = DataTable(source=source,columns= columns, editable=True)

callback_hello_js = CustomJS(code='''
    // just logs to the console
    console.log('hello from js');
    ''')

def callback_hello_py(attr, old, new):
    print('hello from python')

source.on_change('data',callback_hello_py)
source.js_on_change('data',callback_hello_js)

curdoc().add_root(data_table)
⌁   Link to post
Bryan
Bryan

Seems like something to discuss and figure out, please file a GitHub issue with all this information.

Normally, events are only fired when the entire value of a property changes, not when a subitem (e.g. when all of .data is re-assigned, not when a single buried inside .data changes changes). So offhand I’m not sure the python property should be triggering a callback here, when a single element in the table column is changed. The best solution might be to make things consistent with the rest of bokeh and making the python property not fire (consistency is good), but adding some other event that can be watched for “subitem” changes since in this specific case of the table (it’s a common need).

⌁   Link to post
Bryan
Bryan

Thanks, I definitely agree there should be some way, I was only stating that, for the sake of API consistency, perhaps it should not be on_change('data', ...) or js_on_change('data', ...)

⌁   Link to post
sirspoon
sirspoon

Hi, apologies for replying to an old thread, but my issue is similar but I don’t think quite the same. I thought that if I completely replace my source.data then it’s not an in-place update, and my js callback should trigger, however it still refuses to trigger. The python callback works fine. Is this the expected behaviour or have I done something silly. Thanks.

edit: latest version of python (2.3), running the code in a bokeh server

cds_counter=ColumnDataSource(data={"counter":[0]})
### dummy button to see if can trigger js callback
button_dummy=Button(label="Test Button_dummy", button_type="success", width=60)
global dummy_int
dummy_int=0
def button_dummy_callback(event):  # button pressed callback, replaces cds "counter" in .data
    print("button has been pressed")
    global dummy_int
    dummy_int +=1
    temp=dummy_int
    cds_counter.data={"counter": [temp]}
    print(cds_counter.data["counter"])
js_counter_callback = CustomJS(args=dict(cds_counter=cds_counter), code=""" #DOES NOT FIRE
            console.log("test test test")
            """)
def py_counter_callback(attr, old, new):             # RUNS WHEN BUTTON PRESSED
    print("callback based on change has run.")
cds_counter.on_change("data", py_counter_callback)   # WORKING
cds_counter.js_on_change("data", js_counter_callback) #NOT WORKING

button_dummy.on_click(button_dummy_callback)
⌁   Link to post

End of archived discussion · Replies are disabled