В следующем коде используется обратный вызов JS для отображения индекса строки и столбца, а также содержимого ячейки.Второй обратный вызов Python - это хитрость для сброса индексов, чтобы можно было обнаружить щелчок по той же строке (протестировано с Bokeh v1.0.4).Выполнить с bokeh serve --show app.py
from random import randint
from datetime import date
from bokeh.models import ColumnDataSource, TableColumn, DateFormatter, DataTable, CustomJS
from bokeh.layouts import column
from bokeh.models.widgets import TextInput
from bokeh.plotting import curdoc
source = ColumnDataSource(dict(dates = [date(2014, 3, i + 1) for i in range(10)], downloads = [randint(0, 100) for i in range(10)]))
columns = [TableColumn(field = "dates", title = "Date", formatter = DateFormatter()), TableColumn(field = "downloads", title = "Downloads")]
data_table = DataTable(source = source, columns = columns, width = 400, height = 280, editable = True, reorderable = False)
text_row = TextInput(value = None, title = "Row index:", width = 420)
text_column = TextInput(value = None, title = "Column Index:", width = 420)
text_date = TextInput(value = None, title = "Date:", width = 420)
text_downloads = TextInput(value = None, title = "Downloads:", width = 420)
test_cell = TextInput(value = None, title = "Cell Contents:", width = 420)
source_code = """
var grid = document.getElementsByClassName('grid-canvas')[0].children;
var row, column = '';
for (var i = 0,max = grid.length; i < max; i++){
if (grid[i].outerHTML.includes('active')){
row = i;
for (var j = 0, jmax = grid[i].children.length; j < jmax; j++)
if(grid[i].children[j].outerHTML.includes('active'))
{ column = j }
}
}
text_row.value = String(row);
text_column.value = String(column);
text_date.value = String(new Date(source.data['dates'][row]));
text_downloads.value = String(source.data['downloads'][row]);
test_cell.value = column == 1 ? text_date.value : text_downloads.value; """
def py_callback(attr, old, new):
source.selected.update(indices = [])
source.selected.on_change('indices', py_callback)
callback = CustomJS(args = dict(source = source, text_row = text_row, text_column = text_column, text_date = text_date, text_downloads = text_downloads, test_cell = test_cell), code = source_code)
source.selected.js_on_change('indices', callback)
curdoc().add_root(column(data_table, text_row, text_column, text_date, text_downloads, test_cell))
Результат:
![enter image description here](https://i.stack.imgur.com/sCVg9.gif)