Concept
Search function
Every select menu with external source to designed to provide a search function. Once the user enters at least min_query_length
chars its supposed to automatically start matching against your input. However, the actual matching has to be done by your app. Slack will be sending your app the characters the user entered and your app need to respond with the list of matches. If implemented correctly this will result in a search function.
Updating elements before submit
The user has to click on "Submit" before his input is registered and send to your app. It is not possible to get the intermediate state of elements or update them before the user submits.
Example code
Here is an example showing how to supply the data for a dynamic menu with external data. The example is in Python using Flask and the standard Slackclient.
This example will show a dynamic select element "City". Once the user enters text in the search field the list of cities is dynamically filtered based on the user input. e.g. "Li" will only show "London" and "Lisabon".
import os
import slack
from flask import Flask, json, request
app = Flask(__name__) #create the Flask app
@app.route('/slash', methods=['POST'])
def dialog_show():
"""shows the dialog"""
# define dialog
dialog = {
"callback_id": "ryde-46e2b0",
"title": "Request a Ride",
"submit_label": "Request",
"notify_on_cancel": True,
"state": "Limo",
"elements": [
{
"type": "text",
"label": "Pickup Location",
"name": "loc_origin"
},
{
"type": "text",
"label": "Dropoff Location",
"name": "loc_destination"
},
{
"label": "City",
"name": "city",
"type": "select",
"data_source": "external"
}
]
}
# open the dialog
client = slack.WebClient(token=os.environ['SLACK_TOKEN'])
response = client.dialog_open(
trigger_id=request.form.get('trigger_id'),
dialog=json.dumps(dialog)
)
assert response["ok"]
return ""
@app.route('/interactive', methods=['POST'])
def dialog_submit():
"""handle dialog submission"""
payload_json = request.form["payload"]
payload = json.loads(payload_json)
print(payload)
return ""
@app.route('/options_load', methods=['POST'])
def dialog_options_load():
"""provide filtered list of options based on input for dialog"""
payload_json = request.form["payload"]
payload = json.loads(payload_json)
# example list of all options
cities = {
"Berlin": 1,
"Copenhagen": 2,
"Lisabon": 3,
"London": 4,
"Madrid": 5,
"Oslo": 6,
"Paris": 7,
"Rom": 8,
"Stockholm": 9
}
# find matching options
# will match if user input string is in name
options = list()
for name, value in cities.items():
if payload["value"] in name:
options.append({
"label": name,
"value": value
})
# build response structure
response = {
"options": options
}
return json.jsonify(response)
if __name__ == '__main__':
app.run(debug=True, port=8000) #run app in debug mode on port 8000