Js_on_change can't detect changes “inside the array” even if i call source.change.emit()!

I am trying to call a simple CustomJS callback when my line source changes

from bokeh.plotting import figure, show
from bokeh.models import CustomJS, Label

p = figure(width=400, height=400)

line = p.line(x = [1,2,3,4],y = [1,2,3,4],line_width=2,name="Line")

label = Label(x=3, y=8, text="Initial Text")
p.add_layout(label)

callback = CustomJS(
    code="""
        console.log("Callback executed");
    """,
)

line.data_source.js_on_change("data", callback)

show(p)

In the browser console, I tested two scenarios. In the first scenario, I updated the whole source, and the callback worked perfectly

var source = Bokeh.documents[0].get_model_by_name("Line").data_source;
source.data = { x: [1, 2, 3, 4, 7], y: [1, 2, 3, 4, 5] };
source.change.emit();

However, in the second scenario, I only updated source.data.y, and the callback was not called even if i use source.change.emit().

var source = Bokeh.documents[0].get_model_by_name("Line").data_source;
source.data.y = [1, 2, 3, 4, 10];
source.change.emit();

Any help on what I’m doing wrong gratefully received. Thanks.

source.change.emit() does not generate a property-change event for the data property, which is specifically what the callback is listening for. If you really want to do this, then:

source.properties.data.change.emit("data");

But this approach is really getting into the weeds of BokehJS internals. Really, the recommended practice is to actually just update the property for real:

source.data = new_data

Constructing a new data object with existing columns is a lightweight operation, it’s not going to do a deep-copy, for example.

Oh, I get it. Thank you so much!

Specifically with modern JavaScript syntax one can do this:

souce.data = {...source.data, y: [1, 2, 3, 4, 10]}
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.