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)
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).
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', ...)
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)
@sirspoon Python callbacks with on_change only function in Bokeh server applications. Are you actually running this as a Bokeh server application (i.e. with bokeh serve app.py and not just python app.py)?
@sirspoon yes please provide a Minimal Reproducible Example but also please make a brand new topic (I only just noticed this resurrected a very old question)