Welcome, this post is about the different types of select menus and how to use them. View in discord.py docs
Select #
(technically called a “string select”)
This is the most basic select menu, it allows the user to select from a list of (up to 25) custom provided options.
Example:
from typing import Any
import discord
from discord.ui import Select
class FruitSelect ( Select ):
def __init__ ( self ):
super (). __init__ (
placeholder = "Select a favorite fruit..." ,
# the options
options = [
# value is what is returned when the option is selected, label is what is shown to the user
# value is optional, if not provided, label is used as the value
discord . SelectOption ( label = "Apple" , value = "apple" ),
discord . SelectOption ( label = "Orange" , value = "orange" ),
discord . SelectOption ( label = "Banana" , value = "banana" ),
]
)
async def callback ( self , interaction : discord . Interaction ) -> Any :
selected_fruit : str = self . values [ 0 ] # either "apple", "orange" or "banana"
await interaction . response . send_message (
f " { interaction . user . mention } 's favorite fruit is { selected_fruit } !"
)
Sending that as a view will result in a select menu that looks like this:
Auto populated selects #
discord.py v2.1+ required
These are select menus that are populated automatically by Discord, they are not really customizable:
You can not filter the members, roles or channels shown.
You can set the min/max amount of options the user can or must choose using the min_values
(1-25) and max_values
(1-25) kwargs.
You can choose the type of channels that are shown for ChannelSelect.
You can specify the options that should be selected by default using the default_values
kwarg. (requires discord.py v2.4+ ) (more on later)
Only the first 25 options will be shown, the rest can be searched for using the search bar, which has auto-complete.
UserSelect #
This is a select menu that allows the user to select from a list of members in the server. Or, if used in a DM, you and the bot.
Same as the basic select, except we import and use UserSelect
instead of Select
:
from discord.ui import UserSelect
And values
is a list of discord.Member
or discord.User
objects:
from typing import Any
async def callback ( self , interaction : discord . Interaction ) -> Any :
users : list [ discord . Member | discord . User ] = self . values
selected_users = [
f "Name: { user . name } , ID: { user . id } "
for user in users
]
await interaction . response . send_message (
f " { interaction . user . mention } selected the following users: \n " + " \n " . join ( selected_users )
)
RoleSelect #
This is a select menu that allows the user to select from a list of roles in the server.
Same as the basic select, except we import and use RoleSelect
instead of Select
:
from discord.ui import RoleSelect
And values
is a list of discord.Role
objects:
from typing import Any
async def callback ( self , interaction : discord . Interaction ) -> Any :
roles : list [ discord . Role ] = self . values
selected_roles = [
f "Name: { role . name } , ID: { role . id } "
for role in roles
]
await interaction . response . send_message (
f " { interaction . user . mention } selected the following roles: \n " + " \n " . join ( selected_roles )
)
MentionableSelect #
This is a select menu that allows the user to select from a list of members and roles in the server. Or, if used in a DM, you and the bot.
Same as the basic select, except we import and use MentionableSelect
instead of Select
:
from discord.ui import MentionableSelect
And values
is a list of discord.Member
, discord.User
and discord.Role
objects:
from typing import Any
async def callback ( self , interaction : discord . Interaction ) -> Any :
mentionables : list [ discord . Member | discord . User | discord . Role ] = self . values
selected_users = [
f "Name: { user . name } , ID: { user . id } "
for user in mentionables
if isinstance ( user , ( discord . Member , discord . User ))
]
selected_roles = [
f "Name: { role . name } , ID: { role . id } "
for role in mentionables
if isinstance ( role , discord . Role )
]
await interaction . response . send_message (
(
f " { interaction . user . mention } selected the following users: \n " + " \n " . join ( selected_users )
f " \n and the following roles: \n " + " \n " . join ( selected_roles )
)
)
ChannelSelect #
This is a select menu that allows the user to select from a list of channels in the server.
Same as the basic select, except we import and use ChannelSelect
instead of Select
and we can use the channel_types
kwarg to limit the type of channels shown, all channels are shown by default:
from discord import ChannelType
from discord.app_commands import AppCommandChannel , AppCommandThread
from discord.ui import ChannelSelect
And values
is a list of discord.AppCommandChannel
or discord.AppcommandThread
objects:
from typing import Any
class ChannelsSelector ( ChannelSelect ):
def __init__ ( self ):
super (). __init__ (
placeholder = "Select a channel..." ,
# limit the type of channels shown to text, voice and threads
channel_types = [ ChannelType . text , ChannelType . voice , ChannelType . thread ]
async def callback ( self , interaction : discord . Interaction ) -> Any :
channels : list [ AppCommandChannel | AppCommandThread ] = self . values
selected_channels = [
f "Name: { channel . name } , ID: { channel . id } "
for channel in channels
]
await interaction . response . send_message (
f " { interaction . user . mention } selected the following channels: \n " + " \n " . join ( selected_channels )
)
default_values #
discord.py v2.4+ required
This was briefly mentioned above, but you can specify the options that should be selected by default using the default_values
kwarg.
The kwarg takes a list of objects, the type of which depends on the type of select menu, e.g. for a ChannelSelect
it would be a list of channel objects.
There is also special class for it called SelectDefaultValue
which takes the id
of a user, role of channel and the type
of the object or you can also use the from_user
, from_role
and from_channel
classmethods to create the object. This one can be used for all the types of selects.
from typing import Any
import discord
from discord import ui
class ChooseAnyoneExceptMe ( ui . View ):
def __init__ ( self , bot_owner_id : int ):
super (). __init__ ()
# set the default values of the user select to the bot owner, so they can't select me!
self . user_select . default_values = [
discord . SelectDefaultValue ( id = bot_owner_id , type = discord . SelectDefaultType . user )
]
@ ui . select ( cls = ui . UserSelect , placeholder = "Select my owner..." )
async def user_select ( self , interaction : discord . Interaction , select : ui . UserSelect ) -> Any :
selected_user = select . values [ 0 ]
# yes, we are very sure that the selected user is not the bot owner.
await interaction . response . send_message (
f " { selected_user . mention } is not my owner!"
)
Decorator #
The select menus can also be defined using a decorator in a View
subclass and specifying the cls
kwarg (defaults to Select
):
from typing import Any
from discord import ui
class SelectView ( ui . View ):
# string select
# @ui.select(placeholder="Select an option...". options=[...])
# or @ui.select(cls=ui.Select, placeholder="Select an option...". options=[...])
# user select
# @ui.select(cls=ui.UserSelect, placeholder="Select a user...")
# role select
# @ui.select(cls=ui.RoleSelect, placeholder="Select a role...")
# mentionable select
# @ui.select(cls=ui.MentionableSelect, placeholder="Select a role or user...")
# channel select
# only text, voice and threads are shown
@ ui . select ( cls = ui . ChannelSelect , channel_types = [ ChannelType . text , ChannelType . voice , ChannelType . thread ], placeholder = "Select a channel..." )
async def channel_select ( self , interaction : discord . Interaction , select : ui . ChannelSelect ) -> Any :
...