I have been trying to find some documentation or clarity on how "source.trigger(‘changed’) works in the below example in the Bokeh documentation:
I can see that ‘source’ is derived from ColumnDataSource with the dict argument. That is then added as a value to the dictionary being passed into CustomJS. I assumed the ‘source’ that resulted in the javascript code matches that coming in but the Bokeh API for ColumnDataSource.source accepts three positional arguments and not one. What is happening here?
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource, Slider
from bokeh.plotting import Figure, output_file, show
output_file("js_on_change.html")
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.data;
var f = cb_obj.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")
slider.js_on_change('value', callback)
layout = column(slider, plot)
show(layout)
BokehJS can normally automatically detect when Bokeh properties are changed, e.g. if you set plot.title.text = "New Title" then BokehJS will detect this and update the title of the plot without any additional code. However, it's not possible to automatically detect changes "inside" things like arrays. So if you are changing a JS array in-place (as the example below does) then you have to give BokehJS a little help, and call "source.trigger('changed')" yourself. Then any events that need to happen when a data source changes (such as re-rendering the plot) will happen.
I should add that as fas as I can think of offhand, this is one of the only times you would need to call source.trigger yourself.
Please also note that this syntax is changing in 0.12.6, see the section "New Signaling API" in the migration notes:
I have been trying to find some documentation or clarity on how "source.trigger('changed') works in the below example in the Bokeh documentation:
I can see that 'source' is derived from ColumnDataSource with the dict argument. That is then added as a value to the dictionary being passed into CustomJS. I assumed the 'source' that resulted in the javascript code matches that coming in but the Bokeh API for ColumnDataSource.source accepts three positional arguments and not one. What is happening here?
from bokeh.layouts import column
from bokeh.models import CustomJS, ColumnDataSource, Slider
from bokeh.plotting import Figure, output_file, show
callback = CustomJS(args=dict(source=source), code="""
var data = source.data;
var f = cb_obj.value
x = data['x']
y = data['y']
for (i = 0; i < x.length; i++) {
y[i] = Math.pow(x[i], f)
}
source.trigger('change');
""")