[Bolt]モーダルウィンドウを開いてSubmitするまでの実装


手順

モーダルウィンドウ経由であれこれやりたい!となったときに色々ハマったので備忘録。
主に

  • Interactive Components設定忘れ
  • block kitのID忘れ
  • 各種イベントの取得方法

あたりでハマりました。

事前準備

Interactive Components の設定を忘れないようにしておきます。
この設定は Event Subscriptions のものと同様で構いません。

1.モーダルウィンドウを立ち上げるためのボタンを描画

まずは起点となる、モーダルウィンドウを呼び出すためのボタンを作ります。

index.js
const {App} = require('@slack/bolt');

const app = new App({
  signingSecret: process.env.SLACK_SIGNING_SECRET,
  token: process.env.SLACK_BOT_TOKEN
});

// モーダル用のウィンドウを呼び出すボタンを送信
app.event('app_mention', ({event, say}) => {
  say(entryModal);
});

(async () => {
  await app.start(process.env.SLACK_PORT || 8080);
  console.log('⚡️ Bolt app is running!');
})();
entryModal
{
  blocks: [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "modal window"
      },
      "accessory": {
        "type": "button",
        "text": {
          "type": "plain_text",
          "text": "open modal"
        },
        "action_id": "open_modal" // 2.モーダルウィンドウを描画で使うためのID
      }
    }
  ]
}

2.モーダルウィンドウを描画

続いて先ほどのaction_idを使用してモーダルウィンドウを描画していきます。

index.js
app.action('open_modal', ({body, ack, context}) => {
  ack();
  try {
    app.client.views.open({
      token: context.botToken,
      trigger_id: body.trigger_id,
      view: require(modalView)
    });
  } catch (e) {
    console.log(e);
  }
});
modalView
{
  "type": "modal",
  "callback_id": "modal_view", // 3.Submitで使うためのID
  "title": {
    "type": "plain_text",
    "text": "Modal window",
    "emoji": true
  },
  "submit": {
    "type": "plain_text",
    "text": "submit",
    "emoji": true
  },
  "close": {
    "type": "plain_text",
    "text": "cancel",
    "emoji": true
  },
  "blocks": [
    {
      "type": "input",
      "block_id": "modal_view_block", // 3.Submitで値を取得する際に使用
      "element": {
        "type": "radio_buttons",
        "action_id": "modal_view_block_radio", // 3.Submitで値を取得する際に使用
        "options": [
          {
            "text": {
              "type": "plain_text",
              "text": "うどん",
              "emoji": true
            },
            "value": "1"
          },
          {
            "text": {
              "type": "plain_text",
              "text": "ラーメン",
              "emoji": true
            },
            "value": "2"
          }
        ]
      },
      "label": {
        "type": "plain_text",
        "text": "麺類",
        "emoji": true
      },
    }
  ],
};

3.submit

最後にSubmitされた値を取得してみます。
Bolt組み込み関数のviewメソッドを使うと良さそうです。

index.js
app.view('modal_view', ({body, ack, view}) => {
  ack();
  const type = view.state.values.modal_view_block.modal_view_block_radio;
  console.log(body, view, type);
  try {
    // あとはよしなに
    app.client.chat.postMessage({
      token: context.botToken,
      channel: body['user']['id'],
      text: 'submit!'
    });
  } catch (e) {
    console.log(e);
  }
});

参考