2

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?

danludwig
  • 46,965
  • 25
  • 159
  • 237

1 Answers1

5

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:

danludwig
  • 46,965
  • 25
  • 159
  • 237
  • That's true. Pushing new view is used when you are making a wizard like UI interface. In your case you needed https://api.slack.com/surfaces/modals/using#updating_views – Suyash Gaur Jul 26 '21 at 16:09
  • Keep in mind that if `actual work to save the data` part will take too long (more then 3 seconds) this approach won't work. You probably will need to push some "loading..." view, and after that use `views.update` to update it to proper value. – Егор Малыгин Feb 27 '23 at 01:19