通过 JavaScript-回调向数据表添加新列

Adding new column to Datatable via JavaScript-callback

我想知道是否有一些方法可以通过 JavaScript-回调向数据表添加新列。 例如,我有一些 2 列的数据表,我按下一个按钮,然后我已经更新了 3 列的数据表。

一些模式(第 3 列的数据被命名为 "data_to_add" 并在那里注释):

from datetime import date
from random import randint

from bokeh.models import ColumnDataSource, Callback
from bokeh.models.widgets import DataTable, DateFormatter, TableColumn
from bokeh.events import ButtonClick
from bokeh.io import output_file, output_notebook, show
output_notebook()
data = dict(dates=[date(2014, 3, i+1) for i in range(10)],
            downloads=[randint(0, 100) for i in range(10)])

# data_to_add = [randint(10, 60) for i 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=400, height=280, editable=True)

button = Button(label="Button")

button.js_on_event(ButtonClick, CustomJS(code="""
    console.log("I'm going to add new column to your table")
                    """)
                  )

show(column(data_table,button))

谢谢!

这是可能的,但您的数据必须以某种方式最终出现在数据源中。要么是因为您将它直接放在 JavaScript 中,要么是因为您在使用 show(...) 调用生成 HTML 文件之前就已经将它放在那里,或者因为您使用的 Bokeh 服务器能够动态地向数据源添加列。

话虽如此,这是我能想到的最短的例子:

from bokeh.io import show
from bokeh.layouts import column
from bokeh.models import DataTable, TableColumn, Button, CustomJS, ColumnDataSource

ds = ColumnDataSource(data=dict(a=[1, 2, 3], b=[2, 3, 4]))
t = DataTable(columns=[TableColumn(title='a', field='a'),
                       TableColumn(title='b', field='b')],
              source=ds)

b = Button(label="Add random column")

b.js_on_click(CustomJS(args=dict(ds=ds, t=t),
                       code="""\
                           let column_name = null;
                           while (column_name == null || column_name in ds.data) {
                               column_name = Math.random().toString(36).substring(7);
                           }
                           const n = ds.get_length();
                           ds.data[column_name] = Array.from({length: n}, () => Math.random());

                           const TableColumn = Bokeh.Models('TableColumn');
                           t.columns.push(new TableColumn({title: column_name,
                                                           field: column_name}));
                           t.change.emit();
                           ds.change.emit();
                       """))

show(column(b, t))