Two-way data binding with async call on change

Viewed 598

The problem is that this seems to be very hard to achieve the following scenario in Blazor: Having a filter, that when changed calls an async function to update some data.

The typical bind does not work, as the property FilterX can not call async methods:

<input type="text" @bind="@FilterX" />

If changed to the following, async methods can be called, but two-way binding is lost. If, for example, an invalid value is entered into the input, the value cannot be reverted by code.

<input type="text" value="@FilterX" @onchange="@FilterXChangedAsync"/>

Is there any elegant way to solve this?

2 Answers

You should use @bind-Value="FilterX"

Then add this in the code

public virtual string Value
{
    get { return value; }
    set
    {
        if (this.value == value)
        {
           return;
        }
        this.value = value;
        if (ValueChanged.HasDelegate)
        {
            ValueChanged.InvokeAsync(value);
        }
    }
}

public virtual EventCallback<string> ValueChanged { get; set; }

If you want to change your bound value to update on input you can do this:

<input type="text" @bind-Value="FilterX" @bind:event="oninput" />

You can use @() in the html part. The compiler will interpet this as C# code that needs to be run. What I did here was created an async lambda expression where you can use the await.

<input type="text" value="@FilterX" @onchange="@(async e => await FilterXChangedAsync(e))"/>

async Task FilterXChangedAsync(EventArgs args)
{
   var eventValueAsString = e.Value.ToString();
}
Related