How do I use a cell in a data table to drive a dropdown on another page

Hello,

I have an app, that has on one page, 4 data tables. Clicking on a cell from the top, creates a state that drives the table below and 2nd table will drive the table below it and so on to the 4th table. This allows the user to “walk down” our product hierarchy.
hierarchy_walk

I would like two things to happen when the item is chosen on the last table. First, hyperlink to the next page and second, use the item previous clicked in the next page’s dropdown menu.

Below is my hierarchy walk code:

layout = ddk.App(show_editor=True, children = [
    ddk.Block(
        #width = 99,
        children=[
        ddk.DataCard(
                        id='HW',
                        label="The hierarchy walk page allows a user to discover what business line, category, sub-category and item is driving the MAPE or BIAS. Each level of the hierarchy can be filtered by the the level above.",
                        value='Hierarchy Walk Page',
                    ),
            ddk.ControlCard(
                [
                ddk.ControlItem(children=[
        dcc.Dropdown(
            options = [{'label':i, 'value':i}
                 for i in ['home_delivery', 'shop_sales']
                 ],
                multi=False,
                value = 'home_delivery',
                id='location_dropdown',
        ),
        dcc.Dropdown(
            options = [{'label':i, 'value':i}
                for i in model
                ],
                multi=False,
                value = 'base_model',
                id='model_dropdown'
        )
                ],
    )]
            ),
            ddk.Card(children =[
        ddk.Graph(
            id='Business_Line'
        )
    ]),
        ]
    ),
    ddk.Block(
            width = 100,
            children=[
                # ddk.CardHeader(title="Forecast Data Tables"),
                ddk.Card(
                    width=100,
                    children=[ddk.DataTable(id="bl_table",
                            columns=[],
                            data=[],
                            filter_action = 'native',
                            sort_action = 'native')
                    ]
                    ),
                ddk.Card(
                    width=100,
                    children=[
                        ddk.DataTable(id='cat_table',
                        columns = [],
                        data = [],
                        filter_action = 'native',
                        sort_action = 'native',)
                    ]
                ),
                ddk.Card(
                    width=100,
                    children=[
                        ddk.DataTable(id='subcat_table',
                        columns = [],
                        data = [],
                        filter_action = 'native',
                        sort_action = 'native',
                ),
                    ]
                ),
                ddk.Card(
                    width=100,
                    children=[
                        ddk.DataTable(id='item_table',
                        columns = [],
                        data = [],
                        filter_action = 'native',
                        sort_action = 'native',
                ),
                    ]
                )
            ]
    )
]
)





#CONTROL THE BUSINESS LINE GRAPH
@callback(
    dash.dependencies.Output('Business_Line', 'figure'),
    dash.dependencies.Input('model_dropdown', 'value'),
    dash.dependencies.Input('location_dropdown', 'value'),
)
def update_bl(model, location):
    df1 = df_final[(df_final['location_type'] == location) & (df_final['model'] == model)]

    bl = df1.groupby(['glbl_bus_ln_desc']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    bl.replace([np.inf, -np.inf], np.nan, inplace=True)
    bl['sales_dollars'] = np.round(bl['sales_dollars'])
    bl['predictions'] = np.round(bl['predictions'])
    bl.dropna(inplace = True)
    bl.loc[:, 'MAPE'] = np.round(bl.loc[:, 'diff']/ bl.loc[:, 'sales_dollars'], 4) * 100
    bl.loc[:, 'BIAS'] = np.round((bl.loc[:,'predicted_sales']- bl.loc[:, 'sales_dollars'])/ bl.loc[:, 'sales_dollars'], 4) * 100

    fig1 = go.Figure(data=[
    go.Bar( name='MAPE', x=bl['glbl_bus_ln_desc'], y=bl['MAPE']),
    go.Bar(name='BIAS', x=bl['glbl_bus_ln_desc'], y=bl['BIAS'])
    ])
    fig1.update_layout(barmode='group', plot_bgcolor='rgb(0,0,0)',
                        title=go.layout.Title(
                            text=f"{location} MAPE AND BIAS",
                            font=dict(
                family="Courier New, monospace",
                size=22,
                color="#111111"
            )))

    return fig1

#CONTROL THE BL TABLE
@callback(
    Output('bl_table', 'data'),
    Output('bl_table', 'columns'),
    Input('location_dropdown', 'value'),
    Input('model_dropdown', 'value')
    #look up ignore initial
    #look up design kit
)
def filter_table_bl(location, model_type):
    if location == 'home_delivery':
        df1 = df_final[(df_final['location_type']=='home_delivery') & (df_final['model'] == model_type)].copy()
    else:
        df1 = df_final[(df_final['location_type']=='shop_sales') & (df_final['model'] == model_type)].copy()
    

    bl = df1.groupby(['location_type', 'glbl_bus_ln_desc']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    bl.replace([np.inf, -np.inf], np.nan, inplace=True)
    bl['sales_dollars'] = np.round(bl['sales_dollars'])
    bl.loc[:, 'sales_pct'] = bl['sales_dollars']/bl['sales_dollars'].sum()
    bl['predictions'] = np.round(bl['predictions'])
    bl.dropna(inplace = True)
    bl.loc[:, 'MAPE'] = bl.loc[:, 'diff']/ bl.loc[:, 'sales_dollars']
    bl.loc[:, 'MAPE_CONTRIBUTION'] = bl.loc[:, 'sales_pct']*bl.loc[:, 'MAPE']/(bl.loc[:, 'sales_pct']*bl.loc[:, 'MAPE']).sum()
    bl.loc[:, 'BIAS'] = np.round((bl.loc[:,'predicted_sales']- bl.loc[:, 'sales_dollars'])/ bl.loc[:, 'sales_dollars'], 4)
    bl.loc[:, 'BIAS_CONTRIBUTION'] = bl.loc[:, 'sales_pct']*bl.loc[:, 'BIAS']/(bl.loc[:, 'sales_pct']*bl.loc[:, 'BIAS']).sum()
    bl = bl[['location_type','glbl_bus_ln_desc', 'sales_dollars', 'sales_pct', 'MAPE', 'MAPE_CONTRIBUTION', 'BIAS', 'BIAS_CONTRIBUTION']]

    return bl.to_dict('records'), [{'id':c, 'name':c, 'type':'numeric', 'format': money} if c in money_cols else {'id':c, 'name':c, 'type':'numeric', 'format':percentage}  if c in percentage_cols
    else {'id':c, 'name':c} for c in bl.columns ]

@callback(
    Output('cat_table', 'data'),
    Output('cat_table', 'columns'),
    Input('location_dropdown', 'value'),
    Input('bl_table', 'active_cell'),
    State('bl_table', 'data')
    #look up ignore initial
    #look up design kit
)
def filter_table_cat(location, active_cell, state_):
    state_  = pd.DataFrame(state_)
    print(state_)
    cat = df.groupby(['location_type', 'glbl_bus_ln_desc', 'glbl_ctgry_desc']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    
    if ctx.triggered_id == 'location_dropdown':
        filtered_df = cat[cat['location_type'] == location]
    elif ctx.triggered_id == 'bl_table':
        filtered_df = cat[(cat['glbl_bus_ln_desc'] == state_.iloc[active_cell['row'], active_cell['column']]) &
                                        (cat['location_type'] == location)]
        print(active_cell)

    else:
        filtered_df = cat

    filtered_df.replace([np.inf, -np.inf], np.nan, inplace=True)
    filtered_df['sales_dollars'] = np.round(filtered_df['sales_dollars'])
    filtered_df['sales_pct'] = filtered_df.loc[:, 'sales_dollars']/filtered_df['sales_dollars'].sum()
    filtered_df.loc[:, 'MAPE'] = np.round(filtered_df.loc[:, 'diff']/ filtered_df.loc[:, 'sales_dollars'],4)
    filtered_df.loc[:, 'MAPE_CONTRIBUTION'] = filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']/(filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']).sum()
    filtered_df.loc[:, 'BIAS'] = np.round((filtered_df.loc[:,'predicted_sales']- filtered_df.loc[:, 'sales_dollars'])/ filtered_df.loc[:, 'sales_dollars'], 4)
    filtered_df.loc[:, 'BIAS_CONTRIBUTION'] = filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']/(filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']).sum()
    bl_category_table = filtered_df[['location_type','glbl_bus_ln_desc','glbl_ctgry_desc', 'sales_dollars', 'sales_pct', 'MAPE', 'MAPE_CONTRIBUTION', 'BIAS', 'BIAS_CONTRIBUTION']]


    data = filtered_df.to_dict('records')
    
    return data, [{'id':c, 'name':c, 'type':'numeric', 'format': money} if c in money_cols else {'id':c, 'name':c, 'type':'numeric', 'format':percentage}  if c in percentage_cols
    else {'id':c, 'name':c} for c in bl_category_table.columns ]

