I am creating a search application with Dash by Plotly. I have a main search function for that creates a dataframe for the whole application that is defined as:
def search(term):
with index.searcher() as searcher:
parser = QueryParser("content", index.schema)
myquery = parser.parse(term)
results = searcher.search(myquery, limit=None)
print("Documents Containing ", term, ": ", len(results), "\n")
df = pd.DataFrame([i['date'], i['site'], i['system'], i['ticket'], i.score, i['level'], i['first'], i['last'], i['department'], \
i['detect'], i['code'],i['content'], i['description'], i['owner'], i['ownerGroup'], i['docId']] for i in results)
df.columns=['Reported Date', 'Site', 'System','Ticket ID', 'Score', 'Level', 'First', 'Last', 'Department', \
'Detection', 'Code', 'Content', 'Description', 'Owner', 'Owner Group', 'Document ID']
return df
I want users to be able to filter down search results with filters built into dcc.Dropdown
. A couple of them can be hard-coded like so:
dcc.Dropdown(
id='siteFilter',
options=[
{'label': 'ABC', 'value': 'ABC'},
{'label': 'DEF', 'value': 'DEF'},
{'label': 'HIJ', 'value': 'HIJ'},
{'label': 'LMO', 'value': 'LMO'}
],
value=['ABC', 'DEF', 'HIJ', 'LMO'],
multi=True
However, some of the fields I want to filter on contain many options for a search and cannot be hard-coded. I can get the options to work. However, my application will not apply the filter changing when a user changes values. So, I have in my app.layout
:
html.Div(dbc.Row([dbc.Col([
html.Label(["System Filter",
dcc.Dropdown(
id='systemFilter',
options='options',
value='All',
multi=True,
)
])
], width = 5)
]))
In my callback, I have tried several different options/combos of Outputs and States to achieve this with no luck. Callback:
@app.callback(
[Output(component_id='outTable', component_property='data'),
Output(component_id='outTable', component_property='columns'),
Output(component_id='commonWords', component_property='children'),
Output(component_id='systemFilter', component_property='options'),
#Output(component_id='systemFilter', component_property='value')
],
[Input(component_id='button', component_property='n_clicks')],
[State('searchId', 'value'),
State('siteFilter', 'value'),
State('detectFilter', 'value'),
State('levelFilter', 'value'),
State('codeFilter', 'value'),
#State(component_id='systemFilter', component_property='value')
])
def tableCreate(n_clicks, searchId, siteFilter, detectFilter, levelFilter, codeFilter):
if n_clicks > 0:
searchFrame = search(searchId)
###################### System Filter #######################################
#print('HERE DLKFSJSLDFKJSLDKJFJLKFDSJLDSKF')
#print(searchFrame['System'].unique())
#global optionsArray
optionsArray = searchFrame['System'].unique()
optionsArray = optionsArray.tolist()
print('Test')
print(optionsArray)
print('Test')
system_filter_options = [{'label': i, 'value': i} for i in optionsArray]
systemFilter = optionsArray
searchFrame = searchFrame[searchFrame['System'].isin(systemFilter)]
# Bunch of other code
searchFrame = searchFrame.drop(columns=['ContentNoStop'])
columns = [{'name': col, 'id': col} for col in searchFrame.columns]
data = searchFrame.to_dict(orient='records')
return data, columns, wordComponent, system_filter_options #, systemFilter
else:
return dash.no_update, dash.no_update, dash.no_update, dash.no_update
Essentially, one of 2 things happens. 1) The values return blank because they are not defined or 2) the options continually override the updated value parameter which I know is caused by the line systemFilter = optionsArray
but I cannot seem to figure out a work around for this.
Here is an example image. I would like the results to populate all, but when a user filters by system and only selects a few, all my graphs and tables should update. But everytime, it does not seem to catch that. What am I missing here? How can the dcc.Dropdown selections be applied as a filter dynamically? I cannot and do not want to hard-code all the options