Avoid user typing delay in input textfield box mudblazor blazor c#

Viewed 604

I have a mud blazor grid with pagination/global search. The search functionality works as expected when I test it in my local i.e it filters out the grid as soon as the user types in something and it seems to be really fast. The problem occurs when I host it to dev/stage server. The user input is delayed. Also, it works fine if the input is entered slowly. For instance, if I try to enter "test" into the searchbox quite fast then it always misses 1 or 2 characters and prints it as "tst" even though I've typed all the characters carefully. The pointer flickers very frequently on pressing backspace.

I tried to clear the cache but still doesn't work after hosting whereas no such problem occurs when doing the above in my local env.

I can't figure out what have I done wrong as in why the performance is affected. Note: I'm loading the dataset at once from db (inside onInitialized())

The code:

Index.razor

<MudTable Items="CustomersWithOrderInfo" ServerData="new Func<TableState, Task<TableData<Data.Models.CustomerOrderInfoDTO>>>(LoadCustomers)" FixedHeader="true" FixedFooter="true" Class="table table-hover" Style="box-shadow:none !important;" @ref="table" Height="530px">
                        <ToolBarContent>
                            <div class="input-group mb-3" style="width:35%;">
                                <input type="text" class="form-control" placeholder="Search" value="@searchString" @oninput="@FilterChanged">
                                <div class="input-group-append">
                                    <span class="input-group-text bg-primary" id="basic-addon1"><i class="fa fa-search fa-lg fa-charade text-white" style="font-size:small;"></i></span>
                                </div>
                            </div>
                            <br />
                        </ToolBarContent>
                        <HeaderContent>
                            <MudTh Style="font-weight: bold;width:12%;">Customer Id</MudTh>
                            <MudTh Style="font-weight: bold;width:13%">Customer Name</MudTh>
                             ....
                            <MudTh Style="font-weight: bold;width:8%;">Actions</MudTh>
                        </HeaderContent>
                        <RowTemplate>
                                                 
                            <MudTd DataLabel="Customer Id">@context.CustomerId</MudTd>
                            <MudTd DataLabel="Customer Name">@context.CustomerName</MudTd>
                             ....
                            <MudTd DataLabel="Active">@context.IsActive</MudTd>
                            <MudTd DataLabel="">
                            
                               ...
                            </MudTd>
                        </RowTemplate>
                        <PagerContent>
                            <MudTablePager PageSizeOptions="pageSizes" />
                        </PagerContent>
                    </MudTable>

IndexBase.cs

 protected void FilterChanged(ChangeEventArgs args)
        {
            searchString = args.Value.ToString();
            table.ReloadServerData();
        }
protected async Task<TableData<CustomerOrderInfoDTO>> LoadCustomers(TableState tableState)
        {
            IEnumerable<CustomerOrderInfoDTO> data = CustomersWithOrderInfo.OrderByDescending(q => q.CustomerId);
            data = data.Where(p =>
            {
                if (string.IsNullOrWhiteSpace(searchString))
                    return true;
               
                if (!string.IsNullOrEmpty(p.CustomerName) && p.CustomerName.Contains(searchString, StringComparison.OrdinalIgnoreCase))
                    return true;
               
                if ($"{p.CustomerId}".Contains(searchString))
                    return true;
                return false;

            }).ToArray();
            totalItems = data.Count();
            pagedData = data.Skip(tableState.Page * tableState.PageSize).Take(tableState.PageSize).ToArray();
            return new TableData<CustomerOrderInfoDTO>() { TotalItems = totalItems, Items = pagedData };
        }
2 Answers

I think this is because you used @oninput="@FilterChanged", this means this will execute FilterChanged every time you type a character. Since FilterChanged is a function that takes some time, this creates some lags to the UI while it executes.

Try replacing @oninput="@FilterChanged" by @onchange="@FilterChanged". This will execute FilterChanged when the element loses focus.

Another possibility would be to add a button or to execute when Enter key is pressed.

See the doc.

I had exactly the same issue on Ant Blazor. Typing is fine if slow, but if I type quickly characters start getting dropped. The fix is super easy: add DebounceMilliseconds="1000" to your input component.

For example <input DebounceMilliseconds="1000" type="text" class="form-control" placeholder="Search" value="@searchString" @oninput="@FilterChanged">

Explanation on why it works (credit to https://github.com/ant-design-blazor/ant-design-blazor/issues/1283#issuecomment-810108270):

Due to the way inputs work, the string that is 2 way-bounded from the input form gets updated from the string to the text box.

In a Blazor Server scenario, with latency being a thing (imagine 200ms for an average request), if you send multiple updates to the server, they will respond back to you with state, but you already typed more.

One way to fix this is to set the debounce time to be 1 or 2+ seconds

  • such that with slow internet no request will be sent while typing is happening.

If you are using an enter key or button to submit/search etc - you may use an absurdly large debounce time, as the onblur event will cause an update (think tabbing out, clicking somewhere else).

Related