@callback(
    Output('subcat_table', 'data'),
    Output('subcat_table', 'columns'),
    Input('location_dropdown', 'value'),
    Input('cat_table', 'active_cell'),
    State('cat_table', 'data')
    #look up ignore initial
    #look up design kit
)
def filter_table_subcat(location, active_cell, state_):
    state_ = pd.DataFrame(state_)
    subcat = df.groupby(['location_type', 'glbl_bus_ln_desc', 'glbl_ctgry_desc', 'glbl_sub_ctgry_desc']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    
    if ctx.triggered_id == 'location_dropdown':
        filtered_df = subcat[subcat['location_type'] == location]
    elif ctx.triggered_id == 'cat_table':
        filtered_df = subcat[(subcat['glbl_ctgry_desc'] == state_.iloc[active_cell['row'], active_cell['column']]) &
                                        (subcat['location_type'] == location)]
        print(active_cell)
        print(subcat[subcat['glbl_ctgry_desc'] == state_.iloc[active_cell['row'], active_cell['column']]])
    else:
        filtered_df = subcat

    filtered_df.replace([np.inf, -np.inf], np.nan, inplace=True)
    filtered_df['sales_pct'] = filtered_df['sales_dollars']/filtered_df['sales_dollars'].sum()
    filtered_df.loc[:, 'MAPE'] = np.round(filtered_df.loc[:, 'diff']/ filtered_df.loc[:, 'sales_dollars'],4)
    filtered_df.loc[:, 'MAPE_CONTRIBUTION'] = filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']
    filtered_df.loc[:, 'BIAS'] = np.round((filtered_df.loc[:,'predicted_sales']- filtered_df.loc[:, 'sales_dollars'])/ filtered_df.loc[:, 'sales_dollars'], 4)
    filtered_df.loc[:, 'BIAS_CONTRIBUTION'] = filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']/(filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']).sum()
    filtered_df.loc[:, 'MAPE_CONTRIBUTION'] = filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']/(filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']).sum()
    bl_subcategory_table = filtered_df[['location_type','glbl_bus_ln_desc', 'glbl_ctgry_desc', 'glbl_sub_ctgry_desc', 'sales_dollars', 'sales_pct', 'MAPE', 'MAPE_CONTRIBUTION', 'BIAS',
    'BIAS_CONTRIBUTION']]
    
    data = filtered_df.to_dict('records')
        
    return data, [{'id':c, 'name':c, 'type':'numeric', 'format': money} if c in money_cols else {'id':c, 'name':c, 'type':'numeric', 'format':percentage}  if c in percentage_cols
    else {'id':c, 'name':c} for c in bl_subcategory_table.columns ]

