question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[BUG] on_change events of DataTable CDS fail when source is set after init

See original GitHub issue

Software version info bokeh 2.0.0 chrome 80.0.3987.132 (Official Build) (64-bit) ubuntu 19.10

Description of expected behavior and the observed behavior Context:

  • An on_change(‘data’, callback) is registered on the ColumnDataSource which is attached to a DataTable
  • An on_change(‘indices’, callback) is registered on the “selected” field of a ColumnDataSource which is attached to a DataTable

Expect:

  • The callback will be called while the content in the DataTable is edited
  • The callback will be called while a row in the DataTable is selected

Observed:

  • Both callbacks are not called

Complete, minimal, self-contained example code that reproduces the issue

from bokeh.io import curdoc
from bokeh.models import TableColumn, ColumnDataSource, DataTable

columns = [TableColumn(field='a', title='a'),
             TableColumn(field='b', title='b'),
             TableColumn(field='c', title='c')]

cds = ColumnDataSource(dict(a=[1,2,3],b=[2,3,4], c=[3,4,5]))

table = DataTable(editable=True, width=300, height=150)
table.source = cds
table.columns = columns
def on_data(attr, old, new):
    print('on_data')

def on_select(attr, old, new):
    print('on_select')


table.source.on_change('data', on_data)
table.source.selected.on_change('indices', on_select)

curdoc().add_root(table)

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
bryevdvcommented, Mar 10, 2020

@maeglin89273 your code works for me if I change to pass source directly to DataTable:

table = DataTable(editable=True, width=300, height=150, source=cds)

It should work the way you have it too, and I am not sure why it does not, but hopefully this is an immediate solution for you.

0reactions
bryevdvcommented, Mar 11, 2020

@mattpap for reference this solves the issue:

diff --git a/bokeh/document/util.py b/bokeh/document/util.py
index 3583323b2..ab012ec80 100644
--- a/bokeh/document/util.py
+++ b/bokeh/document/util.py
@@ -125,6 +125,7 @@ def references_json(references):

     references_json = []
     for r in references:
+        r._finalize()
         struct = r.struct
         struct['attributes'] = r._to_json_like(include_defaults=False)
         references_json.append(struct)
diff --git a/bokeh/model.py b/bokeh/model.py
index c6594fb1f..e5f17077e 100644
--- a/bokeh/model.py
+++ b/bokeh/model.py
@@ -774,6 +774,16 @@ class Model(HasProps, PropertyCallbackManager, EventCallbackManager):

         return html

+    def _finalize(self):
+        """ This methods can be oeverriden if  a model needs to defer some
+        configuration until serialization time. E.g. if a model needs to set
+        up a relation bewteen two sub-components.
+
+        WARNING: no new models should ever be created inside this method
+
+        """
+        pass
+
 #-----------------------------------------------------------------------------
 # Private API
 #-----------------------------------------------------------------------------
diff --git a/bokeh/models/widgets/tables.py b/bokeh/models/widgets/tables.py
index 9d2c5aa38..aabf093cd 100644
--- a/bokeh/models/widgets/tables.py
+++ b/bokeh/models/widgets/tables.py
@@ -610,16 +610,15 @@ class TableWidget(Widget):
     The source of data for the widget.
     """)

-    view = Instance(CDSView, help="""
+    view = Instance(CDSView, default=lambda: CDSView(), help="""
     A view into the data source to use when rendering table rows. A default view
     of the entire data source is created if a view is not passed in during
     initialization.
     """)

-    def __init__(self, **kw):
-        super().__init__(**kw)
-        if "view" not in kw:
-            self.view = CDSView(source=self.source)
+    def _finalize(self):
+        if self.view.source is None:
+            self.view.source = self.source

 class DataTable(TableWidget):
     ''' Two dimensional grid for visualisation and editing large amounts

Would you be in favor of this approach to get rid of initializers on models more generally?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Reload/refresh table after event — DataTables forums
I am trying to reload the table but I can't seem to find the way to call the reload function. In the .done...
Read more >
How to reinitialize dataTables with newly fetched data from ...
You're re-initializing the table with different options in fetchNews() . You need to destroy the table first, see http://datatables.net/manual/ ...
Read more >
jQuery DataTables: Why click event handler does not work
Provides solution to a problem when click and other event handlers don't work on pages other than first or when table is sorted...
Read more >
Uncaught TypeError: Cannot read property of undefined
If you get undefined error, you need to make sure that which ever variables throws undefined error, is assigned a value to it....
Read more >
Combo box OnChange - Power Platform Community - Microsoft
The population of the combo is fine but the onchange event does not work with more than on set of choices. Please see...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found