On-the-fly Masks and Formats for TextBoxes
Did you know you can manipulate/restrict what a user types into a TextBox on the fly? This is commonly referred to as “masking.” I’ve seen a lot of games on here that could use it, and it’s actually quite easy to do.
How it works:
All you have to do is listen for the Text property to change using GetPropertyChangedSignal("Text")
, then check the Text property and change it accordingly.
For instance, if we want to only allow the user to type in positive integer values, we can restrict this by removing any non-digit characters from the input:
function PositiveIntegerMask(text)
return text:gsub("%D+", "")
end
textBox:GetPropertyChangedSignal("Text"):Connect(function()
-- Replace the text with the formatted text:
textBox.Text = PositiveIntegerMask(textbox.Text)
end)
What’s cool is that the user will not be able to type any non-digit characters into the textbox! Well, kinda… It’s more like a nifty trick. Technically they are typing in non-digit characters, but we’re quickly masking the input directly afterward. To the user, it appears as if typing non-digit characters doesn’t even work.
Note: In the case of some masks, the masking might need a “fail” option, thus you need to return the text to the last valid input. An easy way to do this is to keep a variable of the last valid text (defaulting to whatever starts out in the Text property). If the mask returns nil
, then simply use the last valid input as the text. If the mask works, replace the last valid input with the mask before setting the Text property again.
See the last phone number mask snippet for an example of the above note.
Here’s a couple other nifty masks that you might want to use. At the end of the day, it’s really just string patterns being utilized on the fly:
Examples
Only allow alphanumeric, spaces, and underscores:
function AlphanumericAndUnderscoreAndSpace(text)
return text:gsub("[^%w%s_]+", "")
end
textBox:GetPropertyChangedSignal("Text"):Connect(function()
textBox.Text = AlphanumericAndUnderscoreAndSpace(textBox.Text)
end)
Turn the input into upper-case:
function MakeUppercase(text)
return text:upper()
end
textBox:GetPropertyChangedSignal("Text"):Connect(function()
textBox.Text = MakeUppercase(textBox.Text)
end)
Only allow upper-case (note that this only allows upper-case. The last example simply turns it into upper-case):
function OnlyUppercase(text)
return text:gsub("%U+", "")
end
textBox:GetPropertyChangedSignal("Text"):Connect(function()
textBox.Text = OnlyUppercase(textBox.Text)
end)
Don’t allow spaces:
function NoSpaces(text)
return text:gsub("%s+", "")
end
textBox:GetPropertyChangedSignal("Text"):Connect(function()
textBox.Text = NoSpaces(textBox.Text)
end)
Format 7-digit and 10-digit phone numbers. Obviously not applicable for ROBLOX, but still cool. It’s a little more complicated though. Perhaps there’s an easier way to do this:
function PhoneNumberMask(text)
if (text == "") then return "" end
local t = text:gsub("%D+", "")
local n = tonumber(t)
if (not n) then return nil end
n = tostring(n)
if (#n > 10) then return nil end
if (#n > 7) then
return "(" .. n:sub(1, 3) .. ") " .. n:sub(4, 6) .. "-" .. n:sub(7)
elseif (#n > 3) then
return n:sub(1, 3) .. "-" .. n:sub(4)
else
return n
end
end
local lastValidText = ""
textBox:GetPropertyChangedSignal("Text"):Connect(function()
if (textBox.Text == lastValidText) then return end
local text = PhoneNumberMask(textBox.Text)
if (text) then
lastValidText = text
textBox.Text = text
else
textBox.Text = lastValidText
end
end)
Note: Masking doesn’t mean that the input will be valid! It simply tries to restrict the user from most invalid stuff. A good trick is to use masking to make the text as well-formatted as possible on-the-fly, and then use validation when the input loses focus.
Another Note: You can string together multiple masks in order to get more complicated things done. Just make sure the masks don’t conflict with each other.
Disclaimer: Always validate input on the client and the server!