kms
kms

Reputation: 2024

Rendering Datatable from callback function - Dash

I am creating a dashboard with multiple tabs and each tab triggers and .py file that renders different elements of plotly objects.

For instance, my callback functions return plots, charts and I am looking to return Datatable.

I am able to do render pandas dataframe with go.Table as shown in the example, but not with DataTable, which is newer and offers an enhanced user experience.

import pandas as pd
import dash
from dash.dependencies import Input, Output, State
import dash_html_components as html
import dash_core_components as dcc
import plotly.plotly as py
from plotly import graph_objs as go
from plotly.graph_objs import *
import dash_table
import flask
from datetime import datetime as dt
from app import app


layout = html.Div([

    html.Div([

        dcc.Dropdown(
                id='select',
                options=[{'label': i, 'value': i} for i in List],
                value='abc',
                placeholder="xyz",
                style={'width': '100%'}

        ), 

    ], style={"width": "15%", "margin-left": "20%", "margin-right": "35%"}), 


    html.Div([

        dash_table.DataTable(

            id='my-table',
            columns=[{"name": i, "id": i} for i in df_lease.columns],

        )
    ])
])


@app.callback(Output('my-table', 'data'),
              [
                  Input("landlord-select", "value")
              ]
             )
def render_table(company, market):

    df_sub1 = df_lease[(df_lease['Landlord'] == company)] 

    df_sub1 = df_sub1[['UnitNo',
                       'Commencement_Date',
                       'Expiration_Date'
                       ]]

    return df_sub1.to_dict(orient='records')

Expected behavior is to render the pandas dataframe as DataTable.

File structure:

- app.py
- index.py
- apps
   |-- __init__.py
   |-- app1.py
   |-- app2.py

index.py includes all the code that renders multi-page/tab layout, and the children property of dcc.Tabs is updated as layout object from template file (app1.py) is passed. This is where, I believe, the error is generated from.

app.layout = html.Div([

    # tabs
    html.Div([

        dcc.Tabs(
            id="tabs",
            style={"height":"60","verticalAlign":"middle"},
            children=[
                 dcc.Tab(label="Marketing", value="marketing_tab"),
                 dcc.Tab(label="Tenants", value="tenants_tab"),
                 dcc.Tab(label="Portfolio", value="portfolio_tab"),
            ],
            value="marketing_tab",
        )

        ],

        className="row tabs_div"
        ),

        # Tab content
        html.Div(id="tab_content", style={"margin": "2% 3%"})

])

@app.callback(Output("tab_content", "children"),
          [
              Input("tabs", "value")
          ]
         )
def render_content(tab):
    """
    For user selections, return the relevant tab
    """
    if tab == "marketing_tab":
        return marketing.layout
    elif tab == "tenants_tab":
        return tenants.layout
    elif tab == "portfolio_tab":
        return portfolio.layout
    else:
        return marketing.layout


    # In[10]:

    if __name__ == '__main__':
        app.run_server(debug=True)

Upvotes: 5

Views: 10245

Answers (1)

coralvanda
coralvanda

Reputation: 6616

This link has some good examples for you to check out. Basically, you'll want your callback to update the data prop of the table. Something like this:

@app.callback(
    Output('my-table', 'data'),
    [Input('dropdown', 'value')])
def callback_a(i):
    df = pd.DataFrame(numpy.arange(30).reshape(5, 6))

    return df.to_dict(orient='records')

It's important that the columns for the table be defined so that the id for each column matches the column name in the dataframe. If you are changing the data in the table, then you may want another callback/output to update the columns prop as well.

Upvotes: 6

Related Questions