@callback(
    Output('item_table', 'data'),
    Output('item_table', 'columns'),
    Input('location_dropdown', 'value'),
    Input('subcat_table', 'active_cell'),
    State('subcat_table', 'data')
    #look up ignore initial
    #look up design kit
)
def filter_table_item(location, active_cell, state_):
    state_ = pd.DataFrame(state_)
    item = df.groupby(['location_type', 'glbl_bus_ln_desc', 'glbl_ctgry_desc', 'glbl_sub_ctgry_desc', 'item_desc', 'ord_base7']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    
    if ctx.triggered_id == 'location_dropdown':
        filtered_df = item[item['location_type'] == location]
    elif ctx.triggered_id == 'subcat_table':
        filtered_df = item[(item['glbl_sub_ctgry_desc'] == state_.iloc[active_cell['row'], active_cell['column']]) &
                                        (item['location_type'] == location)]
        print(active_cell)
        print(item[item['glbl_ctgry_desc'] == state_.iloc[active_cell['row'], active_cell['column']]])
    else:
        filtered_df = item
    filtered_df.replace([np.inf, -np.inf], np.nan, inplace=True)
    filtered_df['sales_dollars'] = np.round(filtered_df['sales_dollars'])
    filtered_df['sales_pct'] = filtered_df['sales_dollars']/filtered_df['sales_dollars'].sum()
    filtered_df.loc[:, 'MAPE'] = np.round(filtered_df.loc[:, 'diff']/ filtered_df.loc[:, 'sales_dollars'],4)
    filtered_df.loc[:, 'MAPE_CONTRIBUTION'] = filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']/(filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']).sum()
    filtered_df.loc[:, 'BIAS'] = np.round((filtered_df.loc[:,'predicted_sales']- filtered_df.loc[:, 'sales_dollars'])/ filtered_df.loc[:, 'sales_dollars'], 4)
    filtered_df.loc[:, 'BIAS_CONTRIBUTION'] = filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']/(filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']).sum()
    bl_item_table = filtered_df[['location_type','glbl_bus_ln_desc', 'glbl_ctgry_desc', 'glbl_sub_ctgry_desc', 'item_desc', 'ord_base7', 'sales_dollars', 'sales_pct',
     'MAPE', 'MAPE_CONTRIBUTION', 'BIAS', 'BIAS_CONTRIBUTION']]

    data = filtered_df.to_dict('records')
    
    return data, [{'id':c, 'name':c, 'type':'numeric', 'format': money} if c in money_cols else {'id':c, 'name':c, 'type':'numeric', 'format':percentage}  if c in percentage_cols
    else {'id':c, 'name':c} for c in bl_item_table.columns ]

And below that is code for my item page, where the first drop down is the dropdown I want the value to be equal to the item clicked on the previous page:

layout = ddk.App(show_editor=True, children = [
    ddk.Header([
        # ddk.Logo(src=app.get_relative_path('/assets/logo.png')),
        ddk.Title('Demand Forecasting Item Details'),
    ]),
    ddk.DataCard(
                        id='II',
                        label="The individual item page will display how a model performed through time at both the shop and home delivery location type.  Sale variation by MAPE, TNA & promotion through time as well as BIAS distributions are also displayed.",
                        value='Individual Item Page',
                    ),
    ddk.Block(
        #width = 99,
        children=[
            ddk.ControlCard(
                [ddk.CardHeader(title="Item/Snapshot Dropdown"),
                ddk.ControlItem(children = [
        dcc.Dropdown(
            options = [{'label':i, 'value':i}
                 for i in items
                 ],
                multi=False,
                value = '100188K',
                id='item_dropdown',
        ),
        dcc.Dropdown(
            options = [{'label':i, 'value':i}
                 for i in snapshot
                 ],
                multi=False,
                value = '2021-01-31',
                id='snapshot_dropdown',
        ),
                ]
    )]
            ),
            ddk.Card(
                width=100,
                children =[
        ddk.Graph(
            id='snapshot_timeseries'
        ),
                ]),
        ddk.Card(
            width=100,
            children=[
        ddk.Graph(
            id='snapshot_timeseries_bias'
        ),
                ]),
        ddk.Card(
            width = 100,
            children=[
        ddk.Graph(
            id='timeseries'
            )
            ]),
        ddk.Card(
                width=100,
                children =[
        ddk.Graph(
            id='timeseries2'
            )
            ]),
        ddk.Card(
            width=100,
            children=[
                ddk.Graph(
                    id='tna_figure'
                )
            ]),
         ddk.Card(
            width=100,
            children=[
                ddk.Graph(
                    id='promo_figure'
                )
            ]),   
        ]),
    ddk.Block(
        #width = 99,
        children=[
            ddk.Card(
                width=100,
                children=[dbc.Label('Forecaster Notes'),
                ddk.DataTable(id="notes_table",
                            columns=[],
                            data=[],
                            filter_action = 'native',
                            sort_action = 'native')
                    ])
        ]),
    ddk.Block(
        width = 50, 
        children = [
            ddk.Card(
                width=100,
                children =[
            ddk.Graph(
                id='CoV'
        ),
    ]),
        ]
    ),
    ddk.Block(
        width = 50,
        children = [
            ddk.Card(width = 100,
            children = [
            ddk.Graph(
                id='BIAS'
        ),
            ])
        ]
    )
])

#CONTROL THE Time Series GRAPH
@callback(
    dash.dependencies.Output('snapshot_timeseries', 'figure'),
    dash.dependencies.Input('item_dropdown', 'value'),
)
def time_series_show_snapshot(item):
    df_table = df_final[df_final['ord_base7']==item].groupby(['ord_base7', 'item_desc','model', 'snapshot']).agg({'diff':'sum',
    'predicted_sales':'sum', 'sales_dollars':'sum'}).reset_index()
    df_table.loc[:, 'MAPE'] = np.round(df_table.loc[:, 'diff']/ df_table.loc[:, 'sales_dollars'], 4)
    df_table.loc[:, 'ACCURACY'] = 1 - df_table.loc[:,'MAPE']
    df_table.loc[:, 'BIAS'] = np.round((df_table.loc[:,'predicted_sales']- df_table.loc[:, 'sales_dollars'])/ df_table.loc[:, 'sales_dollars'], 4)
    # print("Data for time series", df_[['dmand_yr_mo', 'ord_base7', 'snapshot', 'model', 'location_type', 'sales_dollars']].sort_values('dmand_yr_mo'))
    
    fig = px.bar(df_table, x="snapshot", y="MAPE", 
                 color="model", barmode="group", title = "MAPE by Snapshot")
    return fig
#CONTROL THE Time Series GRAPH
@callback(
    dash.dependencies.Output('snapshot_timeseries_bias', 'figure'),
    dash.dependencies.Input('item_dropdown', 'value'),
)
def time_series_show_snapshot_bias(item):
    df_table = df_final[df_final['ord_base7']==item].groupby(['ord_base7', 'item_desc','model', 'snapshot']).agg({'diff':'sum',
    'predicted_sales':'sum', 'sales_dollars':'sum'}).reset_index()
    df_table.loc[:, 'MAPE'] = np.round(df_table.loc[:, 'diff']/ df_table.loc[:, 'sales_dollars'], 4)
    df_table.loc[:, 'ACCURACY'] = 1 - df_table.loc[:,'MAPE']
    df_table.loc[:, 'BIAS'] = np.round((df_table.loc[:,'predicted_sales']- df_table.loc[:, 'sales_dollars'])/ df_table.loc[:, 'sales_dollars'], 4)
    # print("Data for time series", df_[['dmand_yr_mo', 'ord_base7', 'snapshot', 'model', 'location_type', 'sales_dollars']].sort_values('dmand_yr_mo'))
    
    fig = px.bar(df_table, x="snapshot", y="BIAS", 
                 color="model", barmode="group", title = "BIAS by Snapshot")
    return fig
    
#CONTROL THE Time Series GRAPH
@callback(
    dash.dependencies.Output('timeseries', 'figure'),
    dash.dependencies.Input('item_dropdown', 'value'),
    dash.dependencies.Input('snapshot_dropdown', 'value'),
)
def time_series_show_hd(item, snapshot):
    df_ = df_final[(df_final['ord_base7']==item) & (df_final['snapshot'] == snapshot) & (df_final['location_type'] == "home_delivery")].sort_values('dmand_yr_mo').copy()
    # print("Data for time series", df_[['dmand_yr_mo', 'ord_base7', 'snapshot', 'model', 'location_type', 'sales_dollars']].sort_values('dmand_yr_mo'))
    
    fig = px.scatter(df_, x = 'dmand_yr_mo', y = 'predicted_sales', color = 'model')
    
    fig1 = px.line(df_[(df_['model'] == 'base_model') & (df_['location_type'] == 'home_delivery')], x = 'dmand_yr_mo', y = 'sales_dollars')

    fig3 = go.Figure(data=fig.data + fig1.data)
    
    fig3.update_layout(hovermode="x unified", title = "Actual (line) vs Predicted (points) Sales @ Home Delivery")

    return fig3

@callback(
    dash.dependencies.Output('timeseries2', 'figure'),
    dash.dependencies.Input('item_dropdown', 'value'),
    dash.dependencies.Input('snapshot_dropdown', 'value'),
)
def time_series_show_ss(item, snapshot):
    df_ = df_final[(df_final['ord_base7']==item) & (df_final['snapshot'] == snapshot) & (df_final['location_type'] != "home_delivery")].sort_values('dmand_yr_mo').copy()
    # print("Data for time series", df_[['dmand_yr_mo', 'ord_base7', 'snapshot', 'model', 'location_type', 'sales_dollars']].sort_values('dmand_yr_mo'))
    
    fig = px.scatter(df_, x = 'dmand_yr_mo', y = 'predicted_sales', color = 'model')
    
    fig1 = px.line(df_[(df_['model'] == 'base_model')  & (df_['location_type'] != 'home_delivery')], x = 'dmand_yr_mo', y = 'sales_dollars')

    fig3 = go.Figure(data=fig.data + fig1.data)
    
    fig3.update_layout(hovermode="x unified", title = "Actual (line) vs Predicted (points) Sales @ Shop Sales")

    return fig3

@callback(
    dash.dependencies.Output('tna_figure', 'figure'),
    dash.dependencies.Input('item_dropdown', 'value'),
    dash.dependencies.Input('snapshot_dropdown', 'value'),
)
def tna_show(item, snapshot):
    df_ = df_final[(df_final['ord_base7']==item) & (df_final['snapshot'] == snapshot)].sort_values('dmand_yr_mo').copy()
    
    # print("Data for time series", df_[['dmand_yr_mo', 'ord_base7', 'snapshot', 'model', 'location_type', 'sales_dollars']].sort_values('dmand_yr_mo'))
    
    fig = px.scatter(df_, x='dmand_yr_mo', y='adj_tna_daily', color = 'location_type',
    title="Time Series Look - TNA")


    return fig
@callback(
    dash.dependencies.Output('promo_figure', 'figure'),
    dash.dependencies.Input('item_dropdown', 'value'),
    dash.dependencies.Input('snapshot_dropdown', 'value')
)
def tna_show(item, snapshot):
    df_ = df_final[(df_final['ord_base7']==item) & (df_final['snapshot'] == snapshot)].sort_values('dmand_yr_mo').copy()
    # print("Data for time series", df_[['dmand_yr_mo', 'ord_base7', 'snapshot', 'model', 'location_type', 'sales_dollars']].sort_values('dmand_yr_mo'))
    df_.loc[:, 'cannibalized'] = df_.loc[:, 'cannibalized'].astype('str')
    fig = px.scatter(df_, x='dmand_yr_mo', y='promo_status_metric_measure', color = 'cannibalized',
    title="Time Series Look - Promotion Occurence")


    return fig

#Control BIAS graph
@callback(
    dash.dependencies.Output('BIAS', 'figure'),
    dash.dependencies.Input('item_dropdown', 'value'),
    # dash.dependencies.Input('snapshot_dropdown', 'value')
)
def cov_show(item):
    df_ = df_final[(df_final['ord_base7']==item)]
    df_['diff'] = np.round((np.round(df_.loc[:, 'predicted_sales'] - df_.loc[:, 'sales_dollars'],2)))
    df_['BIAS'] = (df_.loc[:, 'diff']/df_.loc[:, 'sales_dollars'])

    fig = px.histogram(df_, x = 'BIAS', color = 'location_type', title=item + " BIAS by Location Type", )

    return fig

#Control CoV graph
@callback(
    dash.dependencies.Output('CoV', 'figure'),
    dash.dependencies.Input('item_dropdown', 'value'),
    # dash.dependencies.Input('snapshot_dropdown', 'value')
)
def cov_show(item):
    df1 = df_final.copy()
    df1_group = df1[df1['month_offset']==6].groupby(['ord_base7', 'location_type']).agg(sum_sales = ('sales_dollars','sum'),
                                                                       std_sales = ('sales_dollars', 'std'),
                                                                       mean_sales = ('sales_dollars', 'mean'),
                                                                       sum_predictioned_sales = ('predicted_sales', 'sum')).reset_index()
    df1_group['CoV'] = df1_group.loc[:, 'std_sales']/df1_group.loc[:, 'mean_sales']
    df1_group['diff'] = np.round(np.abs(np.round(df1_group.loc[:, 'sum_predictioned_sales'] - df1_group.loc[:, 'sum_sales'],2)))
    df1_group['MAPE'] = (df1_group.loc[:, 'diff']/df1_group.loc[:, 'sum_sales'])

    fig = px.scatter(df1_group, x='CoV', y='MAPE', color = 'location_type',
    title="MAPE v. Sales Variation @ Six Month Offset - Based on Dollars")
    fig.update_layout(yaxis_range=[0, 2])
    fig.add_trace(go.Scatter(x=df1_group[df1_group['ord_base7'] == item]['CoV'], 
                             y=df1_group[df1_group['ord_base7'] == item]['MAPE'], mode = 'markers',
                             marker_symbol = 'star', marker_size = 15, name = item,))
    fig.add_hline(y=0.2)
    fig.add_vline(x=df1_group['CoV'].mean())

    return fig

