Partitioning an input field into separate input fields

Hello.

I’ve been working on a single text field GUI where the text fields are separated, kind of like an OTP input field.

The GUI consists of 5 text boxes that are connected to the GuiObject.Changed event. So if any text gets added or removed, the event fires. At the same time I’m checking which one of the 5 is focused by using the TextBox.Focused event so I can CaptureFocus() of the next/previous text field.

Now, to the issue. I can not CaptureFocus() of a previous text field if the current one’s text is empty by pressing backspace, the event doesn’t fire. The event fires only when there’s text in the first place.

There are ways around this issue of course, UserInputService for instance, but then I’d be facing another issue. On Windows/Mac there’s a keyboard property called “Character Repeat”, for example, the longer you hold backspace the faster characters get deleted. But by using UserInputService I’d make my life way more difficult. Also by using while loops, things get out of order, sometimes 2-3 characters get deleted at once and it gets counterintuitive by making the player wait.

TL;DR: Is there a way to get a GuiObject.Changed event just by pressing backspace on an empty text field?

GIF of my text field GUI:
Animation

I did something similar to this, here was my solution to the issue:

local function InputBegan(input, gameProcessed)
	if input.UserInputType == Enum.UserInputType.Keyboard then
		if input.KeyCode == Enum.KeyCode.Backspace then
			if TextBoxes[2]:IsFocused() then
				if TextInChat[2]:len() == 0 then
					TextBoxes[1]:CaptureFocus()
				end
			elseif TextBoxes[3]:IsFocused() then
				if TextInChat[3]:len() == 0 then
					TextBoxes[2]:CaptureFocus()
				end
			elseif TextBoxes[4]:IsFocused() then
				if TextInChat[4]:len() == 0 then
					TextBoxes[3]:CaptureFocus()
				end
			end
		end
	end
end

If you wanted to add to that and incorporate Character Repeat functionality, I don’t think that would be too hard, but it would be difficult as you said. The answer to your TL;DR question, is no as far as I no. The main property I could think of as changing would be Text, but pressing backspace on an empty field doesn’t change the text.

This is indeed the more counterintuitive solution that I’ve also found. Overall the GuiObject.Changed event works best, but goes only halfway. Thanks though.

GuiObject.InputEnded exists.

https://developer.roblox.com/en-us/api-reference/event/GuiObject/InputEnded

local TextBox = script.Parent

TextBox.InputEnded:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.Backspace then
		print("Backspace pressed!")
	end
end)

I’ve tried using GuiObject.InputEnded before and likely everything else the Roblox API has to offer.

I found that it is ultimately a bad choice, especially when typing fast. Either the input registers for an unintended input field (input field skipping), or you’d have to make the player wait, which, again, is a poor implementation.

Solved by adding an empty space to every field.