|
1 | 1 | ---
|
2 |
| -title: Pager |
| 2 | +title: Overview |
3 | 3 | page_title: Pager for Blazor Overview
|
4 |
| -description: Add a page navigation to Blazor application |
| 4 | +description: Add a pager navigation for your data to the Blazor application |
5 | 5 | slug: pager-overview
|
6 | 6 | tags: telerik,blazor,pager,paging
|
7 | 7 | published: True
|
8 |
| -position: 20 |
| 8 | +position: 1 |
9 | 9 | ---
|
10 | 10 |
|
11 | 11 | # Pager Overview
|
12 | 12 |
|
13 | 13 | The **Pager** component will enable you to add paging for your data in a Blazor application. We use it in components like the Grid and ListView, and you can also use it for your own templates and data as a standalone component.
|
14 | 14 |
|
| 15 | +The Pager provides the UI for the user to change the page. To the developer, it provides the page index so you can render only the relevant data portion and an [event]({%slug pager-events%}) that you can use to implement [load on demand](#load-on-demand). |
| 16 | + |
15 | 17 | To use Telerik Pager component for Blazor:
|
16 | 18 |
|
17 | 19 | 1. Add the `TelerikPager` tag
|
18 |
| -1. The Pager component provides the UI for the user and the page index and an [event]({%slug pager-events%}) for the developer. It is up to the application to fetch the appropriate data based on that information. |
| 20 | +1. Set its `Total` parameter to the number of items in the data source. |
| 21 | +1. Use the values of its `Page` and `PageSize` parameters to extract and render the desired subset of data. |
19 | 22 |
|
20 |
| ->caption Implement TelerikPager to your own component |
| 23 | +>caption Use the TelerikPager to paginate your own data and content |
21 | 24 |
|
22 | 25 | ````CSHTML
|
23 | 26 | @{
|
| 27 | + // take and render the relevant data portion based on the pager info |
24 | 28 | var pageData = Games.Skip((Page - 1) * PageSize).Take(PageSize).ToList();
|
25 | 29 |
|
26 |
| - foreach (Game game in pageData) |
27 |
| - { |
28 |
| - <div class="card mb-1"> |
29 |
| - <div class="card-body"> |
30 |
| - <h5>@game.GameName</h5> |
31 |
| - <h6 class="card-subtitle mb-2 text-muted">@game.GameId</h6> |
32 |
| - <p class="card-text"> |
33 |
| - Released on: @game.ReleaseDate.ToShortDateString() |
34 |
| - </p> |
| 30 | + <div class="card-deck mb-2"> |
| 31 | + @foreach (Game game in pageData) |
| 32 | + { |
| 33 | + <div class="card"> |
| 34 | + <div class="card-body"> |
| 35 | + <h5>@game.GameName</h5> |
| 36 | + <h6 class="card-subtitle mb-2 text-muted">@game.GameId</h6> |
| 37 | + <p class="card-text"> |
| 38 | + Released on: @game.ReleaseDate.ToShortDateString() |
| 39 | + </p> |
| 40 | + </div> |
35 | 41 | </div>
|
36 |
| - </div> |
37 |
| - } |
| 42 | + } |
| 43 | + </div> |
38 | 44 | }
|
39 | 45 |
|
40 | 46 | <TelerikPager Total="@Games.Count" PageSize="@PageSize" @bind-Page="@Page"></TelerikPager>
|
41 | 47 |
|
42 | 48 | @code {
|
43 | 49 | public int PageSize { get; set; } = 3;
|
44 |
| - public int Page { get; set; } = 1; |
| 50 | + public int Page { get; set; } = 1; // the page indexes are 1-based |
45 | 51 |
|
46 | 52 | public List<Game> Games { get; set; }
|
47 | 53 |
|
48 |
| - //In real-case scenario this model should be in a separate file |
49 |
| - public class Game |
50 |
| - { |
51 |
| - public string GameName { get; set; } |
52 |
| - public int GameId { get; set; } |
53 |
| - public DateTime ReleaseDate { get; set; } |
54 |
| - } |
55 |
| - //Generate sample data |
| 54 | + // Generate sample data |
56 | 55 | protected override void OnInitialized()
|
57 | 56 | {
|
58 | 57 | Games = new List<Game>();
|
59 |
| - for (int i = 0; i < 20; i++) |
| 58 | + for (int i = 1; i < 20; i++) |
60 | 59 | {
|
61 | 60 | Games.Add(new Game()
|
62 | 61 | {
|
63 | 62 | GameName = $"Game {i}",
|
64 |
| - GameId = i + 1, |
65 |
| - ReleaseDate = DateTime.Now.AddDays(i) |
| 63 | + GameId = i, |
| 64 | + ReleaseDate = DateTime.Now.AddDays(-i) |
66 | 65 | });
|
67 | 66 | }
|
68 | 67 | }
|
| 68 | +
|
| 69 | + // In real-case scenario this model should be in a separate file |
| 70 | + public class Game |
| 71 | + { |
| 72 | + public int GameId { get; set; } |
| 73 | + public string GameName { get; set; } |
| 74 | + public DateTime ReleaseDate { get; set; } |
| 75 | + } |
69 | 76 | }
|
70 | 77 | ````
|
71 | 78 |
|
| 79 | +>caption The result from the code snippet above |
| 80 | +
|
| 81 | + |
| 82 | + |
| 83 | + |
72 | 84 | ## Features
|
| 85 | + |
73 | 86 | * `Class` - The CSS class that will be rendered on the main wrapping element of the Pager.
|
74 |
| -* `Total` - ``int`` - Represents the total count of items in the pager. |
75 |
| -* `ButtonCount` - ``int`` - The maximum number of pages to be visible. To take effect the `ButtonCount` must be **less** than the pages count (ButtonCount < Total / number of items on the page). |
76 |
| -* `Page` and `@bind-Page` - ``int`` - Represents the current page of the pager. Those parameters are respectively for one and two-way data binding. If no `Page` or `@bind-Page` are provided they will default to the first page (1). |
77 |
| -* `PageSize` - ``int`` - The number of items to be presented on a page. |
| 87 | +* `Total` - `int - Represents the total count of items in the pager. Required. |
| 88 | +* `ButtonCount` - `int` - The maximum number of page buttons that will be visible. To take effect the `ButtonCount` must be smaller than the pages count (`ButtonCount < Total / PageSize`). |
| 89 | +* `Page` - `int` - Represents the current page of the pager. The first page has an index of `1`. Supports two-way data binding. If no value is provided the parameter will default to the first page (1), but you should always use this parameter value in order to successfully use the component. If you don't use two-way binding and you don't update the value of the parameter after the user action, the pager UI will not reflect the change and will revert to the previous value (page index). |
| 90 | +* `PageSize` - `int` - The number of items to be presented on a page. |
78 | 91 |
|
79 | 92 | ## Examples
|
80 | 93 |
|
81 |
| ->caption Observe the behavior of the Pager with two-way data binding |
| 94 | +### Load On Demand |
| 95 | + |
| 96 | +You can avoid loading all the data at once, as this can be a costly operation. Un such a case, you should use the `PageChanged` event of the Pager component to fetch the new subset of data to render. It is important to always provide the correct `Total` count of items in the full data source to the component so it can render the correct amount of page buttons. |
| 97 | + |
| 98 | +>caption Load paged data on demand |
| 99 | +
|
| 100 | +````CSHTML |
| 101 | +@{ |
| 102 | + <div class="card-deck mb-2"> |
| 103 | + @foreach (Game game in PagedDataToRender) |
| 104 | + { |
| 105 | + <div class="card"> |
| 106 | + <div class="card-body"> |
| 107 | + <h5>@game.GameName</h5> |
| 108 | + <h6 class="card-subtitle mb-2 text-muted">@game.GameId</h6> |
| 109 | + <p class="card-text"> |
| 110 | + Released on: @game.ReleaseDate.ToShortDateString() |
| 111 | + </p> |
| 112 | + </div> |
| 113 | + </div> |
| 114 | + } |
| 115 | + </div> |
| 116 | +} |
| 117 | +
|
| 118 | +<TelerikPager Total="@TotalGames" PageSize="@PageSize" Page="@CurrPage" |
| 119 | + PageChanged="@( (int page) => PageChangedHandler(page) )"> |
| 120 | +</TelerikPager> |
| 121 | +
|
| 122 | +@code { |
| 123 | + int TotalGames { get; set; } |
| 124 | + int CurrPage { get; set; } = 1; // the page indexes are 1-based |
| 125 | + int PageSize { get; set; } = 4; |
| 126 | +
|
| 127 | + List<Game> PagedDataToRender { get; set; } |
| 128 | +
|
| 129 | + protected override async Task OnInitializedAsync() |
| 130 | + { |
| 131 | + await LoadDataOnDemand(); |
| 132 | + } |
| 133 | +
|
| 134 | + async Task PageChangedHandler(int page) |
| 135 | + { |
| 136 | + CurrPage = page; |
| 137 | + await LoadDataOnDemand(); |
| 138 | + } |
| 139 | +
|
| 140 | + async Task LoadDataOnDemand() |
| 141 | + { |
| 142 | + TotalGames = await GetCountFromService(); |
| 143 | + PagedDataToRender = await GetPagedDataFromService(CurrPage - 1, PageSize); |
| 144 | + } |
| 145 | +
|
| 146 | + // simulate a service below |
| 147 | + private List<Game> _allData { get; set; } = Enumerable.Range(1, 500).Select(x => new Game |
| 148 | + { |
| 149 | + GameName = $"Game {x}", |
| 150 | + GameId = x, |
| 151 | + ReleaseDate = DateTime.Now.AddDays(-x) |
| 152 | + }).ToList(); |
| 153 | +
|
| 154 | + public async Task<int> GetCountFromService() |
| 155 | + { |
| 156 | + return await Task.FromResult(_allData.Count); |
| 157 | + } |
| 158 | +
|
| 159 | + public async Task<List<Game>> GetPagedDataFromService(int pageIndex, int pageSize) |
| 160 | + { |
| 161 | + var pagedData = _allData.Skip(pageIndex * pageSize).Take(pageSize); |
| 162 | + return await Task.FromResult(pagedData.ToList()); |
| 163 | + } |
| 164 | +
|
| 165 | + // In real-case scenario this model should be in a separate file |
| 166 | + public class Game |
| 167 | + { |
| 168 | + public int GameId { get; set; } |
| 169 | + public string GameName { get; set; } |
| 170 | + public DateTime ReleaseDate { get; set; } |
| 171 | + } |
| 172 | +} |
| 173 | +```` |
| 174 | + |
| 175 | +### Two-way Binding |
| 176 | + |
| 177 | +You can use two-way binding for the `Page` parameter so it can respond to changes from other element, and to also update other elements. This is the most straightforward use of the component. As an alternative, use the `PageChanged` event to implement additional logic when paging the data, such as [loading it on demand](#load-on-demand). |
82 | 178 |
|
83 | 179 | ````CSHTML
|
84 | 180 | @*This example showcases how the Pager reacts when the page is selected from an outside input.*@
|
|
0 commit comments