bokeh
bokeh copied to clipboard
[BUG] vbar_stack is only updated once by CustomJS
Software versions
Python version : 3.9.10 | packaged by conda-forge | (main, Feb 1 2022, 21:24:11) IPython version : 8.4.0 Tornado version : 6.1 Bokeh version : 2.4.3 BokehJS static path : /opt/conda/envs/aiva-env/lib/python3.9/site-packages/bokeh/server/static node.js version : v17.4.0 npm version : 8.3.1 Operating system : Linux-4.19.0-20-amd64-x86_64-with-glibc2.31
Browser name and version
Google Chrome Version 104.0.5112.80
Jupyter notebook / Jupyter Lab version
Selected Jupyter core packages... IPython : 8.4.0 ipykernel : 6.9.1 ipywidgets : 7.7.1 jupyter_client : 7.1.2 jupyter_core : 4.9.2 jupyter_server : not installed jupyterlab : not installed nbclient : 0.5.12 nbconvert : 6.4.2 nbformat : 5.1.3 notebook : 6.4.8 qtconsole : not installed traitlets : 5.1.1
Expected behavior
I have a CustomJS block and a Slider and I expect, that the figure is updated every time the slider is moved.
Observed behavior
As you can see in the gif below, the slider is moved but the figure is only updated once.
To make sure the Source is updated, I printed the updated values to the console, which works fine.
Example code
from bokeh.plotting import figure, show, output_notebook
from bokeh.models import CustomJS,ColumnDataSource, Slider
from bokeh.layouts import column
from bokeh.palettes import GnBu3, OrRd3
output_notebook()
years = ['2015', '2016', '2017']
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
exports = {'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2015_org' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 4, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]
}
source = ColumnDataSource(exports)
p = figure(x_range=fruits, plot_height=250, y_range=(0, 16), title="Fruit import/export, by year")
p.vbar_stack(years, x='fruits', width=0.9, color=GnBu3, source=source)
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
slider = Slider(start=0, end=5, value=0, step=1, title="2015 exports")
callback = CustomJS(
args=dict(source=source, slider=slider),
code="""
console.log(slider.value)
let y = source.data['2015'];
let y_org = source.data['2015_org']
for (let i = 0; i < y.length; i++) {
y[i] = y_org[i] + slider.value
}
console.log(y)
source.change.emit();
""")
slider.js_on_change('value', callback)
show(column(p,slider))
Stack traceback or browser console output
None, which is odd.
Comment
Replacing the JavaScript code to
callback = CustomJS(
args=dict(source=source, slider=slider),
code="""
source.data = {
...source.data,
'2015': source.data['2015_org'].map((c) => c + slider.value),
};
""")
gives the wanted results. But the other version should workd and was working in other examples for me.