bind-Value is not updating the textbox programmatically

I have the following complete razor page:

@page "/test"
@using System.Text
<RadzenBody>
    <RadzenTextBox @bind-Value=@myText class="w-100 rz-text-uppercase" @oninput=@(args => HandleInput(args.Value.ToString())) />
</RadzenBody>

@code {
    string myText = string.Empty;

    private async void HandleInput(string inputText)
    {
        myText = NormalizeString(inputText);
        StateHasChanged();
        Console.WriteLine(myText);
    }

    public static string NormalizeString(string stringToNormalize)
    {
        string output = "";
        foreach (var chr in stringToNormalize.Normalize(NormalizationForm.FormD))
        {
            if (Char.ToUpper(chr) >= 'A' && Char.ToUpper(chr) <= 'Z' || chr == ' ')
            {
                output += chr;
            }
        }
        return output.ToUpper();
    }
}

The code allows only letters from A to Z and space to be inserted into the TextBox, the code works as expected, but the text that is visible in the TextBox is only updated when the variable value changes.
You can see it in the following image:


The text inside the TextBox matches the variable value, as all keystrokes are valid and update the variable value.
But if we insert some numbers, which are invalid according to the code, the variable does not have its value changed and the TextBox is not invoked so that its text corresponds with the new value of the variable, as shown in the following image:

Note that 1 space and 6 more numbers were entered, in this case, the value of the variable for each of the numbers never changed, as the last valid change was when the space was inserted.

If I simply press a valid key, in this case any letter, the TextBox value is now updated according to the variable value, removing the numeric digits that were only present in the TextBox but did not correspond to the variable value.

In other words, I want that when I type an invalid character in the TextBox, the code will remove such characters and save it in the variable that is binding and the TextBox would have its value updated programmatically.
Is there any way to force the TextBox to update even when the variable value remains the same?
Thank you for your help in advance.

Using async void can definitely lead to such problems. Here is how your code should look:

@using System.Text
<RadzenBody>
    <RadzenTextBox @bind-Value=@myText class="w-100 rz-text-uppercase" @oninput=@HandleInput />
</RadzenBody>

@code {
    string myText = string.Empty;

    private async Task HandleInput(ChangeEventArgs args)
    {
        myText = NormalizeString(args.Value.ToString());
        Console.WriteLine(myText);
    }

    public static string NormalizeString(string stringToNormalize)
    {
        string output = "";
        foreach (var chr in stringToNormalize.Normalize(NormalizationForm.FormD))
        {
            if (Char.ToUpper(chr) >= 'A' && Char.ToUpper(chr) <= 'Z' || chr == ' ')
            {
                output += chr;
            }
        }
        return output.ToUpper();
    }
}

Thank you, @enchev for the quick response!
However, the result still remains the same... Even using your code, the TextBox is still not updated with each key pressed, it is only updated when a valid key is pressed, as apparently the TextBox only has its content updated when the variable myText changes value.

For example:
if I type:
A
the TextBox will show: A
myText will contain: A

If I type the Ç key in sequence
the TextBox will show: AC
myText will contain: AC

However, if I type, for example, the number 2...
the TextBox will show: AC2
myText will contain: AC

I need the TextBox to update with each key pressed, according to the value of myText and not show invalid digits, regardless of whether the variable value has changed or not.

I'm not finding a way to do this.

I managed to find a workaround... maybe it's not the most suitable, but so far it's the only way that worked:

@page "/test"
@using System.Text
@inject IJSRuntime JsRuntime;

<RadzenBody>
    <RadzenTextBox id="tb1" class="w-100 rz-text-uppercase" @oninput="@HandleInput" />
</RadzenBody>

@code {
    private string myText = string.Empty;

    private async Task HandleInput(ChangeEventArgs args)
    {
        myText = NormalizeString(args.Value.ToString());

        await Task.Delay(1); 
        await JsRuntime.InvokeVoidAsync("Radzen.setInputValue", "tb1", myText);
    }

    private static string NormalizeString(string stringToNormalize)
    {
        StringBuilder output = new StringBuilder();
        foreach (var chr in stringToNormalize.Normalize(NormalizationForm.FormD))
        {
            if (Char.ToUpper(chr) >= 'A' && Char.ToUpper(chr) <= 'Z' || chr == ' ')
            {
                output.Append(chr);
            }
        }
        return output.ToString().ToUpper();
    }
}

Thanks to your help, I was able to locate myself and find a way to do this. Thanks

1 Like