hydeinthesky29
hydeinthesky29

Reputation: 177

Blazor Server Side - Load more 50 data

Good Day Everyone

I'm creating a Blazor Server Side application with card style on my home page, I did not use javascript on loading those data, it's just simple razor and c#. Now it loads almost 2000+ data, this makes my app slow, so what I want to do is to load 50 data first, then there is a load more below that will load 50 data, my idea is to insert the 50 on the object where the first 50 is, but I think this will also cause a bulk on the data projected on the page, and it might cause a problem if it reaches a 3000+, is there a way to do this on the Blazor Server-Side?

Thanks and regards

Upvotes: 0

Views: 1372

Answers (3)

Evendyce
Evendyce

Reputation: 41

Edit Note:


I just noticed Bennyboy1973 mentioned this.

I suppose I just expounded on it for no reason, haha.


I know this is an old question, but for anyone else who may stumble across this problem.

Blazor has a "Virtualize" component that you can make use of. Simply put, it only renders and displays records that would be visible on screen. As you scroll in the list, it would then render the next set of records and so on, freeing up the resources that would normally be used rendering the full dataset.

To compliment the "Virtualize" component, Blazor has a ItemsProvider delegate method which you can make use of; allowing you to set it up so that instead of loading the full 2000+ record set, it only loads the amount of records needed for the current viewspace of your app. Then like the Virtualize, as you scroll it will query your dataset for the next X amount of records and then render them, and so on.

Setting up the initial "Virtualize" component is easy:

Let's say you load your cards as below

<div style="height:800px; overflow-y:scroll">
    @foreach (var card in allCardDetails)
    {
        <MyCard @key="card.Id" Title="@card.Title" Details="@card.Details" />
    }
</div>

What this will result in, is all Cards being rendered for all data records. (This includes rendering of Cards that aren't even visible onscreen.)

To implement the Virtualize component, you simply change up the code snippet to resemble the following

<div style="height:800px; overflow-y:scroll">
    <Virtualize Items="@allCardDetails" Context="card">
        <MyCard @key="card.Id" Title="card.Title" Details="@card.Details" />
    </Virtualize>
</div>

Now, only the Cards that would be visible within the region of the DIV will be rendered, and as you scroll down in the DIV it will proceed to render the next Cards that would be visible and so on.

This would greatly aid in screen jittering or rendering (The lag). If you want to take it a step further, to limit the amount of data that is queried from your server at initial load, you can make use of the ItemsProvider delegate method to achieve this.

Virtualize with ItemsProvider:

<div style="height:800px; overflow-y:scroll">
    <Virtualize Context="card" ItemsProvider="@loadCardDetails">
        <MyCard @key="card.Id" Title="card.Title" Details="@card.Details" />
    </Virtualize>
</div>

We've removed the Items field, and replaced it with the ItemsProvider as the Datasource is now mutable; determined by the ItemsProvider. Lastly, we need to create the ItemsProvider method (in this case called "loadCardDetails") which will dynamically load the records as they are needed.

private async ValueTask<ItemsProviderResult<CardDetails>> loadCardDetails(ItemsProviderRequest request)  
{  
    //It would be a good idea, at page load, to get a count of all records and
    //and store in an accessible variable.
    //For the sake of this example, I'll include it here.
    var totalCount = DbContext.CardDetails.Count();

    //This portion, determines how many records need to be loaded next
    //Math.Min is used to ensure that we don't try to load more records than
    //is available.
    //Eg. We have 50 records, but Vitualize is requesting 60 records (more than
    //we have) instead it will only attempt to get the 50 we have and return it
    var numCardDeets = Math.Min(request.Count, totalCount - request.StartIndex);

    //This portion get's the next set of data records to the count of our
    //"numCardDeets" value.
    var results = DbContext.CardDetails.Skip(request.StartIndex).Take(numCardDeets);
    
    //Finally, it returns the result set to the Virtualize component to render.
    return new ItemsProviderResult<CardDetails>(results, totalCount);  
}

And that's it. If all is setup correctly, the Virtualize component will now only load the Data that would fit on your screen (from your datasource) and render it; then as you scroll down it loads the next set of Data, and renders it.

This example is made under the assumption you make use of EntityFramework to retrieve data from a database. The implementation of how you get the Data from your datasource will vary depending on what or where your datasource is.

I'll just note here:

request.StartIndex and request.Count are managed by the ItemsProvider; it keeps track of it's own current index and request number (number of records being requested)

Upvotes: 0

Bennyboy1973
Bennyboy1973

Reputation: 4208

You can either create your own logic to load more results on each click of a button (not really hard to manage that with a SQL query).

Or you can try component virtualization, which I suspect is the closest built-in option to what you want:

https://learn.microsoft.com/en-us/aspnet/core/blazor/components/virtualization?view=aspnetcore-6.0

Upvotes: 1

Bart Kiers
Bart Kiers

Reputation: 170158

Blazor does not have built-in pagination. You'll have to do that yourself in your C# code that sends the data to your frontend/razor component(s). There are Blazor frameworks that can handle that for you, of course (Google for MudBlazor or Radzen).

Upvotes: 1

Related Questions