Triggering change event for select from javascript, is it possible with bokeh?


I have this standalone html generated with 2 select widgets, and I want to trigger a change event for a listener added in python with js_on_change and a jscallback, is it possible to do?

What I have tried so far is using jquery, but the bokeh listener seems to ignore the events. The listener works fine when I click the select with a mouse…


I want to trigger the change of the second select from the first one…

I am not using a bokeh server, standalone html…

I am using


Not sure how the bokeh listener gets notified about the change… When I check onchange in the console it is null…

Thanks for your help.

Bokeh doesn’t use JS events, it uses its own event mechanism. For any interaction with Bokeh entities, you usually have to change the underlying Bokeh model. To do that, the usual workflow is to assign a unique ID to the model that you create in Python code (by just passing id='my_select' or something like that to that call to Select) and to get the model in the JS by calling Bokeh.documents[0].get_model_by_id('my_select'). When you have that model, you can just assign the value: my_select.value = 'item 1'.

Thanks a lot Eugene, this makes sense. I guess it is not yet possible to know when the documents array gets filled? I have like 20 documents in my html, probably have to debug.

20 documents in a single HTML? Either you’re doing something advanced or you’re mixing up some concepts.

There are documents, document roots, and plots.
A document is a collection of document roots. Document roots are the things that get embedded in your HTML. Plots are instances of a specific model, nothing special.
Usually you have one document, one or a few roots, and from 0 to tens plots (maybe more, but I don’t know how practical that is).

If you’re just calling save, show, or curdoc().add_root, then you have a single document on your page.

I am not doing anything advanced, I think. But I would like to mention it just in case there is an easy way to improve. I have one select widget and for each option of the widget I generate a corresponding secondary select widget with its options. All the secondary select widgets are hidden except the one corresponding to the selected option of the first select widget. When the first widget selected option changes a corresponding second select widget becomes visible. I put the widget code into an html file using results from the components method in bokeh. So this way I get the number of documents equal to the number of options in the first widget +1 for the first widget.

    date_selector = Select(title="Select experiment date:", options=station_id_to_dates[station_id])
    date_selector.js_on_change("change:value", select_date_action)  //select_date_action is the JScallback

    js, html = components(date_selector)

But you also call doc.add_root(date_selector). Why? Do you also call it for every widget with the same doc?
If so, and if I’m not mistaken, calling components for each single widget makes you embed the same document over and over, which can be a pretty huge overhead. The thing is, components returns a script that has the whole document encoded as JSON. That’s why it’s desirable to call components just once.

In your case, I would add all widgets in a Bokeh layout model (row, column, or grid), then call components once with that model, and finally toggle the currently visible widget by just toggling its visible property. Or, if you don’t need the values of the hidden widgets, just have two widgets and update available values in the second one based on the current value of the first one. There have been questions here on Discourse about it with answers with complete code (albeit, without using components, but it shouldn’t matter).

Thanks Eugene:

I did not want to rely on the html structure generated by bokeh, so I just put the widgets in separate divs (using a template) identified by me and was moving those around the DOM. As show/hide sometimes leaves the whitespace, or the size of the initially hidden widgets is 0…

It is working more or less ok, but the initial load time is slow. I can only do so much without using an app server… I will try to think if It could be optimized.