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

Bokeh DataTable #713

Open
amitdeliwala opened this issue Nov 5, 2021 · 1 comment
Open

Bokeh DataTable #713

amitdeliwala opened this issue Nov 5, 2021 · 1 comment

Comments

@amitdeliwala
Copy link

I am attempting to add a Bokeh DataTable object via Flexx. Because it uses a ColumnDataSource, I assume that we can make it work very similarly to the BokehWidget for plots. Just as we create a figure, we can create a DataTable from a ColumnDataSource:

x_table = [randint(0, 100) for i in range(10)]
y_table = [randint(0, 100) for i in range(10)]
total = np.sum([x_table, y_table], axis = 0)

self.datatable_source = ColumnDataSource(dict(x=x_table, y=y_table, total = total))
datatable_columns = [TableColumn(field="x", title="x"),
                    TableColumn(field="y", title="y"),
                    TableColumn(field="total", title="total")]
self.data_table= DataTable(source=self.datatable_source,
                            # columns=datatable_columns, 
                            width=600, height=600, editable = True)

I have created a modified BokehWidget object which works very similarly to the BokehWidget for plots:

def make_bokeh_widget_from_data_table(data_table, **kwargs):
    ns = {}
    exec("from bokeh.models.widgets import DataTable", ns, ns)  # noqa - dont trigger e.g. PyInstaller
    exec("from bokeh.embed import components", ns, ns)  # noqa - dont trigger e.g. PyInstaller
    DataTableClone, components = ns["DataTable"], ns["components"]
    # Set plot prop
    if not isinstance(data_table, DataTableClone):
        raise ValueError('plot must be a Bokeh plot object.')
    # The sizing_mode is fixed by default, but that's silly in this context
    
    # if plot.sizing_mode == 'fixed':
    #     plot.sizing_mode = 'stretch_both'
    
    # Get components and apply to widget
    script, div = components(data_table)
    script = '\n'.join(script.strip().split('\n')[1:-1])
    widget = BokehWidgetAdapted(**kwargs)
    widget.set_table_components(
        dict(script=script, div=div, id=data_table.ref['id']))
    return widget

class BokehWidgetAdapted(BokehWidget):
    @classmethod
    def from_data_table(cls, data_table, **kwargs):
        """ Create a BokehWidget using a Bokeh plot.
        """
        return make_bokeh_widget_from_data_table(data_table, **kwargs)
    
    table = event.Attribute(doc="""The JS-side of the Bokeh plot object.""")

    def _render_dom(self):
        return None

    @event.action
    def set_table_components(self, d):
        """ Set the plot using its script/html components.
        """
        global window
        # Embed div
        self.node.innerHTML = d.div  # We put trust in d.div
        # "exec" code
        el = window.document.createElement('script')
        el.innerHTML = d.script
        self.node.appendChild(el)
        # Get plot from id in next event-loop iter
        def gettable():
            self._table = window.Bokeh.index[d.id]
            self.__resize_table()
        window.setTimeout(gettable, 10)
    
    @event.reaction('size')
    def __resize_table(self, *events):
        if self.table and self.parent:
            if self.table.resize_layout:
                self.table.resize_layout()
            elif self.table.resize:
                self.table.resize()  # older
            else:
                self.table.model.document.resize()  # older still

To get these widgets working, the bokeh-tables.js, bokeh-widgets.js and bokeh-mathjax.js files are associated using app.assets.associate_asset. We can then try to add the Bokeh DataTable object:

self.table = BokehWidgetAdapted.from_data_table(self.data_table, title='Table')

This partially works! The table is rendered on the page, but the data is blank and no errors are thrown. Is there something I am missing here? I think this would be a great widget to add to Flexx to have support for tables via Bokeh. I think it should be extendable to most Bokeh widgets such as buttons, checkboxes, etc.

@almarklein
Copy link
Member

Looks cool! I don't have a lot of time to look at this now though ...

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

No branches or pull requests

2 participants