User interaction without bokeh widgets?

Hi!
I am pretty new to bokeh. It’s a great project and very happy with it. Recently, I have hit a roadblock that I am trying to solve. In my project, I use Flask and bokeh together.

On my page there are two Select boxes. The contents of these select boxes are dynamic coming from the server. They are NOT bokeh widgets.

There’s a nice bokeh chart under these select boxes. What I want to do is trigger a data update on the chart depending on the selected values in the selectboxes.I have not been able to trigger a data update in the bokeh chart at all.

Do I need to replace these non-bokeh boxes with bokeh widgets to make my chart interactive? If anyone did this with non-bokeh widgets, I would really appreciate an example.

Csaba

Can a bokeh expert reply with a simple yes or no, please? Am I wasting my time trying to get a custom widget working with bokeh charts?

It’s definitely possible, and people have definitely done it, but I can’t point you to anything offhand. I also can’t offer specific guidance without much more information about your actual situation. E.g. is this otherwise a Bokeh server app in a Flask page? Or is this standalone (non-server) Bokeh content in the page? How/where is the updated data supposed to come from? Etc. There are various possibilities:

  • The non-bokeh widgets could be wrapped and made into a Custom Extension that integrates just like a Bokeh built-in widget.
  • Or, your own event callbacks on the non-bokeh widgets could dig through the global Bokeh.index to find the right Bokeh models to update in response
  • Maybe an AjaxDataSource or ServerSentDataSource could be useful to streamline things, depending on where the data updates come from

More information is needed to suggest any particular course of action.

Thanks, Bryan.
I run a Flask website with bokeh. No bokeh server, though (yet). Whenever I, for example, change a Select box, it sends out an AJAX request to the API part of Flask and gets back json that should be the source of the bokeh chart. Do you think it would be easier to setup a bokeh server and deal with the widget interaction that way?

Here is how you can do it without using a Bokeh server. Make sure the data you want to update is in a ColumnDataSource you explicitly create, and make sure to set a name property on the CDS (can be whatever you want):

from bokeh.io import show
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure

x = [1, 2, 3, 4, 5]
y = [6, 7, 6, 4, 5]

source = ColumnDataSource(data=dict(x=x, y=y), name="MY_SOURCE")

p = figure(plot_width=300, plot_height=300)
p.line('x', 'y', source=source)
show(p)

That produces this:

Now in yout JavaScript event handlers, you can access the global Bokeh.index and use it to obtain the CDS you named, and update it:

The Bokeh.index is a “dict” that maps ids to Bokeh views, each of which has a model that corresponds the the Python side Bokeh object. In this case, the single Figure that was shown. The models also have a select_one method that lets you search for children objects by name (i.e. "MY_SOURCE" in this case). Once you have that data source, you can update it by re-assigning to source.data and the plot will update (you have to make a real assignment, if you update the data arrays “in place” then BokehJS won’t be able to pick up the change automatically).

If you have multiple plots/layouts on the same page you will have potentially need to look through all of the views in Bokeh.index to find what you are looking for. This is all a bit clunky which is why it has not been demonstrated widely.

Note: the JavaScript objects look fairly obfuscated because BokehJS is “minified” by default, to save space. For testing, you can set the environment variable BOKEH_MINIFIED=no and you will see much more human-readable output in the console.

Thank you, Bryan. I have been struggling with this for 2 days. Without your help, I wouldn’t have been able to solve this problem.
I agree, it’s a bit clunky, but it works.

Message moved here.

HI @Csaba_Kiss this Discourse will be most useful as a community resource if we keep the topics as focused as possible to one issue each. Would you mind moving this latest question to its own new topic?