Hi Anthony,
This bokeh server example might be helpful. I’m not sure this is the best way to achieve what you’re after, but it’s one solution.
In this example, the way you dynamically select rows is to have a second data source which you put the computed row indices into. The bokeh server automatically syncs data sources so when the .data property on the data source changes on the python side, it is reflected on the front end. Clicking button2, “Compute indices”, calls the python function compute_indices which sets .data on source2. At this point, you have to then click on the “Select” button, which calls the CustomJS function which takes the data from source2 and sets the selected indices on source1 which is the data source containing the data for the plots. I don’t think there is a way to set the selected property on the Python side and have it propagate to the JS side, so that’s why the CustomJS might be necessary for now. There is also another detail where the signal that causes the the re-rendering of the plot differs from the one that causes highlighting in the data table (see the comments in the CustomJS below).
from bokeh.plotting import figure, curdoc
from bokeh.models import CustomJS
from bokeh.models.sources import ColumnDataSource
from bokeh.layouts import row, column
from bokeh.models.widgets import DataTable, TableColumn, Button
import random
data = dict(index=list(range(10)), x = list(range(10)), y = list(range(10)), z = [‘some other data’] * 10)
source1 = ColumnDataSource(data)
source2 = ColumnDataSource(dict(computed_indices=[1,2,3]))
fig1 = figure(plot_width=300, plot_height=300)
fig1.circle(x=‘x’, y=‘y’, size=10, source=source1)
columns = [
TableColumn(field=“y”, title=“Y”),
TableColumn(field=“z”, title=“Text”),
]
data_table = DataTable(source=source1, columns=columns, width=400, height=280)
button = Button(label=“Select”)
button.callback = CustomJS(args=dict(source1=source1, source2=source2), code="""
source1[‘selected’][‘1d’].indices = source2[‘data’][‘computed_indices’]
source1.properties.selected.change.emit() //DataTable highlights when the selected property “change” signal is emitted
source1.select.emit() //GlyphRenderer (the circles in this example) re-render when a data source’s “select” signal is emitted
“”")
def compute_indices():
computed_indices = random.sample(list(range(10)), 3)
new_data = dict(computed_indices=computed_indices)
source2.data = new_data
button2 = Button(label=“Compute indices”)
button2.on_click(compute_indices)
curdoc().add_root(row(fig1, data_table, column(button2, button)))
``
Best,
Claire