@callback(
dash.dependencies.Output('notes_table', 'data'),
dash.dependencies.Output('notes_table', 'columns'),
dash.dependencies.Input('item_dropdown', 'value')
)
def get_notes(item):
    df_ = df_notes[df_notes['ITEM_NO']==item]

    return df_.to_dict('records'), [{"name": i, "id": i} for i in df_.columns]

Is this possible? I looked at using dcc.Store from here ( Store | Dash for Python Documentation | Plotly but the examples do not translate well (at least for me) to my problem set.

Hello @jbh1128d1,

Yes, this is definitely possible, however, I think opening up a modal would be more user friendly and also easier to implement.

Opening up a modal would allow you to easily access all the previous data on the page, as well as allow the user to navigate back easily if they accidentally clicked on the last option. I would say either a full screen modal or an xl will work.

I’ve never heard of this. What is a modal?

Jordan

It’s like a pop out, take a look here:

https://dash-bootstrap-components.opensource.faculty.ai/docs/components/modal/

1 Like

If you need more inspiration, I created some generic examples with modals lately:

https://community.plotly.com/search?q=%40aimped%20modal

3 Likes

Thank you. I tried to start by copying direct from the docs.

These lines are throwing an error

def toggle_modal(n1, n2, is_open):
    if n1 or n2:
        return not is_open
    return is_open


@callback(
    Output("modal-scroll", "is_open"),
    [Input("open-scroll", "n_clicks"), Input("close-scroll", "n_clicks")],
    [State("modal-scroll", "is_open")],
)(toggle_modal)

@callback(
    Output("modal-body-scroll", "is_open"),
    [
        Input("open-body-scroll", "n_clicks"),
        Input("close-body-scroll", "n_clicks"),
    ],
    [State("modal-body-scroll", "is_open")],
)(toggle_modal)

Here is the error:

raceback (most recent call last):
  File "/root/workspace/app.py", line 31, in <module>
    app = Dash(__name__, use_pages=True)
  File "/app/.heroku/python/lib/python3.7/site-packages/dash/dash.py", line 494, in __init__
    self.init_app()
  File "/app/.heroku/python/lib/python3.7/site-packages/dash/dash.py", line 578, in init_app
    self.enable_pages()
  File "/app/.heroku/python/lib/python3.7/site-packages/dash/dash.py", line 2044, in enable_pages
    self._import_layouts_from_pages()
  File "/app/.heroku/python/lib/python3.7/site-packages/dash/dash.py", line 2016, in _import_layouts_from_pages
    spec.loader.exec_module(page_module)
  File "<frozen importlib._bootstrap_external>", line 724, in exec_module
  File "<frozen importlib._bootstrap_external>", line 860, in get_code
  File "<frozen importlib._bootstrap_external>", line 791, in source_to_code
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/root/workspace/pages/hierarchy_walk.py", line 483
    (toggle_modal)

Has this changed since the docs were published.

Hello @jbh1128d1,

If you are wanting to repeat the same function, you can do this instead:

@callback(
    Output("modal-scroll", "is_open"),
    [Input("open-scroll", "n_clicks"), Input("close-scroll", "n_clicks")],
    [State("modal-scroll", "is_open")],
)

@callback(
    Output("modal-body-scroll", "is_open"),
    [
        Input("open-body-scroll", "n_clicks"),
        Input("close-body-scroll", "n_clicks"),
    ],
    [State("modal-body-scroll", "is_open")],
)

def toggle_modal(n1, n2, is_open):
    if n1 or n2:
        return not is_open
    return is_open

Thank you. I’m slowly getting this thing to work.

I have two questions:

  1. How do I get the modal to be full screen? I copied the documents and added fullscreen=True. I copied just the modal code from my app below.

Here is currently what it looks like even with fullscreen=True.

    [
        dbc.Button(
            "Modal with scrollable body", id="open-body-scroll", n_clicks=0
        ),
        dbc.Modal(
            [
                dbc.ModalHeader(dbc.ModalTitle("Demand Forecasting Item Details")),
                dbc.ModalBody(children = [
                    ddk.Block(
        #width = 99,
        children=[
            ddk.ControlCard(
                [ddk.CardHeader(title="Item/Snapshot Dropdown"),
                ddk.ControlItem(children = [
        dcc.Dropdown(
            options = [{'label':i, 'value':i}
                 for i in items
                 ],
                multi=False,
                value = '100188K',
                id='item_dropdown_modal',
        ),
        dcc.Dropdown(
            options = [{'label':i, 'value':i}
                 for i in snapshot
                 ],
                multi=False,
                value = '2021-01-31',
                id='snapshot_dropdown_modal',
        ),
                ]
    )]
            ),
            ddk.Card(
                width=100,
                children =[
        ddk.Graph(
            id='snapshot_timeseries_modal'
        ),
                ]),
        ddk.Card(
            width=100,
            children=[
        ddk.Graph(
            id='snapshot_timeseries_bias_modal'
        ),
                ]),
        ddk.Card(
            width = 100,
            children=[
        ddk.Graph(
            id='timeseries_modal'
            )
            ]),
        ddk.Card(
                width=100,
                children =[
        ddk.Graph(
            id='timeseries2_modal'
            )
            ]),
        ddk.Card(
            width=100,
            children=[
                ddk.Graph(
                    id='tna_figure_modal'
                )
            ]),
         ddk.Card(
            width=100,
            children=[
                ddk.Graph(
                    id='promo_figure_modal'
                )
            ]),   
        ]),
        ddk.Block(
        width = 50, 
        children = [
            ddk.Card(
                width=100,
                children =[
            ddk.Graph(
                id='CoV_modal'
        ),
    ]),
        ]
    ),
    ddk.Block(
        width = 50,
        children = [
            ddk.Card(width = 100,
            children = [
            ddk.Graph(
                id='BIAS_modal'
        ),
            ])
        ]
    )
                ]),
                dbc.ModalFooter(
                    dbc.Button(
                        "Close",
                        id="close-body-scroll",
                        className="ms-auto",
                        n_clicks=0,
                    )
                ),
            ],
            id="modal-body-scroll",
            fullscreen=True,
            scrollable=True,
            is_open=False,
        ),
    ]
)

