Placeholders
Placeholders are dynamic values that get replaced at runtime. Use them in templates and commands to show player data.
Built-in Placeholders
Framework Placeholders
These require a framework (qb-core, qbx_core, or es_extended):
Masked Placeholders
Show "Anonymous" if player is wearing a mask:
Friends Placeholders
Only show data to friends:
Server Placeholders
Self Placeholders
Message sender info:
Using Placeholders in Templates
In Static Text
T.text('Player {Placeholder:ServerId}')
In Author Field
In Message Content
Placeholders work anywhere in text:
T.message()
-- Shows message with placeholder values
Server-Side Resolution
For dont_register: templates, placeholders are resolved on the server:
Config.Theme['dont_register:job_ad'] = T.build()
:text('Hiring for {Framework.Functions.GetJobLabel}', { bold = true })
:message()
:done()
The server processes {Framework.Functions.GetJobLabel} before sending to clients.
Creating Custom Placeholders
Add custom placeholders in config/placeholders.lua:
Client-Side Placeholder
-- client/custom/placeholder.lua
Client.Custom["Placeholder"]["MyCustom"] = function(placeholder, orTable, args)
return "Custom value"
end
-- Usage in template:
T.text('Custom: {Placeholder:MyCustom}')
Server-Side Placeholder
-- server/placeholders.lua
Server.Custom["Placeholder"]["MyCustom"] = function(placeholder, orTable, args)
return "Server value"
end
-- Usage (dont_register template only):
T.text('Custom: {Placeholder:MyCustom}')
Framework-Based Placeholder
Client.Custom["Placeholder"]["Health"] = function(placeholder, orTable, args)
local health = GetEntityHealth(PlayerPedId())
return tostring(health)
end
-- Usage:
T.text(' [HP: {Placeholder:Health}]')
With Arguments
Client.Custom["Placeholder"]["JobGrade"] = function(placeholder, orTable, args)
-- args contains information from the placeholder itself
local framework = Framework.Functions.GetPlayerData()
return tostring(framework.job.grade.level or 0)
end
Example: Complete Custom Placeholder
-- In config/placeholders.lua
Client.Custom["Placeholder"]["Distance"] = function(placeholder, orTable, args)
-- Get current player position
local ped = PlayerPedId()
local playerCoords = GetEntityCoords(ped)
-- Get target coords from args (if provided)
-- This would be passed from the command handler
if args and args[1] then
local targetCoords = json.decode(args[1])
local distance = #(playerCoords - targetCoords)
return string.format("%.1f m", distance)
end
return "N/A"
end
-- Usage:
Commands.client("distance", {
handler = function(ctx)
local playerCoords = GetEntityCoords(PlayerPedId())
TriggerEvent('chat:addMessage', {
template = HTML.createTemplate(T.build()
:tag('DISTANCE')
:text(': {Placeholder:Distance}')
:done()),
args = { json.encode(playerCoords) }
})
end,
})
Conditional Placeholders
For complex logic, use buildText in commands:
Commands.client("status", {
handler = function(ctx)
local health = GetEntityHealth(PlayerPedId())
local healthText = health > 100 and "Healthy" or "Injured"
TriggerEvent('chat:addMessage', {
templateId = 'cmd:me',
args = { ctx.author, "is " .. healthText }
})
end,
})
Placeholder Syntax
Different placeholder types:
{Framework:GetName} -- Framework method
{Framework.Functions.GetPlayerName} -- Nested functions
{Placeholder:ServerId} -- Placeholder group
{Masked:Framework:GetJob} -- Masked modifier
{Friends:Framework:GetName} -- Friends modifier
{Self:GetArgs} -- Self reference
Escaping Placeholders
Prevent placeholder substitution by using different syntax:
-- This WILL be replaced:
T.text('Hello {Framework:GetName}')
-- To prevent, you must remove the placeholder:
T.text('Hello World')