0

Can you interface the bokeh server with a Javascript library such as JQuery on the client side?

I want to implement an advanced form, and already have a Bokeh server app running.

However, as more and more work were being done I faced many issues with the Bokeh API, such as missing features (callbacks, options, ...), unresolved bugs, instabilities, and so on.

I came to the conclusion that it would be better that some part of the application are in Bokeh (graphs) while others, such as forms, are implemented with a more dedicated API, for example in pure Javascript.

Is this doable or even recommended? If so, how to do it?

I saw that there exists an Ajax data source in bokeh, however I'm not sure it's made for communication between the Bokeh server and a client JS page.

Any advice, explanations or examples appreciated,

Thanks

Carmellose
  • 4,815
  • 10
  • 38
  • 56

1 Answers1

0

You definitely can do this - I was able to make Bokeh work with input widgets created in ClojureScript + re-frame.

There're two ways to approach this:

  1. Create a ColumnDataSource for relevant forms/inputs. In the JS code for the forms/inputs, you'll be able to query values and set new ones (don't forget to call data_source.change.emit() afterward)

  2. Create a separate Bokeh model for relevant forms/inputs (examples) where each field would map to a corresponding value in a form or an input. In this case, you don't need to call emit - you can just set values

As of now, both of this approaches have the same problem - you can't just add an arbitrary model, be it a ColumnDataSource or some custom model, to a Bokeh document due to bokeh/issues/3117 and bokeh/issues/3349, but you can create a custom model just for this:

from bokeh.core.properties import Instance, List
from bokeh.model import Model, DataSource


class DataSourceRoot(Model):
    sources = List(Instance(DataSource))

    __implementation__ = TypeScript("""
    import {DOMView} from "core/dom_view"
    import {Model} from "model"
    import * as p from "core/properties"

    export class DataSourceRootView extends DOMView {
        renderTo(element, replace=false): void {}
    }

    export class DataSourceRoot extends Model {
    }

    DataSourceRoot.prototype.type = 'DataSourceRoot';
    DataSourceRoot.prototype.default_view = DataSourceRootView;
    DataSourceRoot.define({
        sources: [ p.Any ]
    })
    """)

You'll then be able to write something like this:

source_root = DataSourceRoot()
curdoc().add_root(source_root)

source_root.sources.append(ColumnDataSource(id='my-source', data=dict(a=[1])))

And use it on JS side like this:

// Note the unfortunate `[0]` - right now Bokeh doesn't have a way
// to get a document by some ID
console.log(Bokeh.documents[0].get_model_by_id('my-source').data['a']);
Eugene Pakhomov
  • 9,309
  • 3
  • 27
  • 53