Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] visible property for TableColumns #11423

charlesbluca opened this issue Jul 15, 2021 · 2 comments · Fixed by #11501

[FEATURE] visible property for TableColumns #11423

charlesbluca opened this issue Jul 15, 2021 · 2 comments · Fixed by #11501


Copy link

Is your feature request related to a problem? Please describe.

I am trying to use a CheckboxButtonGroup widget to toggle the visibility of columns in a DataTable. My approach to this is to use some CustomJS that adds or removes columns from the table in question upon clicking the button:


from datetime import date
from random import randint

from import show
from bokeh.layouts import column
from bokeh.models import (
from bokeh.plotting import curdoc

data = dict(
        dates=[date(2014, 3, i+1) for i in range(10)],
        downloads=[randint(0, 100) 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)

column_choice = CheckboxButtonGroup(
    active=[0, 1],
            table=data_table, columns=columns
            var visible_columns = []
            for (var i = 0; i <; i++) {
            table.columns = visible_columns;

curdoc().add_root(column(column_choice, data_table))
$ bokeh serve --show

This works fine, and the table responds as expected. However, I get serialization errors in console every time I click the button - I reported this bug in #11422.

Describe the solution you'd like

An alternative method to toggle column visibility would be to have a visible property on TableColumns, similar to the one for DataTables. This would allow me to toggle the visibility of the columns using this property, which would be simpler than what I am currently doing and would potentially circumvent the serialization errors I encountered in #11422.

Describe alternatives you've considered
An alternative suggested by @bryevdv to try and avoid the serialization errors was to use a hidden DataTable in the document as a "bank" for the columns I want to toggle on and off for the main table. I tried this approach out but encountered the same serialization errors.

Additional context
This issue came up while working on dask/distributed#4614.

Copy link

bryevdv commented Jul 16, 2021

Here is a minimal POC diff that gets this minimally working

base ❯ git diff
diff --git a/bokeh/models/widgets/ b/bokeh/models/widgets/
index df9bd0ea0..44f490646 100644
--- a/bokeh/models/widgets/
+++ b/bokeh/models/widgets/
@@ -618,6 +618,10 @@ class TableColumn(Model):
     The default sorting order. By default ``ascending`` order is used.

+    visible = Bool(True, help="""
+    Whether this column shold be displayed or not.
+    """)
 class TableWidget(Widget):
     ''' Abstract base class for data table (data grid) widgets.
diff --git a/bokehjs/src/lib/models/widgets/tables/data_table.ts b/bokehjs/src/lib/models/widgets/tables/data_table.ts
index 0c273d4b2..9cebedfca 100644
--- a/bokehjs/src/lib/models/widgets/tables/data_table.ts
+++ b/bokehjs/src/lib/models/widgets/tables/data_table.ts
@@ -136,6 +136,10 @@ export class DataTableView extends WidgetView {

     this.connect(this.model.source.selected.change, () => this.updateSelection())
     this.connect(, () => this.updateSelection())
+    for (const column of this.model.columns) {
+      this.connect(column.change, () => this.render())
+    }

   override remove(): void {
@@ -254,7 +258,7 @@ export class DataTableView extends WidgetView {

   override render(): void {
-    const columns: ColumnType[] = => {
+    const columns: ColumnType[] = this.model.columns.filter((column) => column.visible).map((column) => {
       return {...column.toColumn(), parent: this}

diff --git a/bokehjs/src/lib/models/widgets/tables/table_column.ts b/bokehjs/src/lib/models/widgets/tables/table_column.ts
index 22df913c0..18ed904da 100644
--- a/bokehjs/src/lib/models/widgets/tables/table_column.ts
+++ b/bokehjs/src/lib/models/widgets/tables/table_column.ts
@@ -18,6 +18,7 @@ export namespace TableColumn {
     editor: p.Property<CellEditor>
     sortable: p.Property<boolean>
     default_sort: p.Property<Sort>
+    visible: p.Property<boolean>

@@ -39,6 +40,7 @@ export class TableColumn extends Model {
       editor:       [ Ref(StringEditor), () => new StringEditor() ],
       sortable:     [ Boolean, true ],
       default_sort: [ Sort, "ascending" ],
+      visible:      [ Boolean, true ],

Some issues:

  • This won't respond by connecting or disconnecting signals if columns itself is modified (but if visible works the best pattern would be to add all columns up front and manage visibility anyway)
  • This doesn't currently seem to update layout in "fit columns" mode

Here is a minimal example to test with

from import curdoc
from bokeh.layouts import row
from bokeh.models import ColumnDataSource, DataTable, TableColumn, Toggle
from bokeh.plotting import figure


source = ColumnDataSource(data=dict(x=x, y=y))

plot_figure = figure(title='Data-Table',height=450, width=600,
              tools="save,reset", toolbar_location="below")

plot_figure.scatter('x', 'y', source=source, size=10)

columns = [
    TableColumn(field="x", title="x"),
    TableColumn(field="y", title="y")
data_table = DataTable(
    # width=80,

toggle = Toggle()

def cb(attr, old, new):
    columns[0].visible =

toggle.on_change('active', cb)

layout=row(plot_figure, data_table, toggle)

curdoc().title = "Data-Table Bokeh Server"

Copy link

bryevdv commented Aug 11, 2021

Try: invalidate_layout

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet

Successfully merging a pull request may close this issue.

2 participants