Dash Ag-grid passing virtualRow data without visible grid

My Dash app has the following structure:

  1. Dropdowns for filtering the df → output: columndefs and rowdata
  2. Rowdata fill the Ag-grid table that is a part of a modal → additional filtering happens here
  3. virtualRowData is sent to another ag-grid table

Problem:
I have to open the modal so that virtualRowData is sent forward. I would like this to happen in the background. Is this possible to achieve?

My modal code is basic:

@callback(
    Output("modal", "is_open"),
    Input("modal-button", "n_clicks"),
    State("modal", "is_open"),
)
def toggle_modal(n1, is_open):
    if n1:
        return not is_open
    return is_open

Code to send virtualRowData to another table:

@callback(
    Output("data_table2", "rowData"),
    Input("data_table", "virtualRowData"),
    prevent_initial_call=True
)
def prepare_tbl_data2(rows):
    
    df_tbl = pd.DataFrame(rows)

    return df_tbl.to_dict("rows")

I’m not sure what the problem is - can you make a complete minimal example?

Hello @davzup89,

The virtualRowData always populates based upon the grid being ready, as with a modal the grid is not ready, you wont be able to use the automatically populated info. However, you could send both the rowData and virtualRowData at the same time to the grid. Especially since you wont be adjusting things like filters without seeing them, you should be able to do this.

2 Likes

Hi @AnnMarieW

Here is the example, not really minimal though. What I want to achieve is to have dash_table rendered upon selection from dropdown. Current setup requires opening a modal first. The use-case of this is additional filtering in the modal but it has to be optional (no opening required to load the data).

from dash import Dash, html, Input, Output, State, dash_table
import dash_ag_grid as dag
import pandas as pd
import dash_bootstrap_components as dbc
import dash_core_components as dcc


app = Dash(__name__)
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/solar.csv")
grid = dag.AgGrid(
    id="grid",
    rowData=[],
    columnDefs=[{"field": i, "id": i} for i in df.columns],
    defaultColDef={"resizable": True, "sortable": True, "filter": True, "minWidth":125},
    columnSize="sizeToFit",
    getRowId="params.data.State"
)

app.layout = html.Div([
    dcc.Dropdown(
        id='dropdown',
        options=[{'label': i, 'value': i} for i in df['State'].unique()],
        value=None,
    ),
    html.Div(id="quickstart-output"),
    dbc.Button("Open Modal", id="modal-button", className="mb-3"),
    dbc.Modal(
        [
            dbc.ModalHeader(dbc.ModalTitle("Test")),
            dbc.ModalBody(grid, className="py-4"),
        ],
        id="modal",
        size="xl",
        is_open=False,
    ),
    dbc.Card(dbc.CardBody(id="df_output3")),
])

@app.callback(
    Output("grid", "rowData"),
    Input("dropdown", "value")
)
def update_output(selected_state):
    df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/solar.csv")
    
    filtered_df = df[df['State'] == selected_state]

    new_df = filtered_df

    return new_df.to_dict("records")


@app.callback(
    Output("df_output3", "children"),
    Input("grid", "virtualRowData"),
    prevent_initial_call=True
)
def prepare_tbl_data(rows):
    #selected = [s["API"] for s in selected] if selected else []
    if len(rows) > 0:
        
        df_tbl = pd.DataFrame(rows)

        new_table = dash_table.DataTable(
            data=df_tbl.to_dict("records"),
            columns=[{"name": i, "id": i} for i in df_tbl.columns],
            style_header={'backgroundColor': 'rgb(44, 62, 80)', 'color': 'white'}
            )

        return new_table
    return None

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

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

Makes sense :slight_smile: Still, if I filter the data I would like to send forward virtualDataRows or selectedRows for that matter. What would be the best way to do that, probably coupling it with opening the modal?

The second you open the modal, it will start updating the virtualRowData… but once you close it, then you will run into the same issues if you are wanting to update the rowData with the filters still filtering the data.

I am probably approaching this the wrong way but due to my functionality reqs I found out that filtering the data with row deselection (selectAll is run when the grid renders) is by far the most effective way of filtering my df. This is due to nature of my df (parallel data) where only certain parallel can get excluded for specific data series.

This means that I would prefer to send forward rowData in case where modal is not opened of and selectedRows when the df is filtered by row deselection.

This maneuvering will probably also cause performance reduction right?

I cant really say, I think the less steps to creating your desired outcome, the better.

2 Likes