# Forms

> Pop up a form with text boxes, then do something with what the user typed.

A **form** (Discord calls it a *modal*) is a pop-up window with text boxes. Use it when you need longer answers, like an application, a report or feedback.

A form has two parts:

1. **Open the form.** From a command or a button click.
2. **Handle the answers.** In a **Modal Submit** event.

## 1. Build and open the form

In a slash command:

1. Under **Behavior**, turn off **Show "thinking…"**. A form must be the first answer to the command.
2. In the **Pre-hook**, build the form and open it:

```python
form = ModalBuilder(title="Staff application", custom_id="apply")
form.add_text_input("age", "How old are you?", max_length=3)
form.add_text_input("why", "Why do you want to join?", style="long")
await send_modal(form)
end()
```

`end()` stops the normal reply. The form is the reply.

### Text box options

```python
form.add_text_input(
    name,
    label,
    style="short",
    placeholder=UNDEFINED,
    value=UNDEFINED,
    required=True,
    min_length=0,
    max_length=4000,
)
```

`UNDEFINED` means "not set". Leave those out unless you need them.

| Option | What it does |
|---|---|
| `name` | The key you read the answer with later. |
| `label` | The question shown above the box. |
| `style` | `"short"` for one line, `"long"` for a big box. |
| `placeholder` | Grey hint text inside the box. |
| `value` | Text already filled in. |
| `required` | Set `False` to allow an empty answer. |
| `min_length`, `max_length` | Shortest and longest answer allowed. |

Discord allows at most 5 text boxes in one form.

## 2. Handle the answers

Make an event:

- **Type:** Modal Submit
- **Custom ids:** `apply` (the same `custom_id` as the form)

```python
defer_response(ephemeral=True)

age = values.get("age", "")
why = values.get("why", "")

send_message("applications", f"New application from {user.mention}\nAge: {age}\nWhy: {why}")
respond_interaction(interaction, "Thanks! Your application was sent.")
```

`values` holds every answer, by the `name` you gave each text box.

> **Answer fast:** Discord waits 3 seconds. Call `defer_response(...)` first, then do the work, then `respond_interaction(...)`.

## Open a form from a button

In a **Button Click** event, open the form as the first answer. Do not defer before it.

```python
form = ModalBuilder(title="Report a user", custom_id="report")
form.add_text_input("details", "What happened?", style="long")
await send_modal(form)
```

Inside a [View](https://ccbot.app/docs/concepts/buttons-and-menus), pass the click as the second argument:

```python
@button(label="Apply", custom_id="apply_btn")
async def apply(self, interaction, component):
    await send_modal(form, interaction)
```

Without the second argument, the form tries to answer the command again, and Discord refuses it.

Full list of form functions: [Forms reference](https://ccbot.app/docs/reference/modals).
