mostlylucid.pagingtaghelper
0.9.4.1
dotnet add package mostlylucid.pagingtaghelper --version 0.9.4.1
NuGet\Install-Package mostlylucid.pagingtaghelper -Version 0.9.4.1
<PackageReference Include="mostlylucid.pagingtaghelper" Version="0.9.4.1" />
<PackageVersion Include="mostlylucid.pagingtaghelper" Version="0.9.4.1" />
<PackageReference Include="mostlylucid.pagingtaghelper" />
paket add mostlylucid.pagingtaghelper --version 0.9.4.1
#r "nuget: mostlylucid.pagingtaghelper, 0.9.4.1"
#addin nuget:?package=mostlylucid.pagingtaghelper&version=0.9.4.1
#tool nuget:?package=mostlylucid.pagingtaghelper&version=0.9.4.1
mostlylucid paging tag helper and viewcomponent.
This is a preview of this tag helper at present but it works. I'll be adding more documentation and samples as I go.
Installation
You can install the package via nuget:
dotnet add package mostlylucid.pagingtaghelper
Usage
The sample site can be found here.
https://taghelpersample.mostlylucid.net/
You can view the source for the sample site here: https://github.com/scottgal/mostlylucid.pagingtaghelper
Aditionally you can follow along with any articles on my blog site here.
Paging Tag Helper
- Basic use without HTMX - this sample shoows the very basic usage of the tag helper. It disables HTMX using the
use-htmx
property set to false.
<paging model="Model"
use-htmx="false"
class="mt-4">
</paging>
It also uses the JavaScript snippet below to handle the form submission:
@Html.PageSizeOnchangeSnippet()
This can be added anywhere.
The most basic model is as follows:
public interface IPagingModel
{
// [HtmlAttributeName("page")]
public int Page { get; set; }
// [HtmlAttributeName("total-items")]
public int TotalItems { get; set; }
// [HtmlAttributeName("page-size")]
public int PageSize { get; set; }
// [HtmlAttributeName("link-url")]
public string LinkUrl { get; set; }
}
These are the required fields and can either be supplied individually to the TagHelper or as a model.
The configuration on the TagHelper is as follows. As you can see it has many options, each of which I'll add to the sample (takes some time!).
PagerTagHelper
Properties
The PagerTagHelper
provides various attributes to customize the pagination component. Below is a detailed list of each property and its purpose.
General Properties
model
(optional)- Type:
IPagingModel?
- Description: The paging model containing the pagination details.
- Type:
pagingmodel
(optional)- Type:
PagerViewModel?
- Description: The view model for the pager component.
- Type:
id
- Type:
string?
- Description: Optionally pass in an ID for the pager component.
- Type:
view-type
- Type:
ViewType
- Default:
ViewType.TailwindANdDaisy
- Description: Defines the type of view to be used for rendering the pager.
- Type:
use-local-view
- Type:
bool
- Default:
false
- Description: Determines whether the local view is used instead of the tag helper view.
- Type:
Pagination Behavior
page
- Type:
int?
- Description: The current page number.
- Type:
page-size
- Type:
int?
- Description: The number of items per page.
- Type:
total-items
- Type:
int?
- Description: The total number of items in the pagination set.
- Type:
pages-to-display
- Type:
int
- Default:
5
- Description: The number of pages to display in the pager navigation.
- Type:
show-pagesize
- Type:
bool
- Default:
true
- Description: Determines whether the page size selection is shown.
- Type:
show-summary
- Type:
bool
- Default:
true
- Description: Determines whether a summary is displayed.
- Type:
Navigation Links
first-page-text
- Type:
string
- Default:
«
- Description: Text for the first page navigation link.
- Type:
previous-page-text
- Type:
string
- Default:
‹ Previous
- Description: Text for the previous page navigation link.
- Type:
skip-back-text
- Type:
string
- Default:
..
- Description: Text for skipping backward in pagination.
- Type:
skip-forward-text
- Type:
string
- Default:
..
- Description: Text for skipping forward in pagination.
- Type:
next-page-text
- Type:
string
- Default:
Next ›
- Description: Text for the next page navigation link.
- Type:
next-page-aria-label
- Type:
string
- Default:
go to next page
- Description: ARIA label for the next page navigation link.
- Type:
last-page-text
- Type:
string
- Default:
»
- Description: Text for the last page navigation link.
- Type:
first-last-navigation
- Type:
bool
- Default:
true
- Description: Indicates whether first and last page navigation links should be displayed.
- Type:
skip-forward-back-navigation
- Type:
bool
- Default:
true
- Description: Indicates whether skip forward/backward navigation should be enabled.
- Type:
Styling & Customization
css-class
- Type:
string
- Default:
btn-group
- Description: The CSS class applied to the pager container.
- Type:
Search & Sorting
search-term
- Type:
string?
- Description: The search term used in pagination filtering.
- Type:
order-by
- Type:
string?
- Description: The column name to order by.
- Type:
descending
- Type:
bool?
- Description: Determines if sorting should be descending.
- Type:
HTMX Integration
use-htmx
- Type:
bool
- Default:
true
- Description: Whether to enable HTMX use for the pagesize component.
- Type:
htmx-target
- Type:
string
- Default:
""
- Description: Specifies the HTMX target for AJAX-based pagination.
- Type:
Internal Processing
link-url
- Type:
string?
- Description: The base URL for pagination links.
- Type:
ViewContext
- Type:
ViewContext
- Description: The current view context, automatically injected.
- Type:
This PagerTagHelper
allows for flexible pagination and supports different UI frameworks through the view-type
property. It integrates with HTMX for enhanced AJAX navigation while providing various customization options for navigation text, styling, and sorting.
This defines all the configuration options for the tag helper.
NOTE: As it stands this site uses DaisyUI with TailwindCSS; later I'll document how to use it with any CSS framework.
For Tailwind & DaisyUI I also add a piece of HTML to the _layout.cshtml file provide a hint to the tailwind processor for required classes.
<span class="hidden btn btn-sm btn-active btn-disabled select select-primary select-sm
text-sm text-gray-600 text-neutral-500 border rounded flex items-center
justify-center min-w-[80px] pr-4 pt-0 mt-0 mr-2 btn-primary btn-outline
bg-white text-black
dark:bg-blue-500 dark:border-blue-400 dark:text-white dark:hover:bg-blue-600
dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-gray-700
dark:btn-accent dark:btn-outline dark:btn-disabled dark:btn-primary dark:btn-active gap-2 whitespace-nowrap">
</span>
- Use with HTMX - this sample shows how to use the tag helper with HTMX. It uses the same
PagerViewModel
as the basic sample but with theUseHtmx
property set totrue
.
<paging hx-boost="true"
class="mt-4"
hx-indicator="#loading-modal"
hx-target="#list"
hx-swap="show:none"
hx-headers='{"pagerequest": "true"}'
model="@Model">
</paging>
The tag helper is designed to preserve the hx
attributes and these cascade into the tag helper. The form submission is then handled using HTMX.
As I designed this to be HTMX by default you only need to specify ust-htmx="false"
if you AREN'T using HTMX. In that case you can use the Page Size JS snipept to handle the page size selector submission.
@Html.PageSizeOnchangeSnippet()
Additionally you can select from multiple Views using the ViewType
property, set using the ViewType attribute view-type="Custom"
.
public ViewType ViewType { get; set; } = Models.ViewType.TailwindANdDaisy;
When set to Custom you are able to pass in the view name using the UseLocalView
property / "use-local-view="\ViewPath.cshtml"
. property.
For the PlainView.cshtml you can use the following would specify the Plain
view for the ViewType
(view-type
). I've also supplied some CSS for basic styling of the component.
You can use the HTML snippet to inject it into your page:
@Html.PlainCSS()
As with the Tailwind & DaisyUI view this enables both dark and light mode.
This is handled within the PagerViewComponent
which is used to render the pager. This is a ViewComponent that is used to render the pager. It uses the PagerViewModel
to render the pager.
var viewName = "Components/Pager/Default";
var useLocalView = model.UseLocalView;
return (useLocalView, model.ViewType) switch
{
(true, ViewType.Custom) when ViewExists(viewName) => View(viewName, model),
(true, ViewType.Custom) when !ViewExists(viewName) => throw new ArgumentException("View not found: " + viewName),
(false, ViewType.Bootstrap) => View("/Areas/Components/Views/Pager/BootstrapView.cshtml", model),
(false, ViewType.Plain) => View("/Areas/Components/Views/Pager/PlainView.cshtml", model),
(false, ViewType.TailwindANdDaisy) => View("/Areas/Components/Views/Pager/Default.cshtml", model),
_ => View("/Areas/Components/Views/Pager/Default.cshtml", model)
};
/// <summary>
/// Checks if a view exists in the consuming application.
/// </summary>
private bool ViewExists(string viewName)
{
var result = ViewEngine.FindView(ViewContext, viewName, false);
return result.Success;
}
Flippy Header Tag Helper
This adds a new taghelper which makes it easy to add a flippy header to your site. This is a simple tag helper that adds a header to your site that flips between two states. As with the paging tag helper this permits you to use HTMX to handle the form submission (transparently, it doesn't NEED HTMX but it's designed to work with it).
You can see more detailed coverage of this 'bonus' tag helper on my blog.
<sortable-header column="Id"
current-order-by="@Model.OrderBy"
descending="@Model.Descending"
hx-get
hx-route-pagesize="@Model.PageSize"
hx-route-page="@Model.Page"
hx-route-search="@Model.SearchTerm"
hx-controller="ServiceBus"
hx-action="List"
hx-params="*"
hx-indicator="#loading-modal"
hx-target="#servicebus-list"
hx-push-url="true">Id</sortable-header>
Page Size Tag Helper
This is a simple tag helper that adds a page size selector to your site. It's used internally within the Paging Tag Helper but can be used independently.
<page-size
model="Model"
view-type="TailwindANdDaisy"
use-htmx="true"
id="custom-pager"
page-size-model="CustomPageSizeModel"
search-term="searchQuery"
link-url="/search/results"
page="1"
page-size="25"
use-local-view="false"
total-items="500">
</page-size>
As you can see it's closely related to the Paging Tag Helper and uses the same PagerViewModel
to render the page size selector (actually it can also take the new
public abstract class BaseTagModel
{
private List<int>? _oageSizes;
public List<int> PageSizes
{
get { return _oageSizes ??= CalculatePageSizes(); }
}
public IPagingModel? Model { get; set; }
public int TotalPages => (int)Math.Ceiling(TotalItems! / (double)PageSize!);
public ViewType ViewType { get; set; } // ViewType.TailwindANdDaisy / ViewType.Bootstrap / ViewType.Plain / ViewType.Custom
public bool UseLocalView { get; set; } = false; // Use a local view instead of the default views
public string? PagerId { get; set; } // Optional local ID for the pager
public string? SearchTerm { get; set; } // Lets you pass in a search term (not REALLY necessary as it now auto-populates from the model / querystring)
public int PageSize { get; set; } // The current page size either passed in in the model or set here
public int TotalItems { get; set; } // The total number of items in the set either passed in in the model or set here
public int Page { get; set; } // The current page number either passed in in the model or set here (or populated from the querystring)
}
public class PageSizeModel : BaseTagModel
{
public bool UseHtmx { get; set; } = true; // Use HTMX to handle the form submission if NOT You MUST Set hx-target
public string? LinkUrl { get; set; } // Optional link URL for the page size selector, defaults to the current page
}
By default the simplest way to use this is to pass in the PagerViewModel
NOTE: If you're using HTMX you need to set the hx-target property to the ID of the element you want to update. This is handled by the tag helper. Otherwise it'll try and swap out itself to...bad results.
<page-size
hx-target="#list"
model="Model">
</page-size>
It also has support for non-JS use using the use-htmx="false"
property. In this case you can use the following JS snippet to handle the form submission.
@Html.PageSizeOnchangeSnippet()
TBC
Additionally I'll write some blog posts over on my site about how to use this tag helper in a real-world scenario as well as detail the thinking behind it's creation etc.
ViewComponent - one aspect of this is I use a ViewComponent in conjunction with a tag helper; this pemits me to use the tag helper in a more dynamic way (for instance you can replace the Default view with your own custom view).
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
-
net8.0
- JetBrains.Annotations (>= 2024.3.0)
- Microsoft.AspNetCore.Components.Web (>= 8.0.14)
-
net9.0
- JetBrains.Annotations (>= 2024.3.0)
- Microsoft.AspNetCore.Components.Web (>= 8.0.14)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
0.9.4.1 | 150 | 4/27/2025 |
0.9.4 | 190 | 4/26/2025 |
0.9.2 | 88 | 4/26/2025 |
0.9.1 | 898 | 3/24/2025 |
0.9.0 | 101 | 3/21/2025 |
0.8.9 | 80 | 3/21/2025 |
0.8.8 | 140 | 3/20/2025 |
0.8.7 | 139 | 3/20/2025 |
0.8.6 | 132 | 3/20/2025 |
0.7.1 | 142 | 3/20/2025 |
0.7.0 | 134 | 3/20/2025 |
0.6.3 | 146 | 3/18/2025 |
0.6.2 | 132 | 3/18/2025 |
0.6.1 | 132 | 3/17/2025 |
0.6.0 | 132 | 3/17/2025 |
0.5.1 | 138 | 3/17/2025 |
0.5.0 | 138 | 3/17/2025 |
0.4.0 | 143 | 3/13/2025 |
0.3.2 | 143 | 3/12/2025 |
0.3.1 | 146 | 3/12/2025 |
0.3.0 | 143 | 3/12/2025 |
0.2.0 | 147 | 3/11/2025 |
0.1.1 | 152 | 3/10/2025 |
0.1.0 | 144 | 3/10/2025 |
0.0.4 | 146 | 3/10/2025 |
0.0.3 | 149 | 3/10/2025 |
0.2.0
Adds multiple views, TailwindANdDaisy,
Custom,
Plain,
Bootstrap
Adds plain CSS injection snippet. @Html.PlainCSS()
0.3.0
Adds light mode for all views.
0.3.1
Improves layout for samples.
0.3.2
Updates readme.
0.5.0
Adds the new FlippySortTagHelper to the package. This enables you to sort a list of items by clicking on the column headers.
0.5.1
Update this release notes as I forgot; update the Samples page.
0.6.0
This update adds HTMX free capabilities to the FlippySortTagHelper. This means you can now sort a list of items without any JavaScript / HTMX.
0.6.1
Fix to add an ability to return href plain when AutoAppend is set to false.
0.6.2-0.6.3
Readme updates.
0.7.0
New functionality (in the Default Tailwind View) for preserving extra query parameters when paging.
0.7.1
Add preserve query string params to page size dropdown.
0.8.0-0.8.9
Update PageSize to accept MaxPageSize, update query string logic to presrve query string params (client size).
Fix Table Sort to work properly with HTMX action links.
0.9.0-0.9.2
Fix bug around totalitems being 0 and not showing the paging controls. Also fix client side bug to reset page to 1 when the page size changes.
0.9.3
Show page size even when there is no paging.
0.9.4
Show page size even when there is no paging.
0.9.4.1
Small tweak to remove the daisyui select-primary class from the page size dropdown.