How do I unselect all of the text in a TextField after it gains focus

Me again. When I select the text field in my subtask, Unity highlights all of the text. I want to instead just move the cursor to the end of the text (already accidentally deleted all of the text during development). I tried using

taskItem.TaskItemDetails.SelectRange(taskItem.TaskItemDetails.text.Length-1, taskItem.TaskItemDetails.text.Length-1);

But this doesn’t work. I think it’s just a Unity bug, because

taskItem.TaskItemDetails.SelectRange(1,2);

doesn’t change the selection either.
Am I using SelectRange incorrectly?

I’m assuming you’re attempting this in the `RegisterCallback()’ callback, as this makes the most sense.
I tried this myself, and got similarly mystifying results. I was able to confirm that the callback was executed when I clicked within the text box, but got no apparent response to the SelectRange.

I suspect what is happening is that this callback is being called first, then a built in callback is coming in and selecting the whole field… like a race condition. More research is needed.

Howdy Brian,
Yes, you are correct, using the FocusEvent:

 taskItem.TaskItemDetails.RegisterCallback<FocusEvent>(delegate {TaskItemFocused(taskItem);});

I know the callback works, because i highlight the task that has focus (and similarly, go back to normal when it loses focus).

I hope you can find a fix, because hitting any key while the text is highlighted replaces it. Not fun. I can’t find anything using web searches…not about this specifically.

As an aside, I can’t get .Trim() to work properly, either. I use tab to leave the textfield and trigger saving the task details, but I first strip off the tab…supposedly. .Trim() will strip every tab AFTER the first tab, but always leaves the first tab (at the end of the string). Any ideas about that one?

After a deep search on the Unity forum, I was able to find questions about preventing focus auto selecting the text, but in every case the question was met with crickets. This looks like something Unity just hasn’t bothered to fix yet. The more I look at it, the less likely I think they are going to. Right now, the regular inspector is behaving exactly the same way.

For the tabs, have you tried Replace?

string filteredString = originalString.Replace("\t", ""); //originalString is untouched

Thanks, Brian. That didn’t work either. Maybe it’s the way I’m trying to use it:

taskItem.TaskItemDetails.value = taskItem.TaskItemDetails.text.Replace("\t","");

Hmmm. I figured I could test this myself, and did this after I tab out of the Details textfield:

taskItem.TaskItemDetails.value = "new details";

and guess what? The text field becomes "new details " - with the tab still there. I think there’s two layers to the TextField, and the underlying layer is wrapping the field, and it’s the part retaining the tab. The mystery deepens.

Hmmm, I hadn’t even noticed it was pushing a tab in there when you press it. It shouldn’t, as the behavior should already be that a tab moves to the next control.

Here’s a quick and dirty solution:

            displayNameTextField.RegisterValueChangedCallback((evt) =>
            {
                if (evt.newValue.Contains("\t"))
                {
                    string newValue = evt.newValue.Replace("\t", "");
                    displayNameTextField.SetValueWithoutNotify(newValue);
                }
            });

Between the testing for the escaped tab and using SetValueWithoutNotify, it should avoid recursion, and appears to let me tab automatically in the inspector to the next field.

Note that this still doesn’t fix the selection issue.

Thanks, Brian. It gets weirder. I noticed you can access the field using .text or .value, so I wanted to know what the difference was, and if that was related to the issue. The code I used was:

void UpdateTask(KeyDownEvent e, TaskItem taskItem){
    //if (e.keyCode != KeyCode.Return) return;
    if (e.keyCode != KeyCode.Tab) return;
       Debug.Log("Before:  Details value: ***" + taskItem.TaskItemDetails.value + "***");
       Debug.Log("Before:  Details text: ***" + taskItem.TaskItemDetails.text + "***");
       taskItem.TaskItemDetails.value = taskItem.TaskItemDetails.text.Trim();
       taskItem.TaskItemDetails.value = taskItem.TaskItemDetails.text.Replace("\t","");
       Debug.Log("After:  Details value: ***" + taskItem.TaskItemDetails.value + "***");
       Debug.Log("After:  Details text: ***" + taskItem.TaskItemDetails.text + "***");
       UpdateTask(taskItem);
       addTaskText.Focus();
    }
}

and here’s the output (when I create a new task, the default details are “blah, blah, blah”):

Before:  Details value: ***blah, blah, blah***
Before:  Details text: ***This is the original text.***
After:  Details value: ***This is the original text.***
After:  Details text: ***This is the original text.***

What’s so weird is that if I stored the .value of the field…it would be wrong - the old value. I have to use .text to get the correct text, even though the documentation says to use the value. Also, I noticed that the tab isn’t in either .text or .value…it’s just in the field. So at least the Details in the SO are correct. BTW, the TextField has the value method, while the underlying/parent TextInputBaseField has the text method, which has a protected setter.

Update: This got me curious and I checked my UpdateTask(taskItem) method, and I was using .value…and my tasks weren’t updating properly. I changed my method to use .text. This is a serious Unity bug. Folks expect value to return the full, current contents of the TextField. Guess I’ll file a bug report.

Update 2: Getting sick of this. In my UpdateTask I had a .Trim(), so I removed it since it appeared that the tab wasn’t actually there…and my SO Details now had a tab in it. So the tab IS actually there, and apparently Debug.Log strips it. Didn’t catch this previously because I was using Debug statements in the console to check whether updating worked correctly. It lied to me.

ouch, I’ve led myself down a few wrong paths myself with Debug statements, and I’m a Debug.Log ninja.

In terms of value vs text, your event is likely intercepting the keystroke before the value is set. The most reliable (and recommended) method of brokering the true value is in a RegisterValueChangedCallback() method. If you’ll look at my example above, I used a lambda expression, but you can assign a formal method with proper type of ChangeEvent (in this case string). In my lambda expression, evt is the actual event.

evt.newValue is the correct new value.
evt.oldValue is the value before the change event.

Of course, this doesn’t let you capture keystrokes, and it also doesn’t work to trap the change to the TextField when we’re adding a new task, but it’s something important to know going forward with other things like actual Custom Editors and Property Fields.

I didn’t consider I may be grabbing the value before it’s updated (although .text is in the parent, and it is updated). I know events bubble up, and bubble down (is that it?), but I haven’t looked into that. I do want to capture the keystrokes, so is there a way to catch the event later, AFTER the value got updated( on the bubbled up/down)? Of course, just using .text instead of .value is working fine…other than that stinkin’ tab.

Update. I don’t think this is the problem, as I get the same results from checking the Details TextField after it loses focus, instead of catching the tab. At least this way, there’s no tab when I return.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms