I’m working on a Discord bot for my college’s alumni using Python. I’ve got a ‘/embed’ command that should open a modal for users to input their name and graduation year. It works fine with ui.TextInput, but I’m having trouble with ui.Select for a dropdown list.
Here’s what I’ve tried:
class GradYearPicker(ui.Modal, title='Alumni Info'):
full_name = ui.TextInput(label='Your Name')
class_year = ui.Select(
placeholder='Pick your graduation year',
options=[
discord.SelectOption(label=str(year), value=str(year))
for year in range(2020, 2025)
]
)
async def on_submit(self, interaction):
# Role assignment logic here
pass
When I use this, I get an error about an invalid form body. The error suggests the ‘type’ field must be 4, but I’m not sure what that means or how to fix it.
Any ideas on how to make the dropdown work? Or is there a better way to let users pick their graduation year? Thanks!
Hey there! I’ve actually been working on a similar project for my university’s alumni network, and I ran into the same issue with ui.Select in modals. What I ended up doing was creating a separate command for selecting the graduation year.
Here’s what worked for me:
I kept the modal for name input, but for the graduation year, I made a new command that uses discord.ui.Select in a View. It looks something like this:
class YearSelect(discord.ui.Select):
def __init__(self):
options = [discord.SelectOption(label=str(year), value=str(year)) for year in range(2020, 2025)]
super().__init__(placeholder='Select your graduation year', options=options)
async def callback(self, interaction):
# Handle the year selection here
class YearView(discord.ui.View):
def __init__(self):
super().__init__()
self.add_item(YearSelect())
@bot.command()
async def set_year(ctx):
view = YearView()
await ctx.send('Choose your graduation year:', view=view)
This approach separates the year selection from the modal, making it more manageable and avoiding the ‘invalid form body’ error. Hope this helps!
hey avamtz, i ran into smth similar. instead of using ui.Select in the modal, try using ui.TextInput with a custom validator. like this:
class_year = ui.TextInput(label='Grad Year (2020-2024)', min_length=4, max_length=4)
async def on_submit(self, interaction):
year = int(self.class_year.value)
if 2020 <= year <= 2024:
# do ur thing
else:
await interaction.response.send_message('invalid year bro', ephemeral=True)
this way u can keep everything in one modal. lmk if it works!
The issue you’re facing is because ui.Select isn’t designed to be used directly within a Modal. Instead, you should use ui.Select components in message components or application command options.
For your use case, I’d recommend using a string input with validation rather than a dropdown. You can modify your code like this:
class GradYearPicker(ui.Modal, title='Alumni Info'):
full_name = ui.TextInput(label='Your Name')
class_year = ui.TextInput(label='Graduation Year (2020-2024)', min_length=4, max_length=4)
async def on_submit(self, interaction):
year = int(self.class_year.value)
if 2020 <= year <= 2024:
# Role assignment logic here
await interaction.response.send_message(f'Welcome, {self.full_name.value} from the class of {year}!')
else:
await interaction.response.send_message('Invalid graduation year. Please try again.', ephemeral=True)
This approach allows users to input their graduation year as text, which you can then validate. It’s simpler and works within the Modal constraints.