.Net 6 , Blazor WASM -- paging a list of "records" for CRUD --

611 Views Asked by At

My project is VS-2022, .Net 6, C#, Blazor WASM hosted. For CRUD, we designed a razor page showing a list of "records" but needed a way to "page" for a list of 12 records on each page.

This post is NOT a question, but may be used by others seeking simple paging that works in similar projects. I hope this post helps others.

From this list screen, we could ADD or EDIT (delete in the future requirement). I had researched the web for how to do paging but the solutions were older and some used TagHelper which is no longer available in Blazor (or my knowledge is too weak to morph it). So from these un-usable (in my case) solutions, I created a simple set of code to be placed on each LIST-for-CRUD-page. This process relies on threeList<> elements to hold the vehicle-data fetched from the DB once in OnParametersSetAsync() method. The paging-list is a subset of the main list of All-Vehicle-data (from the DB) and Filtered-Vehicle-data. The paging is extremely fast since paging takes place in the client-project after a single fetch of DB-data.

I show you the list page with the paging shown at the bottom of the list.

Below the image is the PagingInfo.cs class that holds the relevant paging variables. The "number of records per page" is a constructor value for this class so each CRUD-model-page can have a different number of records per page.

Followed by the pertinent HTML code that renders the paging buttons (only when there is more than a single page of 12 records).

Followed by the C#-code that drives the paging. What is NOT shown is typical Blazor code to fetch DB-data for the Vehicles and managing the Active/In-Active select control's events.

For each CRUD-model, in this case Vehicle CRUD, the C# code has a List<Vehicle> _AllVehicles variable that fetches DB-data-records for all vehicles.

A List<Vehicle> _FilteredVehicles variable that is filtered by CUSTOMER and by Active/In-Active vehicles (see the Active/In-Active select-control in the page-image).

AND a List<Vehicles> _PagedVehicles variable that contains the records to be displayed in the HTML-table (no code provided -- but see the page-image below) that is "computed/filtered" in the PageClicked() -method using Skip and Take filters for the _FilteredVehicles list.

Vehicle List page

Here is the paging-info object that is used by the page's code with information needed for the paging operations.

public class PagingInfo {

    public PagingInfo(int pItemsPerPage = 8) {
        ItemsPerPage = pItemsPerPage;
    }

    public int TotalItems { get; set; }
    public int ItemsPerPage { get; set; }
    public int CurrentPage { get; set; }
    public int TotalPages {
        get {
            return (int)Math.Ceiling((decimal)TotalItems / ItemsPerPage);
        }
    }
}

Here is the HTML paging code below the table-body the list-"table" ( not shown here).

</tbody>
    @if (_PagingInfo.TotalItems > _PagingInfo.ItemsPerPage) {
        <tr class="bg-warning m-0 py-0">
            <td colspan="3">
                <div style="height: 3.1rem; text-align: center;" class="justify-content-center">
                    <div class="btn-group justify-content-center"   role="group" aria-label="Basic outlined example">
                        <button id="btnPrev" type="button" class="btn btn-outline-dark border-3 fw-bold" @onclick="PagingClickPrevious">&#60; Previous</button>
                        <span id="btnPage"   type="button" class="btn btn-outline-dark disabled fw-bold">Page @_PagingInfo.CurrentPage of @_PagingInfo.TotalPages</span>
                        <button id="btnNext" type="button" class="btn btn-outline-dark border-3 fw-bold" @onclick="PagingClickNext">Next &#62;</button>
                    </div>
                </div>
            </td>
        </tr>
    }
</table>

The paging-code follows:

// Paging Functions /////////////////////////////////////////////////////////////////////
PagingInfo _PagingInfo = new PagingInfo(12);      // Initialize here: number of items-per-page.
private IEnumerable<Vehicle> _PagedVehicles { get; set; }

private void initializePagingInfo(int pPageNumber) {    ////////////////////////////////////////////////////////////
        
    _PagingInfo.CurrentPage = pPageNumber;

    if (_FilteredVehicles is not null && _FilteredVehicles.Count() > 0)
        _PagingInfo.TotalItems = _FilteredVehicles.Count();
}

private void PagingClicked(int pItemNumber = -1) {  ////////////////////////////////////////////////////////////    

    _PagingInfo.TotalItems = _FilteredVehicles.Count();      // Get the count of items.

    switch (pItemNumber) {
    case < 1:         // Goto previous page.
    _PagingInfo.CurrentPage = _PagingInfo.CurrentPage < 2 ? 1 : --_PagingInfo.CurrentPage;
    break;

    case > 99:        // Goto next page.
    if (_PagingInfo.CurrentPage < _PagingInfo.TotalPages)
        _PagingInfo.CurrentPage++;    
    break;

    default:
    _PagingInfo.CurrentPage = pItemNumber;
    break;
    }
    _PagedVehicles = _FilteredVehicles.Skip((_PagingInfo.CurrentPage - 1) * _PagingInfo.ItemsPerPage).Take(_PagingInfo.ItemsPerPage).ToList();
}

private void PagingClickPrevious() {    ////////////////////////////////////////////////////////////
    // Event from the HTML-paging "previous" paging button -- pass -1 for previous page.
    PagingClicked(-1);
}

private void PagingClickNext() {            ////////////////////////////////////////////////////////////
    // Event from the HTML-paging "next" paging button -- pass a large number for next page.
    PagingClicked(999);
}
// end of paging functions /////////////////////////////////////////////////////////////////////////////////////
0

There are 0 best solutions below