Hi, @jinnyzor!
Thanks for your response.
I could implement the same using Grid APIs.
Kindly take a look at my code as well and let me know your views.
from dash import dash, Dash, dcc, html, Input, Output, State, clientside_callback
import pandas as pd
import dash_ag_grid
import dash_mantine_components as dmc
import json
option_mapping = {
"contains": "contains",
"notContains": "does not contain",
"startsWith": "begins with",
"endsWith": "ends with",
"blank": "is blank",
"notBlank": "is not blank",
"greaterThan": ">",
"greaterThanOrEqual": ">=",
"lessThan": "<",
"lessThanOrEqual": "<=",
"true": "is true",
"false": "is false",
"equals": {"text": "equals", "object": "equals", "number": "=", "date": "=", "dateString": "="},
"notEqual": {"text": "not equal", "object": "not equal", "number": "!=", "date": "!=", "dateString": "!="},
}
def format_filter_expression(filter_dict):
if "filterType" not in filter_dict:
return ""
filter_type = filter_dict.get("filterType")
if filter_type == "join":
join_type = filter_dict.get("type", "AND")
conditions = filter_dict.get("conditions", [])
formatted_conditions = [format_filter_expression(cond) for cond in conditions]
return f"({f' {join_type} '.join(formatted_conditions)})"
elif filter_type in ["text", "number"]:
col_id = filter_dict.get("colId", "")
filter_type_key = filter_dict.get("type", "")
filter_value = filter_dict.get("filter", "")
# Determine the data type
data_type = "text" # Default to "text" if not specified
if filter_type == "number":
data_type = "number"
# Add more conditions if needed to infer data_type
# Replace filter type using option_mapping
if filter_type_key in option_mapping:
filter_type = option_mapping[filter_type_key]
if isinstance(filter_type, dict):
filter_type = filter_type.get(data_type, filter_type.get("text")) # Default to "text" if specific data type is not found
else:
filter_type = filter_type_key
# Format filter value appropriately
if data_type == "text":
return f"[{col_id}] {filter_type} \"{filter_value}\""
else:
return f"[{col_id}] {filter_type} {filter_value}"
else:
return ""
style_cell = {
"fontFamily": "Inter",
"fontSize": 14,
"height": "30vh",
"minWidth": "100%",
"width": "100%",
"maxWidth": "100%",
"padding": "0.5rem",
"textAlign": "center",
"fontWeight": "normal",
}
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva', 'Frank', 'Grace', 'Hannah', 'Ivy', 'Jack'],
'City': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix', 'Philadelphia', 'San Antonio', 'San Diego', 'Dallas', 'San Jose'],
'Age': [25, 30, 35, 40, 28, 32, 27, 45, 29, 31],
'Gender': ['Female', 'Male', 'Male', 'Male', 'Female', 'Male', 'Female', 'Female', 'Female', 'Male'],
'Salary': [70000, 80000, 120000, 90000, 75000, 85000, 95000, 105000, 60000, 78000]
}
df = pd.DataFrame(data)
grid = dash_ag_grid.AgGrid(
id='ag-grid',
columnDefs=[{"headerName": c, "field": c} for c in df.columns],
rowData=df.to_dict("records"),
className="ag-theme-balham color-setting",
rowStyle={"defaultStyle": style_cell},
dashGridOptions={
"rowHeight": 25,
"pagination": True,
"paginationPageSize": 5,
"icons": {
"columnGroupOpened": '<i class="fa-regular fa-square-check"></i>',
"columnGroupClosed": '<i class="fa-regular fa-square"></i>',
},
"domLayout": "autoHeight",
"tooltipShowDelay": 100,
"postSortRows": {"function": "postSort(params)"},
"enableAdvancedFilter": True
},
enableEnterpriseModules=True,
columnSize="autoSize",
style={"height": "100%", "width": "100%"},
defaultColDef={"editable": True, "filter": True, "floatingFilter": True, "filterParams": {"maxNumConditions": 6, "buttons": ["reset"], "closeOnApply": True}, "wrapText": True, "autoHeight": True, "cellStyle": {"wordBreak": "normal", "lineHeight": "unset"}},
)
grid2 = dash_ag_grid.AgGrid(
id='ag-grid2',
columnDefs=[{"headerName": c, "field": c} for c in df.columns],
rowData=df.to_dict("records"),
className="ag-theme-balham color-setting",
rowStyle={"defaultStyle": style_cell},
dashGridOptions={
"rowHeight": 25,
"pagination": True,
"paginationPageSize": 5,
"icons": {
"columnGroupOpened": '<i class="fa-regular fa-square-check"></i>',
"columnGroupClosed": '<i class="fa-regular fa-square"></i>',
},
"domLayout": "autoHeight",
"tooltipShowDelay": 100,
"postSortRows": {"function": "postSort(params)"},
"enableAdvancedFilter": True
},
enableEnterpriseModules=True,
columnSize="sizeToFit",
style={"height": "100%", "width": "100%", 'display':'none'},
defaultColDef={"editable": True, "filter": True, "floatingFilter": True, "filterParams": {"maxNumConditions": 6, "buttons": ["reset"], "closeOnApply": True}, "wrapText": True, "autoHeight": True, "cellStyle": {"wordBreak": "normal", "lineHeight": "unset"}},
)
app = Dash(__name__)
app.layout = html.Div([
html.Div(id='filter-expression-display'),
dcc.Store(id='filter-expression-store', data=None),
dmc.Space(h=30),
grid,
html.Div(id='filter-expression-display2'),
dcc.Store(id='filter-expression-store2', data=None),
dmc.Space(h=30),
grid2
])
clientside_callback(
"""
async (n1, n2, button) => {
try {
const gridApi1 = await dash_ag_grid.getApiAsync("ag-grid");
const gridApi2 = await dash_ag_grid.getApiAsync("ag-grid2");
if (!gridApi1 || !gridApi2) {
console.error("Grid API not found or not initialized.");
return [dash_clientside.no_update, dash_clientside.no_update];
}
// Get the current advanced filter model for grid 1
const filterModel1 = gridApi1.getAdvancedFilterModel();
// Get the current advanced filter model for grid 2
const filterModel2 = gridApi2.getAdvancedFilterModel();
// Convert the filter models to JSON strings for display
const filterModelJson1 = JSON.stringify(filterModel1, null, 2);
const filterModelJson2 = JSON.stringify(filterModel2, null, 2);
return [filterModelJson1, filterModelJson2];
} catch (error) {
console.error("Error getting grid API or filter model:", error);
return [dash_clientside.no_update, dash_clientside.no_update];
}
}
""",
Output('filter-expression-store', 'data'),
Output('filter-expression-store2', 'data'),
Input("ag-grid", "virtualRowData"),
Input("ag-grid2", "virtualRowData"),
)
# Add a callback to display the filter expression
@app.callback(
Output('filter-expression-display', 'children'),
Input('filter-expression-store', 'data'),
)
def display_filter_expression(data):
# print(data)
if data:
return f"Current Filter Expression: {format_filter_expression(json.loads(data))}"
return "No filters applied."
if __name__ == '__main__':
app.run_server(debug=True)