Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Blazor Component paging

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.

like image 853
ZKS Avatar asked May 03 '20 06:05

ZKS


People also ask

How do you do pagination in Blazor?

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.

Is Blazor single page?

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.

Is Blazor a Razor page?

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.


Video Answer


3 Answers

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.

like image 126
Henk Holterman Avatar answered Oct 18 '22 21:10

Henk Holterman


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

like image 24
Ali Borjian Avatar answered Oct 18 '22 20:10

Ali Borjian


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>&laquo;</button>
        <button disabled>&lsaquo;</button>
      }
      else
      {
        <button @onclick="@MoveFirst" title="Move First">&laquo;</button>
        <button @onclick="@MoveBack" title="Move Back">&lsaquo;</button>
      }
      <span>@CurrentPage of @TotalPages() </span>
      @if (!AtLastPage())
      {
        <button @onclick="@MoveNext" title="Move Next">&rsaquo;</button>
        <button @onclick="@MoveLast" title="Move Last">&raquo;</button>
      }
      else
      {
        <button disabled>&rsaquo;</button>
        <button disabled>&raquo;</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 => ...)
  }
}
like image 31
Rono Avatar answered Oct 18 '22 21:10

Rono