☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

DataTable doesn't update when source changes

Community Supportbokeh
BlaBlou
BlaBlou

I’m working with a DataTable and I want to have some triggers that change the values in the table.
I’m able to change the source value without problem, however, I can’t get the displayed table to update when I do.

Here is a very simplified version of my code. When I click on the button, I expect the first value of col1 to change to ‘z’. When I check by sending the value to the log, it seems to have worked, however, the Table still show an ‘a’ there.

Can you help me find what I’m missing ?

from bokeh.io import curdoc
from bokeh.models import ColumnDataSource, Button
from bokeh.models.widgets import DataTable, TableColumn
from bokeh.layouts import column

import logging
import bokeh
import pandas as pd

df = pd.DataFrame({'col1': ['a', 'a', 'b', 'a', 'c', 'b', 'a'],
                   'col2': [1, 3, 3, 4, 2, 1, 3]
                 })

source = ColumnDataSource(df)

columns = [TableColumn(field = col, title=col) for col in df.columns]

data_table = DataTable(columns=columns, 
                       source=source
                       )

but = Button(label = 'Change')

def change_value():
    global source 
    source.data['col1'][0] = 'z'
    logging.warning(source.data['col1'][0])
    
but.on_click(change_value)

lay = column(data_table, but)

curdoc().add_root(lay)

⌁   Link to post
Bryan
Bryan

Bokeh can only implement so much auto-magic. You need to assign a whole new column, or a whole new .data dict. “In-place” item assignments are not detected.

Alternatively you can use the .patch method on the CDS.

⌁   Link to post
BlaBlou
BlaBlou

Thank you for the quick reply. Do you mean I should assign a new dictionary to source ?

I tried replacing

    source.data['col1'][0] = 'z'

by

    df2 = {'col1': ['z', 'a', 'b', 'a', 'c', 'b', 'a'],
           'col2': [1, 3, 3, 4, 2, 1, 3]
          }
    source = ColumnDataSource(df2)

But nothing changes. Did I misunderstand something ?

EDIT : I just tried with the patch method, it works fine. I’m still curious as to why the above doesn’t work, as it would suit my actual use case better.

⌁   Link to post
gmerritt123
gmerritt123

The issue now is you’re instantiating a new columndatasource, one that isn’t assigned to drive your renderer.

See my edit below:

df2 = {'col1': ['z', 'a', 'b', 'a', 'c', 'b', 'a'],
           'col2': [1, 3, 3, 4, 2, 1, 3]
          }

#source = ColumnDataSource(df2)
#instead:
source.data = df2
#my own curiousity also give this a go---> the "single column replace only" option Bryan mentioned
# source.data['col1'] = df2['col1']
#and also the patch thing Bryan mentioned:
#never used this before, but the idea I think is you pass a dict with columns for keys, and a 2 item tuple as each key value for that dict like this: (index,value to fill it with) 
# source.patch({'col1':(0,'z')})

Best explainer for this that helped me understand why some things “magically auto-update” while others don’t: python - Bokeh: Whats the differences between certain methods of editing data in a ColumnDataSource - Stack Overflow

⌁   Link to post
Bryan
Bryan

FWIW The TLDR reason that “in place” item assignments are not auto-magically handled is that wrapping arrays to intercept every single item assignment would be detrimental to performance of the common usage, and would implicitly promote usage patterns that could never be made efficient (e.g looping over and assigning every item individually would always be terrible, even if it “worked”).

⌁   Link to post

End of archived discussion · Replies are disabled