Building Blazor shared pager component

I have already implemented and then blogged about Blazor pager component and shared Blazor components. This post gathers my previous works and demonstrates how to build Blazor shared pager component we can use in multiple projects.

Let’s start with shared Blazor component I introduced in my blog post Building Blazor shared components. For the end of this blog post I had clean out-of-box shared component with dummy content and no code.

Out-of-box shared component

For pager component I removed content folder as I consider pager styling to be responsibility of Blazor application.

Cleaned shared component

This is the starting point – bare minimal shared Blazor component. Let’s go with new project called BlazorLibrary.Components and clean it up same way as shown on image above. Notice that I changed extension of Component1.cshtml to .razor.

Building shared Blazor pager component

Before going to actual code let’s try rename Component1.razor to Pager.razor. Pager needs to know class that carries paging information. Let’s define two classes: PagedResult<T> and PagedResultBase – almost same ones I used with pager view component for ASP.NET Core.

public abstract class PagedResultBase
{
    public int CurrentPage { get; set; }
    public int PageCount { get; set; }
    public int PageSize { get; set; }
    public int RowCount { get; set; }
}

public class PagedResult<T> : PagedResultBase where T : class
{
    public IList<T> Results { get; set; }

    public PagedResult()
    {
        Results = new List<T>();
    }
}

You can find out more about paging .NET Core from my blog posts Paging with Entity Framework Core and Returning paged results from repositories using PagedResult,

NB! It’s arhitectural decision where to keep these classes. For demo purposes it’s okay to keep these in Blazor shared component project. In practice these classes are used also by other projects and other layers (shared data clients, Entity Framework database context etc). If you build something real then make sure you define these classes in correct layer.

Here is the content for Pager.razor file. Don’t worry about PagerModel class right now as we take care of this at next step.

@inherits PagerModel

@if (Result != null)
{
    <div class="row">
        <div class="col-md-8 col-sm-8">
            @if (Result.PageCount > 1)
            {
                <ul class="pagination pull-right">
                    <li><button type="button" onclick="@(() => PagerButtonClicked(1))" class="btn">&laquo;</button></li>
                    @for (var i = StartIndex; i <= FinishIndex; i++)
                    {
                        var currentIndex = i;
                        @if (i == Result.CurrentPage)
                        {
                            <li><span class="btn btn-primary">@i</span></li>
                        }
                        else
                        {
                            <li><button type="button" onclick="@(() => PagerButtonClicked(currentIndex))" class="btn">@i</button></li>
                        }
                    }
                    <li><button type="button" onclick="@(() => PagerButtonClicked(Result.PageCount))" class="btn">&raquo;</button></li>
                </ul>
            }
        </div>
    </div>
}

Although most of Blazor examples you see in internet have page code in same file inside @functions block, you can still use code-behind files to keep code and presentation separated. You can find out more about this in from blog post Separating code and presentation of Blazor pages.

Let’s add new C# class to project and name it as Pager.razor.cs. Take a look at Solution Explorer – the new file is located nicely under Pager.razor like. Here is code for PagerModel class.

public class PagerModel : ComponentBase
{
    [Parameter]
    protected PagedResultBase Result { get; set; }

    [Parameter]
    protected Action<int> PageChanged { get; set; }

    protected int StartIndex { get; private set; } = 0;
    protected int FinishIndex { get; private set; } = 0;

    protected override void OnParametersSet()
    {
        StartIndex = Math.Max(Result.CurrentPage - 5, 1);
        FinishIndex = Math.Min(Result.CurrentPage + 5, Result.PageCount);

        base.OnParametersSet();
    }

    protected void PagerButtonClicked(int page)
    {
        PageChanged?.Invoke(page);
    }
}

Now we can build a project and we are done with our pager shared component.

Using Blazor shared pager component in other projects

Using shared pager component is easy. In project where we want to use pager component we have to add reference to pager library. After this we  can add pager to some Blazor page.

Here is the example from my Blazor demo project in Github (BlazorLibrary.AspNetCoreHostedBlazor.Client/Pages/Index.razor).

<Pager Result=@Books PageChanged=@PagerPageChanged />

@Books is paged result with books and @PagerPageChanged is event that is fired when user selects another page in pager. This is how pager looks in my Blazor demos.

Blazor shared pager component

If you need different markup and styling for pager then feel free to change Pager.razor file to better reflect your needs.

Wrapping up

Although most of this post is well covered in my previous writings it is still good example how to build something useful on Blazor already today. Although shared components support is not official when writing this post I’m sure it will come to Blazor soon. Pager component is useful as it is needed in almost all application that display tables or lists of data to users. Now this cool component is in its own library and we can share it between projects.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.

    Leave a Reply

    Your email address will not be published. Required fields are marked *