I would like to know whether there is some method to add new column to datatable via JavaScript-callback. For example, I have some datatable of 2 columns, I press a button and then I already have updated datatable with 3 columns.
Some pattern (data for 3rd column is named as "data_to_add" and is commented there):
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))
Thank you!
It's possible, but your data has to somehow end up in the data source. Either because you put it directly there in JavaScript, or because you have put it there before you have generated the HTML file with that show(...)
call, or because you use a Bokeh server that's able to add columns to data sources dynamically.
With that being said, here's the shortest example I could come up with:
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))