# esx_menu_dialog (/docs/core/esx_menu_dialog)

esx_menu_dialog is the input box of ESX Legacy. It shows a title, one text field
(or a larger text area) and Submit/Cancel buttons. Use it when you need a
single value from the player, such as an amount of money, a plate or a short
message. You open it with `ESX.UI.Menu.Open('dialog', ...)`.

## Overview [#overview]

| | |
| --- | --- |
| Resource | `esx_menu_dialog` |
| Side | Client only |
| Menu type | `dialog` |
| Dependencies | `es_extended`, `esx_lib` (loaded via `@esx_lib/imports.lua`) |
| UI | jQuery + Mustache page in `html/` |

The resource has no configuration file. The dialog takes mouse and keyboard
focus about 200 ms after opening and releases it when the last dialog closes.

<Callout type="warn">
The manifest only lists `es_extended`, but the client loads
`@esx_lib/imports.lua`. Start `esx_lib` first.
</Callout>

## Opening a dialog [#opening-a-dialog]

```lua
ESX.UI.Menu.Open('dialog', namespace, name, data, submit, cancel, change, close)
```

| Name | Type | Description |
| --- | --- | --- |
| `namespace` | `string` | Usually `GetCurrentResourceName()`. |
| `name` | `string` | Unique dialog name inside the namespace. |
| `data` | `table` | Dialog data, see below. |
| `submit` | `function(data, menu)?` | Submit button or Enter. |
| `cancel` | `function(data, menu)?` | Cancel button or Escape. |
| `change` | `function(data, menu)?` | Runs on every keystroke with the current text in `data.value`. |
| `close` | `function()?` | Runs after `menu.close()`. |

The returned `menu` object and the generic helpers (`ESX.UI.Menu.Close`,
`CloseAll`, `IsOpen`) are documented on the
[esx_menu_default page](/docs/core/esx_menu_default#menu-object).

### Dialog data [#dialog-data]

| Field | Type | Description |
| --- | --- | --- |
| `title` | `string` | Text in the header. Escaped, so HTML is shown as text. |
| `type` | `string?` | `'default'` (single-line input, default) or `'big'` (multi-line text area). |
| `value` | `string?` | Prefilled value. |

### Callback data [#callback-data]

| Field | Description |
| --- | --- |
| `data.value` | What the player typed. On submit it is always a **string**. |
| `data.title`, `data.type` | Copied from your dialog data. |
| `data._namespace`, `data._name` | Menu identifiers. |

## Input rules on submit [#input-rules-on-submit]

Before your `submit` callback runs, the resource processes the value:

1. If the text parses as a number, it is rounded to the nearest integer.
2. If that number is `0` or negative, the dialog shows the notification
   "That input is not allowed!" and **does not call** `submit`.
3. The value is trimmed and converted to a string.

So `" 12.6 "` arrives as `"13"`, `"-5"` and `"0"` never arrive, and text like
`"ABC 123"` passes through trimmed.

## Example [#example]

```lua title="client/main.lua"
local function askDepositAmount()
    ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'bank_deposit', {
        title = 'Deposit amount',
    }, function(data, menu)
        local amount = tonumber(data.value)

        if not amount then
            ESX.ShowNotification('Enter a valid number', 'error')
            return
        end

        menu.close()
        TriggerServerEvent('my_bank:deposit', amount)
    end, function(data, menu)
        menu.close()
    end)
end
```

A multi-line dialog with a prefilled value:

```lua
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'edit_note', {
    title = 'Note',
    type = 'big',
    value = currentNote,
}, function(data, menu)
    menu.close()
    TriggerServerEvent('my_notes:save', data.value)
end, function(data, menu)
    menu.close()
end)
```

<Callout type="error" title="Validate on the server">
The rounding and the positive-number check run on the client. A cheater can
trigger your server event with any value, so check the amount again on the
server.
</Callout>

## Controls [#controls]

| Key | Action |
| --- | --- |
| Enter | Submit |
| Escape | Cancel |
| Mouse | Submit / Cancel buttons |

## Common issues [#common-issues]

- **Comparing `data.value` to a number fails**: it is a string. Use
  `tonumber(data.value)`.
- **Players cannot enter `0`**: by design. If you need zero or negative values,
  read them in a `change` callback or use [esx_context](/docs/core/esx_context)
  number inputs.
- **Dialog stays open after Submit**: call `menu.close()` in `submit` and
  `cancel`.
- **Mouse cursor stays after closing**: focus is only released when no dialog
  is left open. Make sure every dialog you open is closed, or call
  `ESX.UI.Menu.CloseAll()`.

## Related [#related]

- [esx_menu_default](/docs/core/esx_menu_default)
- [esx_menu_list](/docs/core/esx_menu_list)
- [esx_context](/docs/core/esx_context)
- [Client UI functions](/docs/es_extended/client/ui)
