I am working on Blazor application and have a component showing list of records (retrieving from entity framework entity), wanted to know what would be best and easiest approach to implement paging on component.
Any help would be appreciated.
In Blazor, we use EventCallbacks to run the methods from the parent component inside the child component. In our case, every time we select a new page in the pagination component, we are going to fire the SelectedPage event callback which will execute the method from the parent (Products) component.
Blazor WebAssembly is a single-page app (SPA) framework for building interactive client-side web apps with . NET. Blazor WebAssembly uses open web standards without plugins or recompiling code into other languages. Blazor WebAssembly works in all modern web browsers, including mobile browsers.
While Blazor is a framework, Razor, or Razor Pages, is a templating (View) engine. The Razor syntax combines Razor markup, C#, and HTML to create dynamic web content. Typically, Razor is used for powering ASP.NET MVC Views.
In Blazor you can pass your Page just as you would in MVC.
For a very simple sample, make the following changes to FetchData.razor :
@page "/fetchdata"
@page "/fetchdata/{PageNumber:int}"
... the HTML for the table...
<div>
@for (int i = 1; i <= 5; i++)
{
<span><a href="fetchdata/@i"> @i </a>|</span>
}
</div>
@code {
[Parameter]
public int PageNumber { get; set; }
private WeatherForecast[] forecasts;
protected override async Task OnParametersSetAsync()
{
if (PageNumber < 1) PageNumber = 1;
// adapt the service to take pageIndex, pageSize
forecasts = await ForecastService.GetForecastAsync(PageNumber-1, 5);
}
}
The pager is very crude, just 1 .. 5. There are components available that can do most of the markup and logic, google for "Blazor Pager component". I found this one pretty quickly.
In Blazor you have full control over your DOM. As You are using EF so you can simply perform Skip and Take for your paging :
private int pageSize = 100;
private int pageNumber = 1;
in HTML :
for(int p = 1; p<= list.Count() / pageSize ; p++) {
<button type="button" @onclick="(e=>HandleChangePage(p))">@p</button>
}
Handle Change Page :
void HandleChangePage(int p) {
pageNumber = p;
var page = list.Skip((p-1) * pageSize).Take(pageSize);
}
It's the easiest way to do paging,
Now you can go ahead and create your paging list component
Now you need to pass your list to the component as a parameter
[Parameter]
public List<ClassName> list {get;set;}
If you want to work with a generic list look at Template context parameters
I developed a generic paging component which uses an HTML table and is easily reusable. Save this in it's own component razor named PagedList.razor:
@typeparam TItem
@if (!ListQuery.Any())
{
<div class="none-indicator">(none)</div>
}
else
{
@if (TotalPages() > 1)
{
<div class="pager-display">
@if (CurrentPage == 1)
{
<button disabled>«</button>
<button disabled>‹</button>
}
else
{
<button @onclick="@MoveFirst" title="Move First">«</button>
<button @onclick="@MoveBack" title="Move Back">‹</button>
}
<span>@CurrentPage of @TotalPages() </span>
@if (!AtLastPage())
{
<button @onclick="@MoveNext" title="Move Next">›</button>
<button @onclick="@MoveLast" title="Move Last">»</button>
}
else
{
<button disabled>›</button>
<button disabled>»</button>
}
</div>
}
<table class="table table-striped">
<thead>
@HeaderDisplay
</thead>
<tbody>
@foreach (TItem item in CurrentDisplay)
{
@ItemDisplay(item)
}
</tbody>
</table>
}
@code {
[Parameter]
public IQueryable<TItem> ListQuery { get; set; }
[Parameter]
public RenderFragment HeaderDisplay { get; set; }
[Parameter]
public RenderFragment<TItem> ItemDisplay { get; set; }
[Parameter]
public int ItemsPerPage { get; set; } = 10;
private int CurrentPage = 1;
private List<TItem> CurrentDisplay;
private int TotalCount;
protected override void OnParametersSet()
{
UpdateDisplay();
TotalCount = ListQuery.Count();
}
private void UpdateDisplay()
{
CurrentDisplay = ListQuery.Skip((CurrentPage - 1) * ItemsPerPage).Take(ItemsPerPage).ToList();
}
private bool AtLastPage()
{
return CurrentPage >= TotalPages();
}
private int TotalPages()
{
return Convert.ToInt32(Math.Ceiling(TotalCount / Convert.ToDecimal(ItemsPerPage)));
}
private void MoveFirst()
{
CurrentPage = 1;
UpdateDisplay();
}
private void MoveBack()
{
CurrentPage--;
UpdateDisplay();
}
private void MoveNext()
{
CurrentPage++;
UpdateDisplay();
}
private void MoveLast()
{
CurrentPage = TotalPages();
UpdateDisplay();
}
}
Here's an example of it being used:
<PagedList ListQuery="People">
<HeaderDisplay>
<tr>
<th></th>
<th>First Name</th>
<th>Last Name</th>
<th>Title</th>
</tr>
</HeaderDisplay>
<ItemDisplay>
<tr>
<td><a href="People/Edit/@(context.ID)">Edit</a></td>
<td>@context.FirstName</td>
<td>@context.LastName</td>
<td>@context.Title</td>
</tr>
</ItemDisplay>
</PagedList>
@code {
private IQueryable<Person> People;
protected override void OnInitialized()
{
People = DatabaseContext.Person.Where(p => ...)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With