# Select menu element

Allows users to choose an option from a drop down menu. The select menu also includes type-ahead search, where a user can type a part or all of an option string to filter the list.

| | |
|---|---|
| **Type** | `static_select` |
| **Available in** | Messages, Modals, Home tab |
| **Works in blocks** | [Section block](https://workstation.repzo.com/docs/developers/block-kit/blocks/section-block), [Actions block](https://workstation.repzo.com/docs/developers/block-kit/blocks/actions-block), [Input block](https://workstation.repzo.com/docs/developers/block-kit/blocks/input-block) |

## Usage

There are five kinds of select menu, depending on where the options come from. They share most fields; the fields table marks the ones that belong to a single kind.

| Type | Options come from | Value in `block_actions` |
|---|---|---|
| `static_select` | the `options` or `option_groups` you send | `selected_option` — an option object |
| `external_select` | your app, as the reader types (`block_suggestion`, below) | `selected_option` — an option object |
| `users_select` | the active members of the workspace | `selected_user` — a user id |
| `conversations_select` | the channels and DMs the reader can see, narrowed by `filter` | `selected_conversation` — a channel id |
| `channels_select` | the channels the reader can see | `selected_channel` — a channel id |

Choosing an option sends your app a `block_actions` payload:

```json
{
  "type": "static_select",
  "action_id": "deal_stage",
  "block_id": "deal_d2291_stage",
  "placeholder": { "type": "plain_text", "text": "Move to stage" },
  "selected_option": { "text": { "type": "plain_text", "text": "Negotiation" }, "value": "negotiation" },
  "action_ts": "1793786400.000000"
}
```

Option labels are copied from your element (or from what your app served), never from the reader's client. People must be active members of the workspace, and conversations must be ones the reader can see.

See the [button element](https://workstation.repzo.com/docs/developers/block-kit/elements/button-element) for the rest of the payload.

The current value is also reported in `state.values[block_id][action_id]` (as `{ "type": …, <value field> }`) of every later interaction with the same message or view.

Inside an [input block](https://workstation.repzo.com/docs/developers/block-kit/blocks/input-block), changing the value sends nothing on its own: your app reads it from `view.state.values` in the `view_submission` payload. Set `dispatch_action: true` on the input block to also receive a `block_actions` payload on every change.

### Loading options from your app (`block_suggestion`)

An external select asks your app for options as the reader types. Once the reader has typed `min_query_length` characters (default `3`), Repzo POSTs a signed `block_suggestion` payload to your app's subscription for the `block_suggestion` event — or, if it has none, to the subscription that receives `block_actions` (Slack's single Request URL):

```json
{
  "type": "block_suggestion",
  "team": { "id": "<workspace id>" },
  "user": { "id": "<user id>", "username": "<email>", "name": "<display name>", "team_id": "<workspace id>" },
  "api_app_id": "<app id>",
  "container": { "type": "message", "message_ts": "<message id>", "channel_id": "<channel id>", "is_ephemeral": false },
  "channel": { "id": "<channel id>" },
  "block_id": "account_picker",
  "action_id": "choose_account",
  "value": "north"
}
```

In a modal or the Home tab, `container` is `{ "type": "view", "view_id": … }` and the payload also carries the `view`.

Answer **within 3 seconds** with `{ "options": [ … ] }` or `{ "option_groups": [ … ] }` (option objects; up to 100 options in a list or group). Option values longer than 150 characters are dropped, labels and descriptions are cut to 75 characters, and an option's `url` is ignored. If your app doesn't answer in time, the reader sees an error and can type again.

A reader can only choose an option your app served them (Repzo remembers each reader's suggestions for an hour) or the element's initial option(s). Anything else is refused before your app hears about it, so you can trust every `value` you receive.

## Fields

| Field | Type | Description | Required? |
|---|---|---|---|
| `type` | String | The type of element: `static_select`, `external_select`, `users_select`, `conversations_select` or `channels_select`. | Required |
| `action_id` | String | An identifier for the action triggered when a menu option is selected. You can use this when you receive an interaction payload to identify the source of the action. Should be unique among all other `action_id`s in the containing block. Maximum length is 255 characters. If you leave it out, Repzo generates one. | Optional |
| `options` | Array of [Option object](https://workstation.repzo.com/docs/developers/block-kit/objects/option-object) | **`static_select` only.** An array of option objects. Maximum number of options is 100 (counting the options inside `option_groups`). If `option_groups` is specified, this field should not be. | Required for `static_select` unless `option_groups` is provided |
| `option_groups` | Array of [Option group object](https://workstation.repzo.com/docs/developers/block-kit/objects/option-group-object) | **`static_select` only.** An array of option group objects. If `options` is specified, this field should not be. | Optional |
| `initial_option` | [Option object](https://workstation.repzo.com/docs/developers/block-kit/objects/option-object) | **`static_select` and `external_select`.** A single option that exactly matches one of the options within `options` or `option_groups` (for external menus: an option your app would serve). This option will be selected when the menu initially loads. | Optional |
| `min_query_length` | Integer | **`external_select` only.** The fewest number of typed characters required before Repzo asks your app for options. The default value is `3`. | Optional |
| `initial_user` | String | **`users_select` only.** The user ID of any valid user to be pre-selected when the menu loads. | Optional |
| `initial_conversation` | String | **`conversations_select` only.** The ID of any valid conversation to be pre-selected when the menu loads. If `default_to_current_conversation` is also supplied, `initial_conversation` will take precedence. | Optional |
| `default_to_current_conversation` | Boolean | **`conversations_select` only.** Pre-populates the select menu with the conversation that the user was viewing when they opened the modal, if available. Default is `false`. | Optional |
| `filter` | [Conversation filter object](https://workstation.repzo.com/docs/developers/block-kit/objects/conversation-filter-object) | **`conversations_select` only.** A filter object that reduces the list of available conversations using the specified criteria. | Optional |
| `initial_channel` | String | **`channels_select` only.** The ID of any valid channel to be pre-selected when the menu loads. | Optional |
| `confirm` | [Confirmation dialog object](https://workstation.repzo.com/docs/developers/block-kit/objects/confirmation-dialog-object) | A confirm object that defines an optional confirmation dialog that appears after a menu item is selected. If the reader cancels, nothing is sent to your app. | Optional |
| `focus_on_load` | Boolean | Indicates whether the element will be set to auto focus within the view. Only one element can be set to `true`. Defaults to `false`. | Optional |
| `placeholder` | [Text object](https://workstation.repzo.com/docs/developers/block-kit/objects/text-object) | A `plain_text` only text object that defines the placeholder text shown on the menu. Maximum length for the `text` in this field is 150 characters. | Optional |

> **How Repzo Chat differs from Slack**
>
> - `response_url_enabled` isn't supported: `view_submission` payloads always carry an empty `response_urls`.
> - Channel menus (`channels_select`, `multi_channels_select`) list the public **and private** channels the reader can see; Slack lists public channels only.
> - Repzo has public channels, private channels, direct messages (`im`) and group direct messages with two to eight other people (`mpim`). `exclude_external_shared_channels` has no effect because Repzo has no externally shared channels. Without a filter, conversations menus list channels and DMs, group DMs included; channels menus list channels only. `exclude_bot_users` hides DMs with apps.
> - Every chosen conversation is checked on the server: it must be one the reader can see and, when `filter.include` is set, of an allowed kind.
> - On the web, an external select starts asking your app after the first typed character even when `min_query_length` is `0`; the mobile app asks as soon as the picker opens.
> - Suggestions go to the app's `block_suggestion` subscription, or to its `block_actions` subscription when it has none — there is no separate Options Load URL to configure.
> - `focus_on_load` is accepted but not applied to this element yet.

## Examples

### A static select with option groups

```json
{
  "blocks": [
    {
      "type": "section",
      "block_id": "deal_d2291_stage",
      "text": {
        "type": "mrkdwn",
        "text": "*Northwind Traders — Expansion 2027* hasn't moved in 14 days. Update its stage?"
      },
      "accessory": {
        "type": "static_select",
        "action_id": "deal_stage",
        "placeholder": {
          "type": "plain_text",
          "text": "Move to stage"
        },
        "option_groups": [
          {
            "label": {
              "type": "plain_text",
              "text": "Open"
            },
            "options": [
              {
                "text": {
                  "type": "plain_text",
                  "text": "Qualification"
                },
                "value": "qualification"
              },
              {
                "text": {
                  "type": "plain_text",
                  "text": "Proposal"
                },
                "value": "proposal"
              },
              {
                "text": {
                  "type": "plain_text",
                  "text": "Negotiation"
                },
                "value": "negotiation"
              }
            ]
          },
          {
            "label": {
              "type": "plain_text",
              "text": "Closed"
            },
            "options": [
              {
                "text": {
                  "type": "plain_text",
                  "text": "Won"
                },
                "value": "won"
              },
              {
                "text": {
                  "type": "plain_text",
                  "text": "Lost"
                },
                "value": "lost"
              }
            ]
          }
        ]
      }
    }
  ]
}
```

### External, people and channel selects in a form

This example belongs in a modal view — the screenshot shows it in a modal.

```json
{
  "blocks": [
    {
      "type": "input",
      "block_id": "account_picker",
      "label": {
        "type": "plain_text",
        "text": "Account"
      },
      "element": {
        "type": "external_select",
        "action_id": "choose_account",
        "min_query_length": 2,
        "placeholder": {
          "type": "plain_text",
          "text": "Search accounts"
        }
      }
    },
    {
      "type": "input",
      "block_id": "owner_picker",
      "label": {
        "type": "plain_text",
        "text": "Account owner"
      },
      "element": {
        "type": "users_select",
        "action_id": "owner",
        "placeholder": {
          "type": "plain_text",
          "text": "Select a person"
        }
      }
    },
    {
      "type": "input",
      "block_id": "announce_in",
      "optional": true,
      "label": {
        "type": "plain_text",
        "text": "Announce the handover in"
      },
      "element": {
        "type": "conversations_select",
        "action_id": "channel",
        "default_to_current_conversation": true,
        "filter": {
          "include": [
            "public",
            "private"
          ]
        }
      }
    }
  ]
}
```

## Related

- [Block elements](https://workstation.repzo.com/docs/developers/block-kit/elements)
- [Block Kit overview](https://workstation.repzo.com/docs/developers/block-kit)
