I posted this to SO, but getting no responses, decided maybe here was a better venue:
Basically I have a page I want to switch between data sets in the browser without communicating with the server (my users will be switching back and forth a lot). I have a bokeh chart that starts out with 7 line series in a chart. A select widget changes the data and shows only 4 series via a customjs callback
for i in range(7): if i < 4: js_code += """data['y%d']=data.%s;""" % (i,newseriesnames[i]) js_code += """line%d.visible = %s;""" % (i,'true' if i < 4 else 'false') js_code += 'source.change.emit();' callback = CustomJS(args = args,code=js_code) select.js_on_change('value',callback)
where line0 through line6 are the lines in the plot linked to data objects data[‘y0’] through data[‘y6’] and select is a bokeh selector widget. This works great in the bokeh chart itself, but it doesn’t update the legend. The legend is always the same as when it is first rendered. It retains the 7 elements, even when they are hidden in the chart.
Some things that don’t seem to work:
- Setting legend.items.renderers.visible=false
- Setting legend.items.visible=false
- Calling legend.change.emit(), legend.items.change.emit(), and legend.items.renderers.change.emit()
- Overwriting the legend with a different one made using bokeh’s python Legend() method
A workaround is, in python create a new legend for every possible set of line charts
for group_name in group_names: legend_items[group_name] = make_legend(group_name) plot.add_layout(legend_items[group_name], 'right') for g in legend_items: legend_items[g].visible = False legend_items[group_names].visible = True
and then in the callback turn off all but the one you want to show
for f in group_names: js_code += """legend_items['%s'].visible = false;""" % f js_code += 'legend_items[f].visible = true;'
This works but seems inelegant. How would someone tackle this?