1

The below code is a minimal example of an issues where a bokeh model doesn't update when it's attribute is set via a callback. I've found that removing and adding back a model object (not even the suspect one) from the layout of the curdoc forces it to refresh. I've shown this via the first button press.

Is there a more elegant way to force bokeh to redraw the figure?

The example is for DataTable.columns.formatter, but I've noticed that this applies to other model attributes as well (including axis ranges, where I've seen a workaround involving setting the range explicitly at figure creation to allow updates).

from bokeh.models.widgets import Dropdown, RadioButtonGroup, CheckboxGroup, \
    Toggle, DataTable, TableColumn, NumberFormatter
from bokeh.plotting import figure, curdoc, ColumnDataSource
from bokeh.layouts import column, layout


def update_format(attr, old, new):
    if toggle_commas.active == 1:
        (t.columns[1].formatter)
        # remove the commas
        t.columns[1].formatter = NumberFormatter(format='0,0.[00]')
        # show that it updates the actual attribute
        print(t.columns[1].formatter)
        del doc_layout.children[-1]
        doc_layout.children.insert(1, toggle_commas)
    else:
        # change the formatter back and note that it doesn't update the table unless you remove and add something
        (t.columns[1].formatter)
        # remove the commas
        t.columns[1].formatter = NumberFormatter(format='0.[00]')
        # show that it updates the actual attribute
        print(t.columns[1].formatter)

table_data = dict(
        percentiles=['min', '1st', '5th', '10th', '25th', '50th',
                     '75th', '90th', '95th', '99th', 'max', '', 'mean', 'std'],
        values=[i for i in range(1000, 1014)]
    )
table_source = ColumnDataSource(table_data)
table_columns = [
    TableColumn(field="percentiles", title="Percentile"),
    TableColumn(field="values", title="Value", formatter=NumberFormatter(format='0.[00]'))
    ]

t = DataTable(source=table_source, columns=table_columns, width=400, height=600,
              name='pct_table')

toggle_commas = Toggle(label='Commas', active=False)
toggle_commas.on_change('active', update_format)

doc_layout = layout(t, toggle_commas)
curdoc().add_root(doc_layout)
Chris McL
  • 190
  • 10

0 Answers0