Search code examples
javascriptplotcallbackbokeh

How to access and update Bokeh plots or widgets using an external JavaScript code?


I have a Bokeh plot which is controlled by a time Bokeh slider. I am trying to set the time of the slider and the corresponding plotted data to the current time of the browser by clicking on a button.

I know how to do the same thing if everything has been entirely developed in JS. But I am writing an external JS function embedded in the HTML file and I don't know how to access the Bokeh objects (in this case the Slider) and manipulate them. I can only use the callback functions to start from a slider and change the underlying data, but not the other way around. I need to set the value of the slider using a button to the current time!

callback = CustomJS( JS Code to cahnge the data; )

Timeslider = DateSlider(start=dt(2019, 9, 1, 16, 0, 0), end=dt(2019, 9, 2, 8, 0, 0), value=dt(2019, 9, 1, 16, 0, 0), step=1) 

callback.args['time_slider'] = Timeslider
Timeslider.js_on_change('value', callback)


Solution

  • You can embed another JS library in the block postamble part of the Bokeh template like described here. Then if you give your slider a name you can access it like this:

    Python:

    slider = Slider(start=0, end=10, value=5, name='my_slider')
    

    JS:

    var slider = Bokeh.documents[0].get_model_by_name('my_slider')
    console.log('slider value before:', slider.value)
    slider.value = 10
    console.log('slider value after:', slider.value)
    

    This is assuming that you have just one Bokeh document in your app (note that 0 index in documents[0]). Then you can access and manipulate the Slider object the same way like you would do in a CustomJS callback, but note that cb_obj and cb_data are not available in this case.

    See complete working example below (Bokeh v1.3.0):

    external_js.py:

    from bokeh.io import save
    from bokeh.models import Slider, Column
    from bokeh.util.browser import view
    
    template = """
    {% block postamble %}
        <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
        <script>
            $(document).ready(function() {
                var slider = Bokeh.documents[0].get_model_by_name('my_slider')
                console.log('slider value before:', slider.value)
                slider.value = 10
                console.log('slider value after:', slider.value)
            });
        </script>
    {% endblock %}
    """
    
    slider = Slider(start=0, end=10, value=5, name='my_slider')
    
    save(Column(slider), template=template)
    view("external_js.html")