ox_lib context menu: registerContext, inputDialog and alertDialog
Build menus in FiveM with ox_lib: lib.registerContext and lib.showContext with submenus and icons, plus lib.inputDialog and lib.alertDialog, and fixing 'lib' being nil.
You call lib.registerContext and the console says:
attempt to index a nil value (global 'lib')Or the menu code runs and nothing opens. This article covers ox_lib's menu tools: the context menu, the input dialog and the alert dialog, with the manifest line that makes lib exist.
Load ox_lib in your manifest
lib is a global that ox_lib adds to your resource through its init file. Without it, every lib. call fails with the error above. In fxmanifest.lua:
fx_version 'cerulean'
game 'gta5'
lua54 'yes'
shared_script '@ox_lib/init.lua'
client_scripts { 'client/*.lua' }
server_scripts { 'server/*.lua' }Then start ox_lib before your script in server.cfg:
ensure ox_lib
ensure my_scriptIf the file cannot be found at all, see @ox_lib/init.lua not found.
A context menu
A context menu is a list of clickable options. You register it once under an id, then show it when you need it. Both calls are client side:
lib.registerContext({
id = 'my_script_main',
title = 'Garage',
options = {
{
title = 'Take out a vehicle',
description = 'Choose from your parked vehicles',
icon = 'car',
onSelect = function()
print('take out')
end,
},
{
title = 'Store vehicle',
description = 'Park the vehicle you are in',
icon = 'warehouse',
onSelect = function()
print('store')
end,
},
{
title = 'Impound',
description = 'Not available',
icon = 'lock',
disabled = true,
},
},
})
lib.showContext('my_script_main')The options you will use most:
| Field | What it does |
|---|---|
title |
The main text of the option. |
description |
A second line of text under the title. |
icon |
A Font Awesome icon name, like car. You can also pass a full class such as fa-solid fa-car. |
onSelect |
Function that runs when the option is clicked. |
menu |
The id of another context to open (a submenu). |
arrow |
Shows an arrow on the right, a hint that it opens something. |
disabled |
Greys the option out so it cannot be clicked. |
Other fields exist, such as event, serverEvent, args, metadata and progress. Check the ox_lib documentation for the version you run.
Submenus
To open a submenu, give the option menu with the id of the next context. Give the second context a menu pointing back to the first, and it gets a back button:
lib.registerContext({
id = 'my_script_main',
title = 'Garage',
options = {
{
title = 'My vehicles',
icon = 'car',
arrow = true,
menu = 'my_script_vehicles',
},
},
})
lib.registerContext({
id = 'my_script_vehicles',
title = 'My vehicles',
menu = 'my_script_main',
options = {
{
title = 'Sultan',
description = 'Plate ABC 123',
onSelect = function()
print('selected Sultan')
end,
},
},
})
lib.showContext('my_script_main')Tip: the options table is built when you register the menu. For a list that changes, such as a player's vehicles, build the table and call
lib.registerContextagain just beforelib.showContext. Registering the same id again replaces the old menu.
lib.hideContext() closes the menu from code.
Ask for input with inputDialog
lib.inputDialog opens a form and waits until the player confirms or cancels. It returns a table with the values in row order, or nil if the player cancelled:
local input = lib.inputDialog('New shop', {
{ type = 'input', label = 'Shop name', required = true },
{ type = 'number', label = 'Price', default = 100, min = 0 },
{ type = 'checkbox', label = 'Open to everyone' },
})
if not input then return end
local name, price, open = input[1], input[2], input[3]
print(name, price, open)Other row types include select, slider and textarea. A select takes a list of options:
local input = lib.inputDialog('Pick a colour', {
{
type = 'select',
label = 'Colour',
options = {
{ value = 'red', label = 'Red' },
{ value = 'blue', label = 'Blue' },
},
},
})
if input then print(input[1]) endBecause the call waits, run it in a thread or in a handler that is allowed to wait, such as an onSelect function. Never validate on the client alone. When the value goes to the server, check it there as well.
Confirm with alertDialog
lib.alertDialog is a yes/no window. It returns 'confirm' or 'cancel':
local alert = lib.alertDialog({
header = 'Delete the shop?',
content = 'This cannot be undone.',
centered = true,
cancel = true,
})
if alert == 'confirm' then
print('deleting')
endWithout cancel = true there is only an OK button.
Use it from a target or a command
A menu is usually opened by something else. With ox_target, call lib.showContext in onSelect (see ox_target: how to add targets). With a command, call it in the handler:
RegisterCommand('garage', function()
lib.showContext('my_script_main')
end, false)Register the contexts first, at the top of the client file or when the script starts, so the id exists when the command runs.
Checklist
| Symptom | Fix |
|---|---|
attempt to index a nil value (global 'lib') |
Add shared_script '@ox_lib/init.lua' and start ox_lib first |
lib.showContext opens nothing |
Register the id with lib.registerContext before showing it |
| Submenu has no back button | Set menu on the submenu to the parent id |
| Menu shows stale data | Register it again with the new options before lib.showContext |
inputDialog returns nil |
The player cancelled: check for nil |
| Icon does not appear | Use a valid Font Awesome name, or a full class like fa-solid fa-car |
Quick answers
Why is lib nil in my script?
Your manifest does not load ox_lib's init file. Add shared_script '@ox_lib/init.lua' and make sure ox_lib starts before your resource.
How do I make a submenu?
Register a second context with its own id, then give the option in the first menu menu = 'second_id'. Set menu = 'first_id' on the second so it gets a back button.
How do I read what the player typed?
lib.inputDialog returns a table with one value per row, in order, or nil if the player cancelled. Always check for nil.
Scripts that skip this problem
Item Creator V2Create usable items with animations, props, effects and more β without writing code.View script β
Shop CreatorBuild a shop in under a minute β owners, employees, vaults and robberies included.View script β
Quest CreatorA visual editor for quests and NPC dialogues, built node by node in game.View script β