2nd Question. How do I change the action button from the button itself to an observation clicked in a datatable above?

1 Like

Looks good.

Scrollable I think shouldn’t be provided, I’m wondering if that might be causing an issue.

As far as fire it from the last table’s cellClicked event.

I took out scrollable, and I also tried fullscreen = 'xxl-down' according to the docs. I also tried fullscreen=<xxl>-down" in case the “<>” were required.

fullscreen=True

Should have taken care of it.

Question, have you refreshed the entire page after removing the scrollable?

Yes. I’ve refreshed mulitple times with each change I’ve tried.

1 Like

Hello @jbh1128d1,

I noticed that you are using ddk, just to make sure, are you importing the dbc themes as well?

If so, make sure that this example works for you:

import dash_bootstrap_components as dbc
from dash import Input, Output, State, html, Dash

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

modal = html.Div(
    [
        dbc.Button("Open modal", id="open-fs"),
        dbc.Modal(
            [
                dbc.ModalHeader(dbc.ModalTitle("Fullscreen modal")),
                dbc.ModalBody("Wow this thing takes up a lot of space..."),
            ],
            id="modal-fs",
            fullscreen=True,
        ),
    ]
)

app.layout = modal


@app.callback(
    Output("modal-fs", "is_open"),
    Input("open-fs", "n_clicks"),
    State("modal-fs", "is_open"),
)
def toggle_modal(n, is_open):
    if n:
        return not is_open
    return is_open

app.run()

If it works, then try stepping back and just make sure that you can get a basic fullscreen modal to display.

This works however, I’m not sure the difference. Should I have my modal defined outside of my layout and then bring it inside of my layout via an object name? I have the external_stylesheets=[dbc.themes.BOOTSTRAP] inside the app.

Nope, you shouldnt need to do that.

I recommend taking everything out of the body and make you can get the fullscreen modal to show, once you get that working, start adding in the other stuff.

I took everything out. Still no full screen. Below is the entire layout code in case there is something I’m missing.

layout = ddk.App(show_editor=True, children = [
    ddk.Block(
        #width = 99,
        children=[
        ddk.DataCard(
                        id='HW',
                        label="The hierarchy walk page allows a user to discover what business line, category, sub-category and item is driving the MAPE or BIAS. Each level of the hierarchy can be filtered by the the level above.",
                        value='Hierarchy Walk Page',
                    ),
            ddk.ControlCard(
                [
                ddk.ControlItem(children=[
        dcc.Dropdown(
            options = [{'label':i, 'value':i}
                 for i in ['home_delivery', 'shop_sales']
                 ],
                multi=False,
                value = 'home_delivery',
                id='location_dropdown',
        ),
        dcc.Dropdown(
            options = [{'label':i, 'value':i}
                for i in model
                ],
                multi=False,
                value = 'stats_model',
                id='model_dropdown'
        )
                ],
    )]
            ),
            ddk.Card(children =[
        ddk.Graph(
            id='Business_Line_modal'
        )
    ]),
        ]
    ),
    ddk.Block(
            width = 100,
            children=[
                # ddk.CardHeader(title="Forecast Data Tables"),
                ddk.Card(
                    width=100,
                    children=[ddk.DataTable(id="bl_table",
                            columns=[],
                            data=[],
                            filter_action = 'native',
                            sort_action = 'native')
                    ]
                    ),
                ddk.Card(
                    width=100,
                    children=[
                        ddk.DataTable(id='cat_table',
                        columns = [],
                        data = [],
                        filter_action = 'native',
                        sort_action = 'native',)
                    ]
                ),
                ddk.Card(
                    width=100,
                    children=[
                        ddk.DataTable(id='subcat_table',
                        columns = [],
                        data = [],
                        filter_action = 'native',
                        sort_action = 'native',
                ),
                    ]
                ),
                ddk.Card(
                    width=100,
                    children=[
                        ddk.DataTable(id='item_table',
                        columns = [],
                        data = [],
                        filter_action = 'native',
                        sort_action = 'native',
                ),
                    ]
                )
            ]
    ),
    html.Div(
    [
        dbc.Modal(
            [
                dbc.ModalHeader(dbc.ModalTitle("Demand Forecasting Item Details")),
                dbc.ModalBody(children = [
                ]),
                dbc.ModalFooter(
                    dbc.Button(
                        "Close",
                        id="close-body-scroll",
                        className="ms-auto",
                        n_clicks=0,
                    )
                ),
            ],
            id="modal_",
            fullscreen=True,
        ),
    ]
)
]
)

