Введите и измените sh предложения в <datalist>? - PullRequest
1 голос
/ 04 февраля 2020

Я строю выпадающий ввод с предложениями. Есть миллионы предложений. Я хочу показать первые 50 предложений. И пользователи могут вводить больше символов, чтобы сузить предложения.

Как реализовать это с помощью Blazor (на стороне сервера)?

<datalist id="suggestions">
    @foreach (var b in list.Where(x => x.Name.StartWith(theValueEntered).Take(50)) // list has millions records, which is stored in database.
    {
        <option value="@b.Value">@b.Text</option>
    }
</datalist>
<input autoComplete="on" list="suggestions" />

1 Ответ

2 голосов
/ 04 февраля 2020

Примерно так:

@inject DbContext dbContext; // your EF DbContext to access your data

<datalist id="suggestions">
    @foreach (var b in filteredList)
    {
        <option value="@b.Value">@b.Text</option>
    }
</datalist>
<input autoComplete="on" list="suggestions" value="@theValueEntered"
               @oninput="OnInputChanged"
               @onfocus='() => OnInputChanged(new ChangeEventArgs { Value = "" })'/>

@code {
    private string theValueEntered;
    private IEnumerable<Data> filteredList;

    private async Task OnInputChanged(ChangeEventArgs e)
    {
        theValueEntered = e.Value as string;
        filteredList = await dbContext.Data
           .Where(x => x.Name.StartWith(theValueEntered)
           .Take(50)
           .ToListAsync()
           .ConfigureAwait(false);
        StateHasChanged();
    }
}

Если вы хотите ограничить количество запросов к вашей базе данных, вы можете использовать Task.Delay

// with the same html code
@inject IServiceProvider provider; // get a provider instance

@code {
    private CancellationTokenSource cancellationTokenSource;
    private string theValueEntered;
    private IEnumerable<Data> filteredList;

    private Task OnInputChanged(ChangeEventArgs e)
    {
        theValueEntered = e.Value as string;
        cancellationTokenSource?.Cancel();
        cancellationTokenSource?.Dispose();
        cancellationTokenSource = new CancellationTokenSource();
        var token = _cancellationTokenSource.Token;

        return Task.Delay(250, token)
                   .ContinueWith(async task =>
                   {
                        if (task.IsCanceled)
                        {
                            return;
                        }        

                        using var scope = provider.CreateScope();
                        var context = scope.GetRequiredService<DbContext>();
                        filteredList = await context.Data
                            .Where(x => x.Name.StartWith(theValueEntered)
                            .Take(50)
                            .ToListAsync()
                            .ConfigureAwait(false);
                        await InvokeAsync(StateHasChanged);
                    }, TaskScheduler.Default);
    }
}

...