Dash AG Grid Update ColumnDefs in another file?

I have a multipage Dash WebApp that consists of following four files:

  1. app.py <=from where app is launched
  2. sql.py <=different functions/queries/variables/lists pulling data from SQL
def sql_fn():
    ....
   return list_1, list_2
  1. columnDefs.py <=contains column definitions for the AG Grid on page.py and a function from (2) sql.py that is pulling a certain list from SQL
from sql.py import sql_fn

list_1, list_2 = sql_fn()

columnDefs = [
{
        "headerName": "Category 1",
        "field": "category1",
        # "type": "rightAligned",
        # "editable":False,
        "filter": "agTextColumnFilter",
        # "hide":"True",
        "cellEditor":"agSelectCellEditor",
        "cellEditorParams":{"values":list_1}
    },
    {
        "headerName": "Category 2",
        "field": "category2",
        # "type": "rightAligned",
        # "editable":False,
        "filter": "agTextColumnFilter",
        # "hide":"True",
        "cellEditor":"agSelectCellEditor",
        "cellEditorParams":{"function": f"dynamicOptions(params, {list_2})"}
    },
] 
  1. page.py <=contains a layout for the page, incl. AG Grid
from columnDefs.py import columnDefs

def layout_x:
   ...
   dbc.Row(
        dbc.Col(
            html.Div(id='table-from-sql')   # this is taking the table from callback
        )
   ...
   return layout_new

layout=layout_new

@callback(
        Output("table-from-sql", "children"),
        Input("SQL-data", "data")
)

def populate_datatable(json_data):
    dff = pd.read_json(json_data, orient="split")
    table = grid.AgGrid(
            id="sql-table",
            rowData=dff.to_dict("records"), 
            columnDefs=columnDefs,   # <===this is not getting updated each time webapp is reloaded/layout is refreshed
            defaultColDef={
                "resizable": True,
                "sortable": True,
                "filter": True,
                "floatingFilter": True,
                "editable": True,
                "minWidth":125
            },
            columnSize="sizeToFit",
            dashGridOptions={
                "undoRedoCellEditing": True,
                "rowDragManaged": True,
                "animateRows": True,
                "rowDragMultiRow": True,
                "suppressRowClickSelection" : True,
                "rowSelection": "multiple",
                "rowDragEntireRow": True,
            },
        )
    return table

On page.py inside the layout I have the following line, thanks to which the layout is refreshed/activated once a week or when page (app) is refreshed in browser.

dcc.Interval(id='interval_pg1', interval=86400000*7, n_intervals=0),

The problem is that when I physically refresh the webapp in the browser, only page.py is refreshed, i.e. only layout is refreshed.
The columnDefs.py file is not refreshed/re-initialized, thus, it is not pulling the latest lists from SQL, thus, layout on page.py doesn’t contain the latest list (e.g. dropdown options are not updated).

How do I force columnDefs.py to refresh each time I refresh pages in the browser?

I know I could avoid it if I put all columnDefs inside page.py, but I am trying to do it in a “cleaner” way.
I also tried to putting a layout in page.py as a function so that function is activated every time webapp is reloaded. I was hoping that it will cause the columnDefs.py also to get reloaded (initialized again) and it will be the latest list from SQL, but it’s not happening.

Thanks for help in advance.

Hello @mrel,

Any time you want something dynamic I. The layout, it must be triggered inside the function call.

1 Like

Hi, @jinnyzor .

Note: I edited the code in the original post above.

I actually put the whole layout into a function.
I was hoping that on page reload function will trigger the layout, layout will trigger the columnDefs from columnDefs.py, list_1 and list_2 in columnDefs.py will trigger the sql_fn.
But it’s not working.
Or am I putting something wrong into function?

Where you are fetching the columns from the db needs to be a function that gets called upon loading of the page. Right now, it would only be every time you spin up the app.

1 Like

Right now, it would only be every time you spin up the app.

Yes, that is exactly what is happening.

I tried to add a callback for new columnDefs, but it is still not working.
I was hoping that after page reload callback would overwrite the original imported columnDefs with columnDefs_new, but it’s not happening.

@callback(
        Output("columnDefs_new", "columnDefs"),
        Input("interval_pg", "n_intervals"),
)

def sql_list(n):
   list_1, list_2 = sql_fn()

   columnDefs_new = [
{
        "headerName": "Category 1",
        "field": "category1",
        # "type": "rightAligned",
        # "editable":False,
        "filter": "agTextColumnFilter",
        # "hide":"True",
        "cellEditor":"agSelectCellEditor",
        "cellEditorParams":{"values":list_1}
    },
    {
        "headerName": "Category 2",
        "field": "category2",
        # "type": "rightAligned",
        # "editable":False,
        "filter": "agTextColumnFilter",
        # "hide":"True",
        "cellEditor":"agSelectCellEditor",
        "cellEditorParams":{"function": f"dynamicOptions(params, {list_2})"}
    },
] 
   return columnDefs_new

What version of the grid are you using?

What sort of component has the id of "columnDefs_new" ? From the the code you posted above, it looks like your gird has an id of "sql-table"

2 Likes

2.3.0

image

Aaaand you are right. Apparently the error was in the output component. After I corrected it, the app worked immediately.

1 Like