最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to get Bokeh DataTable cell content on click? - Stack Overflow

programmeradmin4浏览0评论

Do you know how to get Bokeh DataTable cell value by clicking on it?

If I use:

data = dict(
 items=bokehItems,
    values0=bokehValues0,
    values1=bokehValues1,
    values2=bokehValues2
)

source = ColumnDataSource(data)

columns = [
    TableColumn(field="items", title="Item"),
    TableColumn(field="values0", title="Value"),
    TableColumn(field="values1", title="Cluster"),
    TableColumn(field="values2", title="Interaction"),
]



data_table_worst_cases = DataTable(source=source, columns=columns, height=280,
                                   row_headers=False, fit_columns=True)


source.callback = CustomJS(args=dict(source=source), code="""
    console.log( cb_obj.get('data'));
""")

When I click in the table I always get the content of the plete table, not the particular cell.

Do you know how to get Bokeh DataTable cell value by clicking on it?

If I use:

data = dict(
 items=bokehItems,
    values0=bokehValues0,
    values1=bokehValues1,
    values2=bokehValues2
)

source = ColumnDataSource(data)

columns = [
    TableColumn(field="items", title="Item"),
    TableColumn(field="values0", title="Value"),
    TableColumn(field="values1", title="Cluster"),
    TableColumn(field="values2", title="Interaction"),
]



data_table_worst_cases = DataTable(source=source, columns=columns, height=280,
                                   row_headers=False, fit_columns=True)


source.callback = CustomJS(args=dict(source=source), code="""
    console.log( cb_obj.get('data'));
""")

When I click in the table I always get the content of the plete table, not the particular cell.

Share Improve this question edited Jan 19, 2017 at 16:49 Zoran Milosavljevic asked Jan 19, 2017 at 16:30 Zoran MilosavljevicZoran Milosavljevic 511 silver badge3 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 9

This version uses Python callback (updated for Bokeh v1.0.4). Run as: bokeh serve --show app.py

from random import randint
from datetime import date
from bokeh.models import ColumnDataSource, TableColumn, DateFormatter, DataTable
from bokeh.layouts import column
from bokeh.models.widgets import TextInput
from bokeh.plotting import curdoc

data = dict(dates = [date(2014, 3, i + 1) for i in range(10)],
            downloads = [randint(0, 100) for i in range(10)],
            identities = ['id_' + str(x) for x in range(10)])

source = ColumnDataSource(data)

columns = [TableColumn(field = "dates", title = "Date",
           formatter = DateFormatter()),
           TableColumn(field = "downloads", title = "Downloads")]

data_table = DataTable(source = source, columns = columns, width = 280, height = 280, editable = True)
table_row = TextInput(value = '', title = "Row index:")
table_cell_column_1 = TextInput(value = '', title = "Date:")
table_cell_column_2 = TextInput(value = '', title = "Downloads:")

def function_source(attr, old, new):
    try:
        selected_index = source.selected.indices[0]
        table_row.value = str(selected_index)
        table_cell_column_1.value = str(source.data["dates"][selected_index])
        table_cell_column_2.value = str(source.data["downloads"][selected_index])
    except IndexError:
        pass

source.selected.on_change('indices', function_source)
curdoc().add_root(column(data_table, table_row, table_cell_column_1, table_cell_column_2))

Result:

And here is how you can also distinguish between table rows and columns that are being clicked. The second Python callback is a trick to reset the indices so that a click on the same row can be detected (updated for Bokeh v1.0.4). Run with 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))

Result:

You did not post the entire code so it is hard to give you direct answer. However based on the example below you should be able to figure out how to solve your problem (updated for Bokeh v1.0.4).

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, show

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_date = TextInput(value = None, title = "Date:", width = 420)
text_downloads = TextInput(value = None, title = "Downloads:", width = 420)

source_code = """
row = cb_obj.indices[0]
text_row.value = String(row);
text_date.value = String(new Date(source.data['dates'][row]));
text_downloads.value = String(source.data['downloads'][row]); """

callback = CustomJS(args = dict(source = source, text_row = text_row, text_date = text_date, text_downloads = text_downloads), code = source_code)
source.selected.js_on_change('indices', callback)
layout = column(data_table, text_row, text_date, text_downloads)
show(layout)

Result:

发布评论

评论列表(0)

  1. 暂无评论