#CONTROL THE BUSINESS LINE GRAPH
@callback(
    dash.dependencies.Output('Business_Line_modal', 'figure'),
    dash.dependencies.Input('model_dropdown', 'value'),
    dash.dependencies.Input('location_dropdown', 'value'),
)
def update_bl(model, location):
    df1 = df_final[(df_final['location_type'] == location) & (df_final['model'] == model)]

    bl = df1.groupby(['glbl_bus_ln_desc']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    bl.replace([np.inf, -np.inf], np.nan, inplace=True)
    bl['sales_dollars'] = np.round(bl['sales_dollars'])
    bl['predictions'] = np.round(bl['predictions'])
    bl.dropna(inplace = True)
    bl.loc[:, 'MAPE'] = np.round(bl.loc[:, 'diff']/ bl.loc[:, 'sales_dollars'], 4) * 100
    bl.loc[:, 'BIAS'] = np.round((bl.loc[:,'predicted_sales']- bl.loc[:, 'sales_dollars'])/ bl.loc[:, 'sales_dollars'], 4) * 100

    fig1 = go.Figure(data=[
    go.Bar( name='MAPE', x=bl['glbl_bus_ln_desc'], y=bl['MAPE']),
    go.Bar(name='BIAS', x=bl['glbl_bus_ln_desc'], y=bl['BIAS'])
    ])
    fig1.update_layout(barmode='group', plot_bgcolor='rgb(0,0,0)',
                        title=go.layout.Title(
                            text=f"{location} MAPE AND BIAS",
                            font=dict(
                family="Courier New, monospace",
                size=22,
                color="#111111"
            )))

    return fig1

#CONTROL THE BL TABLE
@callback(
    Output('bl_table', 'data'),
    Output('bl_table', 'columns'),
    Input('location_dropdown', 'value'),
    Input('model_dropdown', 'value')
    #look up ignore initial
    #look up design kit
)
def filter_table_bl(location, model_type):
    if location == 'home_delivery':
        df1 = df_final[(df_final['location_type']=='home_delivery') & (df_final['model'] == model_type)].copy()
    else:
        df1 = df_final[(df_final['location_type']=='shop_sales') & (df_final['model'] == model_type)].copy()
    

    bl = df1.groupby(['location_type', 'glbl_bus_ln_desc']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    bl.replace([np.inf, -np.inf], np.nan, inplace=True)
    bl['sales_dollars'] = np.round(bl['sales_dollars'])
    bl.loc[:, 'sales_pct'] = bl['sales_dollars']/bl['sales_dollars'].sum()
    bl['predictions'] = np.round(bl['predictions'])
    bl.dropna(inplace = True)
    bl.loc[:, 'MAPE'] = bl.loc[:, 'diff']/ bl.loc[:, 'sales_dollars']
    bl.loc[:, 'MAPE_CONTRIBUTION'] = bl.loc[:, 'sales_pct']*bl.loc[:, 'MAPE']/(bl.loc[:, 'sales_pct']*bl.loc[:, 'MAPE']).sum()
    bl.loc[:, 'BIAS'] = np.round((bl.loc[:,'predicted_sales']- bl.loc[:, 'sales_dollars'])/ bl.loc[:, 'sales_dollars'], 4)
    bl.loc[:, 'BIAS_CONTRIBUTION'] = bl.loc[:, 'sales_pct']*bl.loc[:, 'BIAS']/(bl.loc[:, 'sales_pct']*bl.loc[:, 'BIAS']).sum()
    bl = bl[['location_type','glbl_bus_ln_desc', 'sales_dollars', 'sales_pct', 'MAPE', 'MAPE_CONTRIBUTION', 'BIAS', 'BIAS_CONTRIBUTION']]

    return bl.to_dict('records'), [{'id':c, 'name':c, 'type':'numeric', 'format': money} if c in money_cols else {'id':c, 'name':c, 'type':'numeric', 'format':percentage}  if c in percentage_cols
    else {'id':c, 'name':c} for c in bl.columns ]

@callback(
    Output('cat_table', 'data'),
    Output('cat_table', 'columns'),
    Input('location_dropdown', 'value'),
    Input('bl_table', 'active_cell'),
    State('bl_table', 'data')
    #look up ignore initial
    #look up design kit
)
def filter_table_cat(location, active_cell, state_):
    state_  = pd.DataFrame(state_)
    print(state_)
    cat = df.groupby(['location_type', 'glbl_bus_ln_desc', 'glbl_ctgry_desc']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    
    if ctx.triggered_id == 'location_dropdown':
        filtered_df = cat[cat['location_type'] == location]
    elif ctx.triggered_id == 'bl_table':
        filtered_df = cat[(cat['glbl_bus_ln_desc'] == state_.iloc[active_cell['row'], active_cell['column']]) &
                                        (cat['location_type'] == location)]
        print(active_cell)

    else:
        filtered_df = cat

    filtered_df.replace([np.inf, -np.inf], np.nan, inplace=True)
    filtered_df['sales_dollars'] = np.round(filtered_df['sales_dollars'])
    filtered_df['sales_pct'] = filtered_df.loc[:, 'sales_dollars']/filtered_df['sales_dollars'].sum()
    filtered_df.loc[:, 'MAPE'] = np.round(filtered_df.loc[:, 'diff']/ filtered_df.loc[:, 'sales_dollars'],4)
    filtered_df.loc[:, 'MAPE_CONTRIBUTION'] = filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']/(filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']).sum()
    filtered_df.loc[:, 'BIAS'] = np.round((filtered_df.loc[:,'predicted_sales']- filtered_df.loc[:, 'sales_dollars'])/ filtered_df.loc[:, 'sales_dollars'], 4)
    filtered_df.loc[:, 'BIAS_CONTRIBUTION'] = filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']/(filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']).sum()
    bl_category_table = filtered_df[['location_type','glbl_bus_ln_desc','glbl_ctgry_desc', 'sales_dollars', 'sales_pct', 'MAPE', 'MAPE_CONTRIBUTION', 'BIAS', 'BIAS_CONTRIBUTION']]


    data = filtered_df.to_dict('records')
    
    return data, [{'id':c, 'name':c, 'type':'numeric', 'format': money} if c in money_cols else {'id':c, 'name':c, 'type':'numeric', 'format':percentage}  if c in percentage_cols
    else {'id':c, 'name':c} for c in bl_category_table.columns ]

