'Reset <input> text after @onchange

I'm building a blazor component that will revert back to the original input if the entered text is not valid. Since ValueText doesn't change the rendering process won't update it/replace user input.

<input type="text"
       value="@ValueText"
       @onchange="TextChanged" />

Calling StateHasChanged() won't change the result.

In my case ValueText is always empty. The workaround has been to alternate between null and "" that will cause the input to be reset.

Is there a method to mark the element attribute as "dirty" so the blazor rendering will refresh the DOM even though the virtual DOM is not changed?



Solution 1:[1]

Alternate the value set to ValueText.
This will cause a change in the virtual DOM and cause the DOM to be updated.
By using a special non-printable unicode character it won't affect the visual or interactive behavior.
Since the event can be triggered several times before the diff algorithm is executed we can't rely on a single swap between two values, here I have choosen the arbitrary 10 number of alternative values.

Eventually with #17281 it wont be needed anymore.

Make sure to remove workaroundChar when parsing the input.

Instead of

ValueText = "";

use

    int workaroundIndex = 0;
    const string workaroundChar = "\u00AD";

    void SetValueText(string? text)
    {
            //Special case for empty values, otherwise the unicode character will hide the placeholder.
            if (string.IsNullOrWhiteSpace(text))
            {
                if (text == null)
                    ValueText = "";
                else
                    ValueText = null;
                return;
            }

            string w = "";
            for (int n = 0; n < workaroundIndex; n++)
                w += workaroundChar;

            ValueText = text + w;

            workaroundIndex = (workaroundIndex + 1) % 10;
    }
}

Solution 2:[2]

When you set an attribute value in Blazor (or Razor) and the value is null then the attribute is removed. Hence value=@ValueText would not update the value.

Setting the value to an empty string fixes this:

<input type="text" value=@ValueText @onchange="TextChanged" />
@if (isValid)
{
    <span class="text-success">?</span>
}
<p>
    Current value is: @ValueText
</p>

@code
{
    string ValueText = null;
    bool isValid = false;

    void TextChanged(ChangeEventArgs e)
    {
        // only accept values starting with 'a'
        string newValue = (string)e.Value;
        if (!string.IsNullOrEmpty(newValue) && newValue.StartsWith('a'))
        {
            // accept
            ValueText = newValue;
            isValid = true;
        }
        else
        {
            ValueText = "";
            isValid = false;
        }
    }
}

This example will only permit a value that starts with 'a':

demo showing accepted value

Solution 3:[3]

ValueText  = "";
await Task.Delay(1); //Magic!  
StateHasChanged();
ValueText  = value;
StateHasChanged();

thanks for https://github.com/dotnet/aspnetcore/issues/17281#issuecomment-620541274

Solution 4:[4]

You have to create an input value property, customize its setter, and add a field to store the value

In Your HTML section

<input @bind=@inputBindValue /> 

Then in the @code section

  private string _privateValue = string.Empty;

private string inputBindValue
{
    get => _privateValue;

    set
    {
        if( InputIsValid(value) ) return; // check if valid - if yes, then do nothing

        // do stuff if input value is not valid

        _privateValue = string.Empty; // empty Your input field value
    }
}

Solution 5:[5]

KISS - Keep It Simple...

HTML:

<input type="file" value="@_fileValue"@onchange="async () => await OpenFileAsync()" />

Code:

fileValue = _fileValue == null ? "" : null;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Quango
Solution 3 W.S. KK
Solution 4 chmur300
Solution 5 eshirvana