Blazor Virtualize update when request change

Viewed 1298

I have a component that display many athletes from a database up to 200000. It work well but when I added a select with a list of countries tou filter result I can see the result count updated but the Virtualize component is not updated until I scroll ?

@page "/persons"
@inject HttpClient Http


<div class="container-fluid">
    <div class="row">
        <div class="col-12">
            <h1>@($"{totalindividu:### ### ##0}") athletes linked</h1>
        </div>
    </div>
    <div class="row">
        <div class="col-4">
            <select class="form-control" @onchange="ChangePays">
                <option value="-1" selected>Pas de sélection sur le pays</option>
                @if (pays != null)
                {
                    @foreach (var p in pays)
                    {
                    <option value="@p.aatpays_id">@p.aaipays_nom</option>
                    }
                }
            </select>
        </div>
        <div class="col-4">&nbsp;</div>
        <div class="col-4"><p>@selpays</p></div>
    </div>
    <div class="row">
        <div class="col-12">
            <table class="table">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Code</th>
                        <th>Nom long</th>
                        <th>Pays</th>
                        <th>Discipline</th>
                        <th>Date de naissance</th>
                    </tr>
                </thead>
                <tbody>
                    <Virtualize Context="individu" ItemsProvider="@LoadIndividus">
                        <ItemContent>
                            <tr>
                                <td style="width: 100px">@individu.aatindividu_id</td>
                                <td style="width: 100px">@individu.aalindividu_code</td>
                                <td>@individu.aaiindividu_nomLong</td>
                                <td style="width: 200px">@individu.aaipays_nom</td>
                                <td style="width: 200px">@individu.aaidiscipline_nom</td>
                                <td style="width: 100px">@individu.aatindividu_dateNaissance</td>
                            </tr>
                        </ItemContent>
                        <Placeholder>
                            <tr>
                                <td style="width: 100px">Loading...</td>
                                <td style="width: 100px">Loading...</td>
                                <td>Loading...</td>
                                <td style="width: 200px">Loading...</td>
                                <td style="width: 200px">Loading...</td>
                                <td style="width: 100px">Loading...</td>
                            </tr>
                        </Placeholder>
                    </Virtualize>
                </tbody>
            </table>
        </div>
    </div>
</div>

@code {
    private int totalindividu = 0;
    private string selpays = "-1";
    private BdsPays[] pays = null;
    private BdsIndividu[] individus = null;

    protected override async Task OnInitializedAsync()
    {
        pays = await Http.GetFromJsonAsync<BdsPays[]>("api/BdsAa/pays/1");
        //individus = await LoadIndividus(0, 50);
    }

    private async Task<BdsIndividu[]> LoadIndividus(int start, int count)
    {
        totalindividu = await Http.GetFromJsonAsync<int>($"api/BdsAa/individusinoutcount/1/33/{selpays}");
        individus = await Http.GetFromJsonAsync<BdsIndividu[]>($"api/BdsAa/individusinout/1/33/{start}/{count}/{selpays}");
        return individus;
    }

    private async ValueTask<ItemsProviderResult<BdsIndividu>> LoadIndividus(ItemsProviderRequest request)
    {
        individus = await LoadIndividus(request.StartIndex, request.Count);
        StateHasChanged();
        return new ItemsProviderResult<BdsIndividu>(individus, totalindividu);
    }

    private async Task ChangePays(ChangeEventArgs e)
    {
        selpays = e.Value.ToString();
        individus = null;
        StateHasChanged();
    }
}

Any idea to force update of table when my filter change ?

Jean

3 Answers

You should be able to call RefreshDataAsync() as follows.

From GitHub issue where this functionality was added

For the more general case where the developer uses ItemsProvider, we should add a new public async Task RefreshDataAsync method on Virtualize. Developers can call this if they have reason to think the underlying data source output may have changed, for example when a user clicks a "Refresh" button. This would just do the same thing that happens when the user scrolls into a new set of data.

To expand a little on Mike's post, you'll need to add a reference to your Virtualize component like this:

<Virtualize @ref="ArticleContainer" ItemsProvider="LoadArticles">
[...]
</Virtualize>

@code {
    private Virtualize<Article> ArticleContainer { get; set; }
}

With the reference, you can then trigger a refresh. Note that this does not cause the component to render again (if it's async!), you will have to call StateHasChanged() as well.

private async Task ReloadArticles()
{
    await ArticleContainer.RefreshDataAsync();
    StateHasChanged();
}

Just label your Virtualize with @ref and perform your OnInput event to refreshdataasync on your ref

<div class="form-floating">
 <input class="form-control" value="@FilterInvoice" type="text" 
 placeholder="Filter Invoice..." id="idfilterInvoice"                       
 @oninput="@FilterChangeInvoice">
 <label for="idfilterInvoice">Filter Invoice</label>
 </div>

 <Virtualize @ref="ordersContainer" ItemsProvider="LoadOrders" 
 Context="..." >
 [...]
 </Virtualize>

@code {
    private Virtualize<Order> ordersContainer { get; set; }
    private Order _order = new Order();

    private async Task FilterChangeInvoice(ChangeEventArgs args)
    {
        FilterInvoice = args.Value.ToString();
        await ordersContainer.RefreshDataAsync();
         StateHasChanged();    
    }

        private async ValueTask<ItemsProviderResult<Order>> LoadOrders(ItemsProviderRequest request)
    { ....}
}
Related