Hey all,
I’m using bokeh 0.13.0 and tried to change a bokeh side from save
to embedding to have greater control over the layout. After doing this my CustomJS could no longer update my div, although a console.log(...)
was still working. After some time I minimized my problem to the code below. The problem only occures when I assign something to source.callback
(reproduced in cb_embed.html
), if I do not the div doesn’t work correctly (shown in without_cb_embed.html
). This can be fixed by wrapping the div in a widgetbox (as done automatically by the layout call, I first thought save
was somehow responsible, but wrapping the div in a widgetbox and embedding also works).
While I think having a “raw” div without a widgetbox is not really supported it feels very buggy that this only happens if a callback is assigned to source.callback
. I’m not sure if this is a bug or if this is “working as expected” - if it is the later maybe an error should be thrown when trying to embed an raw widget without a widgetbox.
from bokeh.io import save, output_file, show
from bokeh.plotting import figure
from bokeh.events import ButtonClick
from bokeh.models import CustomJS, Div, Button, ColumnDataSource
from bokeh.layouts import layout, widgetbox
from bokeh.embed import components
import jinja2
def make_plots(include_cb, embed):
source_dict = {"x": [1,2], "y": [3,4]}
source = ColumnDataSource(source_dict)
p = figure()
p.circle(x="x", y="y", source=source)
div = Div(text="Div Initialized")
cb = CustomJS(args=dict(div=div), code='console.log("Callback 1"); div.text="cb";')
cb1 = CustomJS(args=dict(div=div), code='console.log("Callback 1"); div.text="cb";')
button = Button(label="Foo", button_type="success")
button.js_on_event(ButtonClick, cb)
template = jinja2.Template("""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title></title>
<link href="https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css" rel="stylesheet" type="text/css">
<link href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css" rel="stylesheet" type="text/css">
<link href="https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css" rel="stylesheet" type="text/css">
<script src="https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.js"></script>
<script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.js"></script>
<script src="https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.js"></script>
</head>
<body>
<div>
{{ map }}
</div>
<div>
{{button}}
{{ div }}
</div>
{{ script }}
</body>
</html>
""")
name = "cb_" if include_cb else "without_cb_"
name = name + ("embed.html" if embed else "save.html")
if include_cb:
source.callback = cb
if embed:
script, (map, div_, button_) = components([p, div, button])
with open(name, mode="w") as f:
f.write(template.render(script=script,
map=map,
div=div_, button=button_))
else:
output_file(name)
save(layout([p, widgetbox(div), widgetbox(button)]))
make_plots(False, False)
make_plots(True, True)
make_plots(True, False)
make_plots(False, True)
``
Best wishes,
Simon