@callback(
    Output('subcat_table', 'data'),
    Output('subcat_table', 'columns'),
    Input('location_dropdown', 'value'),
    Input('cat_table', 'active_cell'),
    State('cat_table', 'data')
    #look up ignore initial
    #look up design kit
)
def filter_table_subcat(location, active_cell, state_):
    state_ = pd.DataFrame(state_)
    subcat = df.groupby(['location_type', 'glbl_bus_ln_desc', 'glbl_ctgry_desc', 'glbl_sub_ctgry_desc']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    
    if ctx.triggered_id == 'location_dropdown':
        filtered_df = subcat[subcat['location_type'] == location]
    elif ctx.triggered_id == 'cat_table':
        filtered_df = subcat[(subcat['glbl_ctgry_desc'] == state_.iloc[active_cell['row'], active_cell['column']]) &
                                        (subcat['location_type'] == location)]
        print(active_cell)
        print(subcat[subcat['glbl_ctgry_desc'] == state_.iloc[active_cell['row'], active_cell['column']]])
    else:
        filtered_df = subcat

    filtered_df.replace([np.inf, -np.inf], np.nan, inplace=True)
    filtered_df['sales_pct'] = filtered_df['sales_dollars']/filtered_df['sales_dollars'].sum()
    filtered_df.loc[:, 'MAPE'] = np.round(filtered_df.loc[:, 'diff']/ filtered_df.loc[:, 'sales_dollars'],4)
    filtered_df.loc[:, 'MAPE_CONTRIBUTION'] = filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']
    filtered_df.loc[:, 'BIAS'] = np.round((filtered_df.loc[:,'predicted_sales']- filtered_df.loc[:, 'sales_dollars'])/ filtered_df.loc[:, 'sales_dollars'], 4)
    filtered_df.loc[:, 'BIAS_CONTRIBUTION'] = filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']/(filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']).sum()
    filtered_df.loc[:, 'MAPE_CONTRIBUTION'] = filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']/(filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']).sum()
    bl_subcategory_table = filtered_df[['location_type','glbl_bus_ln_desc', 'glbl_ctgry_desc', 'glbl_sub_ctgry_desc', 'sales_dollars', 'sales_pct', 'MAPE', 'MAPE_CONTRIBUTION', 'BIAS',
    'BIAS_CONTRIBUTION']]
    
    data = filtered_df.to_dict('records')
        
    return data, [{'id':c, 'name':c, 'type':'numeric', 'format': money} if c in money_cols else {'id':c, 'name':c, 'type':'numeric', 'format':percentage}  if c in percentage_cols
    else {'id':c, 'name':c} for c in bl_subcategory_table.columns ]

@callback(
    Output('item_table', 'data'),
    Output('item_table', 'columns'),
    Input('location_dropdown', 'value'),
    Input('subcat_table', 'active_cell'),
    State('subcat_table', 'data')
    #look up ignore initial
    #look up design kit
)
def filter_table_item(location, active_cell, state_):
    state_ = pd.DataFrame(state_)
    item = df.groupby(['location_type', 'glbl_bus_ln_desc', 'glbl_ctgry_desc', 'glbl_sub_ctgry_desc', 'item_desc', 'ord_base7']).agg({'ord_qty':'sum',
                                    'predictions':'sum',
                                    'sales_dollars':'sum',
                                    'predicted_sales':'sum', 
                                    'diff':'sum'}).reset_index()
    
    if ctx.triggered_id == 'location_dropdown':
        filtered_df = item[item['location_type'] == location]
    elif ctx.triggered_id == 'subcat_table':
        filtered_df = item[(item['glbl_sub_ctgry_desc'] == state_.iloc[active_cell['row'], active_cell['column']]) &
                                        (item['location_type'] == location)]
        print(active_cell)
        print(item[item['glbl_ctgry_desc'] == state_.iloc[active_cell['row'], active_cell['column']]])
    else:
        filtered_df = item
    filtered_df.replace([np.inf, -np.inf], np.nan, inplace=True)
    filtered_df['sales_dollars'] = np.round(filtered_df['sales_dollars'])
    filtered_df['sales_pct'] = filtered_df['sales_dollars']/filtered_df['sales_dollars'].sum()
    filtered_df.loc[:, 'MAPE'] = np.round(filtered_df.loc[:, 'diff']/ filtered_df.loc[:, 'sales_dollars'],4)
    filtered_df.loc[:, 'MAPE_CONTRIBUTION'] = filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']/(filtered_df['sales_pct']*filtered_df.loc[:, 'MAPE']).sum()
    filtered_df.loc[:, 'BIAS'] = np.round((filtered_df.loc[:,'predicted_sales']- filtered_df.loc[:, 'sales_dollars'])/ filtered_df.loc[:, 'sales_dollars'], 4)
    filtered_df.loc[:, 'BIAS_CONTRIBUTION'] = filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']/(filtered_df.loc[:, 'sales_pct']*filtered_df.loc[:, 'BIAS']).sum()
    bl_item_table = filtered_df[['location_type','glbl_bus_ln_desc', 'glbl_ctgry_desc', 'glbl_sub_ctgry_desc', 'item_desc', 'ord_base7', 'sales_dollars', 'sales_pct',
     'MAPE', 'MAPE_CONTRIBUTION', 'BIAS', 'BIAS_CONTRIBUTION']]

    data = filtered_df.to_dict('records')
    
    return data, [{'id':c, 'name':c, 'type':'numeric', 'format': money} if c in money_cols else {'id':c, 'name':c, 'type':'numeric', 'format':percentage}  if c in percentage_cols
    else {'id':c, 'name':c} for c in bl_item_table.columns ]

@callback(
    Output("modal_", "is_open"),
    Input("item_table", "active_cell"),
    Input("close-body-scroll", "n_clicks"),
    State("modal_", "is_open"),
)

def toggle_modal(n1, n2, is_open):
    if n1 or n2:
        return not is_open
    return is_open

Hmm, maybe check with your plotly rep, I cant debug further. Everything looks like it should…

2 Likes

Just to close this out, it turns out from my plotly rep that using dbc modals with ddk does not work. Somewhere, they’re stepping on each other. A majority of the app is written using ddk so I’m going to swtich to the ddk.FullScreen function.

2 Likes

I thought that that may have been the case. At least you learned something new. :grin:

Hello! I just wanted to elaborate on why fullscreen= True doesn’t work.

DDK has its own style guide that interacts with DBC and that is why the modal isn’t fullscreen. If you run the code snippet from @jinnyzor it will open fullscreen, but if you add `import dash_design_kit as ddk’ with the other import statements, then it will reproduce your error and open to 1/3 size.

You can either:

  1. Turn off the DDK property that is messing up the fullscreen modal.
  2. Or, use a different combination of libraries to achieve the same effect.

Using the inspect tool in the browser, you can identify which property is supposed to determine modal width, and which property is actually determining modal width.
By creating an assets folder with a css file with the following:

.modal-dialog {
    max-width: unset !important;
    margin: unset !important;
}

This unsets the max-width and margin and lets that be dictated by the styling in DBC.

More information on adding a css file to your assets folder can be found in this doc.

Or, if you don’t need DBC for any other use, you can create a modal using DDK and have no styling override issues.

I hope that clears things up a bit.

Eliza :slight_smile:

3 Likes