You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guides/modals.md
+72Lines changed: 72 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,37 +4,53 @@ title: "Modals"
4
4
lang: en
5
5
---
6
6
# Modals
7
+
7
8
[Modals](https://api.slack.com/surfaces/modals/using) are a focused surface to collect data from users or display dynamic and interactive information. To users, modals appear as focused surfaces inside of Slack enabling brief, yet deep interactions with apps. Modals can be assembled using the visual and interactive components found in [Block Kit](https://api.slack.com/block-kit).
9
+
8
10
### Slack App Configuration
11
+
9
12
The first step to use modals in your app is to enable Interactive Components. Visit the [Slack App configuration page](http://api.slack.com/apps), choose the app you're working on, and go to **Features** > **Interactivity & Shortcuts** on the left pane. There are three things to do on the page.
13
+
10
14
* Turn on the feature
11
15
* Set the **Request URL** to `https://{your app's public URL domain}/slack/events`
12
16
* Click the **Save Changes** button at the bottom for sure
17
+
13
18
### What Your Bolt App Does
19
+
14
20
There are three patterns to handle on modals. As always, your app has to respond to the request within 3 seconds by `ack()` method. Otherwise, the user will see the timeout error on Slack.
21
+
15
22
#### `"block_actions"` requests
23
+
16
24
When someone uses an [interactive component](https://api.slack.com/reference/block-kit/interactive-components) in your app's modal views, the app will receive a [block_actions payload](https://api.slack.com/reference/interaction-payloads/block-actions). All you need to do to handle the `"block_actions"` requests are:
25
+
17
26
1.[Verify requests](https://api.slack.com/docs/verifying-requests-from-slack) from Slack
18
27
1. Parse the request body, and check if the `type` is `"block_actions"` and the `action_id` in a block is the one you'd like to handle
19
28
1.[Modify/push a view via API](https://api.slack.com/surfaces/modals/using#modifying) and/or update the modal to hold the sent data as [private_metadata](https://api.slack.com/surfaces/modals/using#carrying_data_between_views)
20
29
1. Respond to the Slack API server with 200 OK as an acknowledgment
30
+
21
31
#### `"view_submission"` requests
32
+
22
33
When a modal view is submitted, you'll receive a [view_submission payload](https://api.slack.com/reference/interaction-payloads/views#view_submission). All you need to do to handle the `"view_submission"` requests are:
34
+
23
35
1.[Verify requests](https://api.slack.com/docs/verifying-requests-from-slack) from Slack
24
36
1. Parse the request body, and check if the `type` is `"view_submission"` and the `callback_id` is the one you'd like to handle
25
37
1. Extract the form data from `view.state.values`
26
38
1. Do whatever to do such as input validations, storing them in a database, talking to external services
27
39
1. Respond with 200 OK as the acknowledgment by either of the followings:
28
40
* Sending an empty body means closing only the modal
29
41
* Sending a body with `response_action` (possible values are `"errors"`, `"update"`, `"push"`, `"clear"`)
42
+
30
43
#### `"view_closed"` requests (only when `notify_on_close` is `true`)
44
+
31
45
Your app can optionally receive [view_closed payloads](https://api.slack.com/reference/interaction-payloads/views#view_closed) whenever a user clicks on the Cancel or x buttons. These buttons are standard, not blocks, in all app modals. To receive the `"view_closed"` payload when this happens, set `notify_on_close` to `true` when creating a view with [views.open](https://api.slack.com/methods/views.open) and [views.push](https://api.slack.com/methods/views.push) methods.
32
46
All you need to do to handle the `"view_closed"` requests are:
33
47
1.[Verify requests](https://api.slack.com/docs/verifying-requests-from-slack) from Slack
34
48
1. Parse the request body, and check if the `type` is `"view_closed"` and the `callback_id` is the one you'd like to handle
35
49
1. Do whatever to do at the timing
36
50
1. Respond with 200 OK as the acknowledgment
51
+
37
52
### Modal Development Tips
53
+
38
54
In general, there are a few things to know when working with modals. They would be:
39
55
* You need `trigger_id` in user interaction payloads to open a modal view
40
56
* Only the inputs in `"type": "input"` blocks will be included in `view_submission`'s `view.state.values`
@@ -43,8 +59,11 @@ In general, there are a few things to know when working with modals. They would
43
59
* You can use `view.private_metadata` to hold the internal state and/or `"block_actions"` results on the modal
44
60
* You respond to `"view_submission"` requests with `response_action` to determine the next state of a modal
45
61
*[views.update](https://api.slack.com/methods/views.update) and [views.push](https://api.slack.com/methods/views.push) API methods are supposed to be used when receiving `"block_actions"` requests in modals, NOT for `"view_submission"` requests
62
+
46
63
---
64
+
47
65
## Examples
66
+
48
67
**NOTE**: If you're a beginner to using Bolt for Slack App development, consult [Getting Started with Bolt]({{ site.url | append: site.baseurl }}/guides/getting-started-with-bolt), first.
49
68
Let's start with opening a modal. Let's say, we're going to open the following modal.
50
69
```javascript
@@ -81,13 +100,16 @@ Let's start with opening a modal. Let's say, we're going to open the following m
81
100
]
82
101
}
83
102
```
103
+
84
104
**slack-api-client** offers a smooth DSL for building blocks and views. The following code generates **View** objects in a type-safe way.
If you need to carry some information to the modal, setting `private_metadata` is a good way for it. The `private_metadata` is a single string with a maximum of 3000 characters. So, if you have multiple values, you need to serialize them into a string in a format.
A `trigger_id` is required to open a modal. You can access it in payloads sent by user interactions such as slash command invocations, clicking a button. InBolt, you can acquire the value by calling `Request.getPayload().getTriggerId()` as it's a part of payloads. More easily, it's also possible to get it by `Context.getTriggerId()`.These methods are defined only when `trigger_id` exists in a payload.
The same code in Kotlin looks as below. (New to Kotlin? [GettingStarted in Kotlin]({{ site.url | append: site.baseurl }}/guides/getting-started-with-bolt#getting-started-in-kotlin) may be helpful)
InKotlin, it's much easier to embed multi-line string data in source code. It may be handier to use `viewAsString(String)` method instead.
196
+
163
197
```kotlin
164
198
// Build a view using string interpolation
165
199
val commandArg = req.payload.text
@@ -182,15 +216,19 @@ val modalView = """
182
216
]
183
217
}
184
218
""".trimIndent()
219
+
185
220
val res = ctx.client().viewsOpen { it
186
221
.triggerId(ctx.triggerId)
187
222
.viewAsString(modalView)
188
223
}
189
224
```
225
+
190
226
Alternatively, you can use the [Block Kit DSL]({{ site.url | append: site.baseurl }}/guides/composing-messages#block-kit-kotlin-dsl) in conjunction with the Java Builder to construct your view. The Java example above would look like this in Kotlin:
Basically it's the same with [InteractiveComponents]({{ site.url | append: site.baseurl }}/guides/interactive-components) but the only difference is that a payload coming from a modal has `view` and also its `private_metadata`
`view_submission` payloads don't have `response_url` by default. However, if you have an `input` block asking users a channel to post a message, payloads may provide `response_urls` (`List<ResponseUrl> responseUrls` in Java).
419
+
361
420
To enable this, set the block element type as either [`channels_select`](https://api.slack.com/reference/block-kit/block-elements#channel_select) or [`conversations_select`](https://api.slack.com/reference/block-kit/block-elements#conversation_select) and add `"response_url_enabled": true`. Refer to [the API document](https://api.slack.com/surfaces/modals/using#modal_response_url) for details.
421
+
362
422
Also, if you want to automatically set the channel a user is viewing when opening a modal to`initial_conversation(s)`, turn `default_to_current_conversation` on in [`conversations_select`](https://api.slack.com/reference/block-kit/block-elements#conversation_select) / [`multi_conversations_select`](https://api.slack.com/reference/block-kit/block-elements#conversation_multi_select) elements.
0 commit comments