I have a Slack modal with a section
block containing an input element. When a user submits my modal without entering a value in this input, how do I communicate that error to the user?
Slack's documentation describes how to validate input
blocks when I receive a view_submission
event (https://api.slack.com/surfaces/modals/using#displaying_errors). But if I return an error for a section
block containing a static_select
, then Slack does not display an error message (nor does it close the modal).
optional
field to falseinput
blocks have an optional
field that can be used for validation. But a static_select
in a section
block does not have an optional
field: https://api.slack.com/reference/block-kit/block-elements#select
input
blocksI can not use input
blocks because they do not trigger block_actions
messages (documented at https://api.slack.com/surfaces/modals/using#interactions). I need to update the modal as the users answer questions.
I could reply to the view_submission
event with a "response_action": "update" response. In that response include an error message like this above the input with the missing value:
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Please provide a start time:*"
}
}
I do not like this solution because I doubt I can duplicate the nice error messaging UX that Slack provides for input
block validation.
Here is a simplified version of the view
parameter that I am passing to the views.open call:
{
"blocks": [
{
"block_id": "start_times",
"type": "section",
"text": {
"type": "plain_text",
"text": "Choose a start time"
},
"accessory": {
"action_id": "start_times",
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Choose start"
},
"options": [
{
"text": {
"type": "plain_text",
"text": "10:27 pm"
},
"value":
"{\"path\":\"bookings/new\",\"date\":\"2020-02-14 04:27:22 UTC\"}"
},
{
"text": {
"type": "plain_text",
"text": "10:45 pm"
},
"value":
"{\"path\":\"bookings/new\",\"date\":\"2020-02-14 04:45:00 UTC\"}"
}
]
}
}
],
"callback_id": "create booking",
"private_metadata":
"{\"channel_id\":\"C6M2A4690\",\"min_start_time\":\"2020-02-14 04:27:22 UTC\",\"path\":\"bookings/create\",\"room_id\":175128,\"selected_end_time\":null,\"selected_start_time\":null}",
"type": "modal",
"submit": {
"type": "plain_text",
"text": "Book"
},
"title": {
"type": "plain_text",
"text": "Booking room"
}
}
If the user immediately clicks submit, this is my response to the view_submission
event:
{
"response_action": "errors",
"errors": {
"start_times": "Please complete this required field"
}
}
Upon receipt of my response, Slack turns off the spinner, leaves the modal open, but does not display an error message. The modal looks exactly the same as when it was first opened via views.open
.
Since you posted your question, the functionality of input
blocks has changed. Earlier this month, the ability for input
blocks to emit block_actions
payloads was introduced.
In the Block Kit reference docs for the input
block you can see a new dispatch_action
parameter. This is a boolean which, when set to true, causes the interactive element inside the input
block to emit a block_actions
payload when changed.
Therefore, to answer your question more directly, your #3 solution should now be possible without the caveat that you included. Place the static_select
inside of an input
block, and set dispatch_action
to true
, like so:
{
"type": "input",
"dispatch_action": true,
"element": {
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Select an item",
"emoji": true
},
"options": [
{
"text": {
"type": "plain_text",
"text": "*this is plain_text text*",
"emoji": true
},
"value": "value-0"
},
{
"text": {
"type": "plain_text",
"text": "*this is plain_text text*",
"emoji": true
},
"value": "value-1"
},
{
"text": {
"type": "plain_text",
"text": "*this is plain_text text*",
"emoji": true
},
"value": "value-2"
}
],
"action_id": "static_select-action"
},
"label": {
"type": "plain_text",
"text": "Label",
"emoji": true
}
}
Upon receiving a view_submission
payload, you'll now be able to respond with the correct validation errors and display them to a user. And you can still receive block_actions
payloads as needed too.
Set the response's "content_type
" to "application/json
" before returning response.
If you are using Django as backend then you can do this.
error_object = {
"response_action": "errors",
"errors": {
"start_times": "Please complete this required field"
}
}
return HttpResponse(json.dumps(error_object), content_type="application/json")
===OR===
return JsonResponse(error_object)
don't forget to import JsonReponse if you are using it:
from django.http import JsonResponse
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With