I created a new free slack workspace to learn the slack bot app API. I have an action handler that listens to a global shortcut and opens an input modal in response. There is another action handler that listens to the modal input submit callback_id
, does some work, and then uses the trigger_id
to open another modal.
app.view('do_thing_b.submit', async (slack) => {
try {
await slack.ack()
console.info(`Received modal submit`)
// TODO: actual work to save the data
const view = {
type: 'modal',
callback_id: 'do_thing_b.received_submission',
title: {
text: 'Thing B Done',
type: 'plain_text',
},
blocks: [
{
type: 'section',
text: {
text: 'My Plain Text',
type: 'plain_text',
emoji: true,
},
},
],
close: {
text: 'Close',
type: 'plain_text'
}
}
const openViewParams = {
trigger_id: slack.body.trigger_id,
view,
}
console.log(`Opening Done Modal with open view params ${JSON.stringify(openViewParams)}`)
const result = await slack.client.views.open(openViewParams)
console.log(`=============================== Done modal opened?`)
console.debug(result)
}
catch (err) {
console.error(`Error submitting Thing B modal:`)
console.error(err)
}
})
The inconsistency is that this works as expected only when running the app in SocketMode against local code.
When I deploy the app and disable socket mode, the form submission never triggers the second modal to be displayed. I am able to see in the logs the same evidence of code behaviors that I see when running locally. The await slack.client.views.open(openViewParams)
invocation succeeds and the result log indicates a 200 ok response from slack.
I have the same request URL set for events and interactivity as I do for the global shortcut. In fact, I also have a slash command that posts an ephemeral help screen to the user, similar to what the /polly
command does. That message contains a button that also triggers this modal form to be displayed. Clicking that button to open the modal locally shows the same exact behavior: it works as expected when running locally with the app in Socket Mode, but never shows the followup modal after submission.
Follow-up question:
If this is not supposed to be allowed, how should slack apps respond to data input submission events? I also tried pushing a new view onto the modal, but closing the submit confirmation view just slides back to the original form, where I want it to close out the entire model. Do I need to send the user an ephemeral message to follow up after their data input submission?
Turns out I didn't need to open a modal, all I needed to do was update the existing modal. Instead of calling await slack.client.views.open
with a trigger_id
, I should have done this:
app.view('do_thing_b.submit', async (slack) => {
try {
console.info(`Received modal submit`)
// TODO: actual work to save the data
const view = {
type: 'modal',
callback_id: 'do_thing_b.received_submission',
title: {
text: 'Thing B Done',
type: 'plain_text',
},
blocks: [
{
type: 'section',
text: {
text: 'My Plain Text',
type: 'plain_text',
emoji: true,
},
},
],
close: {
text: 'Close',
type: 'plain_text'
}
}
const result = await slack.ack({
response_action: 'update', view
})
}
catch (err) {
console.error(`Error submitting Thing B modal:`)
console.error(err)
}
})
The docs I kept missing are these: