Including CSS Classes for DataTable

First let me say I’m pretty new to Bokeh. And let me also say my knowledge of CSS is pretty darn limited (of course this is part of the appeal of Bokeh!)

I am using the DataTable widget in my project. I wanted to provide some CSS styling for this DataTable which I was able to get to work…

What I did (thanks in part to a StackOverlow article or two I found along the way) was to specify the css_classes parameter when I instantiate the DataTable object. Here, I specified a couple of CSS classes…

And then I included the HTML to create those CSS classes within two totally separate Bokeh Div widgets. FWIW here I’m realizing I probably could have included all the code in just one Div widget vs. two…

So my code looks something like this:

foo_table = DataTable(
    source = source,
    columns = columns,
    width = 400,
    height = 100,
    css_classes = ['table_style', 'table_header_style'])

table_style = Div(text = """
<style>
.table_style{
font-weight: bold !important;
font-size: 10px !important; 
}
</style>
""")
table_header_style = Div(text = """
<style>
.slick-header-column{
  color: white !important;
  background: green !important;
}
</style>
""")

show(
    layout(
            [other_widget_1, other_widget_2],
            foo_table,
            table_style,
            table_header_style
            )
    )

So as noted this all works as intended, but I have a few questions:

  1. It seems to me that my first CSS class seems to be overwriting the CSS for the SlickGrid table and that the CSS class name really does not matter. However, for the second CSS class, it seems that this class is correctly named to match up with a specific SlickGrid CSS class (I was actually able to find this class I think by clicking through on the page source to the CDN-based JavaScript code)… So is this indeed what is happening?

  2. Is there a better way to do what I am doing here? It seems a bit hacky to create a separate Div object that is used for no other purpose than to specify the CSS classes/styles and then to refer to those separately in my DataTable widget. Should the CSS be included in the Web page/Bokeh doc in some other way? I have gone through the Bokeh documentation a good bit and may have missed it, but I’m guessing there may be a better way to include the CSS or to otherwise be able to apply different like styling to the DataTable. FWIW, for now I am just running this code on a desktop, using the show method as noted.

  3. I don’t think this is related to my questions above, but I did not notice the below error in the page source. The error does not go away if I totally remove the css_classes parameter from my DataTable and also remove the Div objects. Is this error indicative of something actually missing from my project?

Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing.

Thanks in advance for any help!

1 Like

This is a good question that I don’t quite know the answer to, but I am wondering if bokeh’s Theme model could somehow be used to accomplish this in lieu of the Div-hack. I am very interested in improving table formatting/customization… it’s one of the biggest complaints I get from users, that the tables are not as “pretty” nor are they consistent with my themed figures.

1 Like

So I took a rough stab at understanding this. I managed to be able to control some table formatting through a css style sheet-type setup using a jinja template and the resources/components assembly line similar to this: bokeh/embed_themed.py at branch-3.0 · bokeh/bokeh · GitHub .


from bokeh.models.widgets import DataTable, TableColumn
from bokeh.models import CheckboxGroup, ColumnDataSource
from jinja2 import Template
from bokeh.embed import components
from bokeh.resources import Resources
from bokeh.layouts import layout

#make dummy stuff
data = {'things':['apple','banana','thing3']}
src=ColumnDataSource(data)
cbg = CheckboxGroup(labels=data['things'],active=[0,1,2]
                    ,css_classes=['cbstyle'] ##???? probably not doing this right? do 
                    )
col = TableColumn(field='things',title='WHY NOT ALIGNED RIGHT?')
tbl = DataTable(source=src,columns=[col])
#put em together in a layout
lo = layout([[cbg,tbl]])
#break into script and div componenents
script,div = components(lo)

#some of this schtuff works, some of it doesn't...
css_stuff = '''
                <style>
                  .slick-header-columns {
                    background-color: #17648D !important;
                    font-family: arial;
                    font-weight: bold;
                    font-size: 12pt;
                    color: #FFFFFF;
                    text-align: right;
                    }
                  .slick-row{
                    font-size: 8pt;
                    font-family: arial;
                    text-align: right;
                    }
                  .cbstyle{
                      font-size: 45pt
                      background: red
                      }
                </style>
            '''

tpl = Template('''<!DOCTYPE html>
        <html lang="en">
            <head>
                <meta charset="utf-8">
                <title>'''+'Here is a title'+'''</title>
                {{ resources }}
                {{ script }}
                '''+css_stuff+'''
            </head>
            <body>
                <div>
                {{ div }}
                </div>
            </body>
        </html>
        ''')
resources = Resources().render()
html = tpl.render(resources=resources,script=script,div=div)
with open('test.html', mode="w", encoding="utf-8") as f:
    f.write(html)

Now what’s confusing/not working for me at all:

  1. For some reason text-align doesn’t want to work? As far as I can tell there’s some default slickgrid formatting overriding things that I can’t seem to get access to? Every bloody js side demo I see of this, I can just write text-align: center and it works → see Edit fiddle - JSFiddle - Code Playground

  2. I have read slickgrid documentation basically all day and I still don’t really understand how to somehow “know” what components are available to me (e.g. slick-row or slick-header-columns etc.) nor do l know how to know what aspect of the table they format, nor what formatting options are available to me for them. It’s just been brute force trial and error, using inspect in the browser somewhat combined with the .css for slick grid here :SlickGrid/slick.grid.css at master · 6pac/SlickGrid · GitHub

  3. With the checkbox group, I’m ultimately trying to do something somewhat related/approach this kind of custom formatting alternatively–> using the css_classes arg when instantiating a checkboxgroup. What my conceptualization is (and this may be wrong because it’s clearly not working but it’s how i’ve interpreted the documentation at least), is that i assign a string within a list to the css_classes, and that string will be looked up in the css for formatting instructions? If that’s not how it works then fine, but if it is, how do I even know what formatting options are available to me then? You can see my attempt in the code above, I’m trying to make the checkbox group text massive and give it a red background just for demo’s sake.

Anyway, just sharing my “learning” for the day…hopefully this helps a bit.

1 Like

Thanks a ton for digging in to this @gmerrit123. I’ve moved on to some stuff outside the formatting topic of my post, bit I will undoubtedly come back to this soonish to revisit and will further check out what you have suggested re a jinja template.

1 Like

So minor progress update → based on this thread: [FEATURE] Add ability to align RadioGroup options with icons · Issue #11524 · bokeh/bokeh · GitHub, I was able to figure out how to mess with formatting of a widget through the css_classes arg. My thought process was correct but I missed the same nuance @efremdan1 did initially → that you have to point to the .bk class in the stylesheet.

In my css string in the code above, if I go


.cbstyle .bk{
font-size: 45pt;
background: red
}

‘’’

An aesthetically unpleasing yet demonstrative success:

image

So what still remains a bit of a ? for me is controlling certain aspects of stuff inside tables, like text alignment.