Skip to main content
A form (Discord calls it a modal) is a window that opens in Discord with fields to fill in: texts, menus, checkboxes. It is the way to ask for more than a command’s options can hold, like a paragraph of text. This page adds /suggest, which opens a form and posts the suggestion.

A form is a file

Create src/components/suggest.ts (a form is declared with modal() and exported, from any file of src/):
src/components/suggest.ts
A command opens it with showModal():
src/commands/suggest.ts
Use /suggest: the form opens. Fill it in, submit: run of the form runs, posts in the channel, and thanks you privately. Hover fields in the form file: summary is a string, details is string | undefined (not required), area is 'The server' | 'The bot' | 'Events'. Each field is typed from its kind, like the options of a command.

Fields

A form has 1 to 5 fields. Each has a label (45 characters at most) and an optional description. The kind decides what the person sees and what run receives: | type | What it is | fields.name is | | ------------------------------------------------ | ----------------------------------------------------------------- | -------------------------- | --------------------- | | 'text' | A text, on one line (style: 'short') or several ('paragraph') | string | | 'select' | A menu of options, written like a select menu’s | A list of the values | | 'user', 'role', 'mentionable', 'channel' | A menu filled by Discord | User[], Role[], (User | Role)[], Channel[] | | 'files' | Files to upload | A list of attachments | | 'radio' | One choice among 2 to 10 options | One value | | 'checkboxes' | Several choices among 1 to 10 options | A list of the values | | 'checkbox' | Yes or no | boolean | | 'note' | A text to read, which nobody fills in | Not there | Every field is required unless it says required: false. minLength and maxLength bound a text; min and max say how many can be picked or uploaded.

From a button

A button or a menu can open a form too. The form then knows the message of the button (interaction.message) and can change it with update() instead of sending a new message. The data of a form works like the data of a button: given when the form is opened, received typed in run:
src/components/edit-topic.ts
src/components/topic.ts
To fill some fields in advance, pass values where the form is opened: topic({ channelId }, { values: { topic: 'Current topic' } }).

Points of attention

  • A form must be the first answer. showModal() after a reply() or a defer() is refused by Discord: open the form first, answer the submission in the form’s run.
  • No form from a form. Discord only opens a form in answer to a command or a component.
  • The person has as long as they want. A form is not bound by the 3 seconds; its submission is, and the framework defers for you.
  • The answers of a form are those of a command: reply(), defer(), edit(), followUp(), delete(), plus update() and deferUpdate() when a button opened it.

Recap

  • A form is modal({ title, fields, run }), exported; run receives fields typed per kind.
  • interaction.showModal(form) opens it, from a command, a button or a menu, as the first answer.
  • data and values are given where the form is opened.

Embeds and layout

Write an embed once, and build messages out of texts, sections and containers.

Guide: Forms

Every kind of field, in short.