Pass a Pandas DataFrame to a Bootstrap Table from a callback?

Has anyone been able to successfully pass a df to a dbc.Table.from_dataframe() using a callback? I think it would be relatively simple but haven’t been successful so far.

Any help would be appreciated.

Thanks!

Hi @cgeorge

I never did it, but reading the documentation seams to be very simple, just pass the DataFrame as ‘children’ to the table, showing table in the layout as:

dbc.Table.from_dataframe(df, striped=True, bordered=True, hover=True)

If I understand correctly, the first argument is the ‘children’ then replace df for your DataFrame.

If do not work, show your code and the error you are facing.

1 Like

I think the easiest thing to do is to actually call dbc.Table.from_dataframe inside the callback and pass the output to a wrapper element. Something like the below.

app.layout = html.Div(id="table-container")


@app.callback(Output("table-container", "children"), [Input(..., ...)]))
def make_table(...):
    df = make_df_from_inputs(...)
    return dbc.Table.from_dataframe(df, ...)

The Table component itself isn’t able to understand a dataframe, the .from_dataframe method is really just a convenience function that converts a dataframe to Dash html components, but you can’t directly pass a dataframe to the table from a callback.

4 Likes

@tcbegley Great explanation, got it working now. Thanks!

1 Like

Hey Tom,

Thanks for the explanation !!!

It’s a very easy way to assign a DataFrame to a Table :smiley:

1 Like

@tcbegley Dear Tom,
i have followed your suggestions and passing the whole table from a callback in an html.Div, instead of only the dataframe. But i saw something strange… Since my input on the callback as an interval component, each time the table is updated, there is some extra space added in the container. I’m not updating the table with extra values, i’m updating the table with the same static values.

this is the container with the table…:

services_section=dbc.Container( dbc.Col([
html.Div(“Services section”),
html.Div([‘sdfsdf’,‘sdfsdfd’,‘df’,‘dsf’], id=‘services_table’),
], style={‘background-color’: ‘#ADD8E6’} , width=12) )

this is the code updating the table

def read_table2():

    df = pd.DataFrame(
        {
            "Service": ['1','2','3','4'],
            "Status": ['1','2','3','4'],
        })
    services_table=dbc.Table.from_dataframe(df, id='services_table')
    return services_table


and the callback:

@app.callback(Output('terminal', 'value'),
              Output('service_name', 'children'),
              Output('services_table','children'),
              Input('command', 'n_clicks'),
              Input('interval', 'n_intervals'),
              #Input('terminal', 'value'),
              State('input_text', 'value'),
              )

def update_interval(n, interval , input_text):   #input values as arguments

    now = datetime.now() # current date and time
    d = now.strftime("%M%S")
    #print('new line: ', d)	
    disp(d)
    #print('lines: ', lines)
    terminal_out=lines2textarea()
    #df=read_services()

    return [ terminal_out , ['Code Name: ', input_text] , read_table2() ]

any suggestions ?

@Bambos Each time you call update_interval you’re making a new dbc.Table which is being assigned as the children of services_table. And in fact, this new table itself has id services_table. So each time the callback runs, instead of replacing the table you’re making a new table and putting it inside the old one. That will lead to a HTML structure like this.

<table>
  <table>
    <table>
       ...
    </table>
  </table>
</table>

Instead of returning dbc.Table as the children of an already existing dbc.Table, I suggest you make a html.Div with id="services_table_container" and change your callback to update Output("services_table_container", "children") instead.