AngryMonkey.CloudComponents.DataGrid
4.2.1
dotnet add package AngryMonkey.CloudComponents.DataGrid --version 4.2.1
NuGet\Install-Package AngryMonkey.CloudComponents.DataGrid -Version 4.2.1
<PackageReference Include="AngryMonkey.CloudComponents.DataGrid" Version="4.2.1" />
<PackageVersion Include="AngryMonkey.CloudComponents.DataGrid" Version="4.2.1" />
<PackageReference Include="AngryMonkey.CloudComponents.DataGrid" />
paket add AngryMonkey.CloudComponents.DataGrid --version 4.2.1
#r "nuget: AngryMonkey.CloudComponents.DataGrid, 4.2.1"
#:package AngryMonkey.CloudComponents.DataGrid@4.2.1
#addin nuget:?package=AngryMonkey.CloudComponents.DataGrid&version=4.2.1
#tool nuget:?package=AngryMonkey.CloudComponents.DataGrid&version=4.2.1
CloudComponents.DataGrid
Production-ready Blazor data grid for .NET 10 with strongly typed models, server-driven data loading, paging modes, sorting, selection, row actions, reordering, export, and theme-friendly CSS variables.
CloudDataGridis the single entry point. It composes header, body, and footer internally and is driven by one requiredDataProvidercallback.
Table of contents
- Features
- Installation
- Quick start
- Data flow (
DataProvider) - Component API
- Models reference
- Paging modes
- Body height modes
- Sorting behavior
- Actions (header, row, bulk, more)
- Selection
- Row reordering
- Export
- Styling and theming
- Troubleshooting
Features
- Pure Blazor interaction model for grid UX (sorting, resizing, selection, reordering)
- Required async
DataProviderpattern for consistent load/search/sort/page orchestration - Optional toolbar (
CloudDataGridHeaderOptions) with built-in Search, Refresh, Export - Header actions + row actions + bulk actions + more-menu actions
- Paging modes:
PagesLoadMoreInfiniteScroll(via built-in Blazor virtualization)
- Runtime CSV export for:
- current page
- all records (respecting active search/sort)
- selected records
- Row link support + row-level arbitrary HTML attributes
- CSS-variable theming + predictable class naming
Installation
NuGet
dotnet add package AngryMonkey.CloudComponents.DataGrid
Project reference
Reference CloudComponents.DataGrid from your Blazor app.
Namespace import
Add where needed:
@using CloudComponents.DataGrid.Components
@using CloudComponents.DataGrid.Models
Quick start
@using CloudComponents.DataGrid.Components
@using CloudComponents.DataGrid.Models
<CloudDataGrid Columns="_columns"
DataProvider="LoadAsync"
Header="_header"
AllowSelection="true"
@bind-SelectedRecords="_selected"
RowsPerPage="25"
PagingMode="CloudDataGridPagingMode.Pages" />
@code {
private readonly List<Guid> _selected = [];
private readonly List<CloudDataGridColumn> _columns =
[
new() { Label = "Photo", Key = "photo", IsImage = true, Sortable = false, Width = 84 },
new() { Label = "Name", Key = "name", Width = 220 },
new() { Label = "Email", Key = "email", Width = 280 },
new() { Label = "Status", Key = "status", Width = 120 }
];
private readonly CloudDataGridHeaderOptions _header = new()
{
Label = "Contacts",
AllowSearch = true,
AllowRefresh = true,
AllowExport = true
};
private async Task<CloudDataGridDataResult?> LoadAsync(CloudDataGridDataRequest request)
{
// Query your backend with request.Page, request.PageSize, request.Search, request.Sort
await Task.Delay(100);
return new CloudDataGridDataResult
{
Page = request.Page,
PageSize = request.PageSize,
Total = 2,
Rows =
[
new()
{
Id = Guid.NewGuid(),
Link = "/contacts/1",
Cells = ["/images/p1.jpg", "Mia Carter", "mia@domain.com", "Active"]
},
new()
{
Id = Guid.NewGuid(),
Link = "/contacts/2",
Cells = ["/images/p2.jpg", "Noah Brooks", "noah@domain.com", "Inactive"]
}
]
};
}
}
Data flow (DataProvider)
CloudDataGrid always calls a required callback:
Func<CloudDataGridDataRequest, Task<CloudDataGridDataResult?>> DataProvider
Called on:
- initial load
- search query changes
- sort changes
- page changes
- reload/refresh
CloudDataGridDataRequest includes:
PagePageSizeSearchSortIsAppendTotal
Return a CloudDataGridDataResult with Rows, Page, PageSize, Total, and optional ErrorMessage.
Component API
CloudDataGrid parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
Header |
CloudDataGridHeaderOptions? |
null |
Shows toolbar when provided. |
Columns |
List<CloudDataGridColumn> |
[] |
Column definitions in render order. |
DataProvider |
Func<CloudDataGridDataRequest, Task<CloudDataGridDataResult?>> |
required | Data source callback for all grid state transitions. |
AllowSelection |
bool |
false |
Enables checkbox column + select-all behavior. |
SelectedRecords |
List<Guid>? |
null |
Selected row IDs (supports @bind-SelectedRecords). |
SelectedRecordsChanged |
EventCallback<List<Guid>> |
— | Raised on selection updates. |
AllowReordering |
bool |
false |
Enables row drag handle and drop reordering. |
OnRowsReordered |
EventCallback<CloudDataGridRowReorder> |
— | Fired after a row is dropped in a new position. |
OnActionClicked |
EventCallback<CloudDataGridActionEventArgs> |
— | Fired for button actions (row/header/bulk). |
RowActions |
List<CloudDataGridAction>? |
null |
Explicit row actions (merged with Header.Actions that set ShowOnRow). |
ActionFilter |
Func<CloudDataGridRow, CloudDataGridAction, bool>? |
null |
Per-row action visibility filter. |
CssClass |
string? |
null |
Additional classes appended to .cloudgrid. |
LinkTarget |
string |
_parent |
Target for row links (CloudDataGridRow.Link). |
LoadingText |
string |
retrieving data... |
Loading status text. |
SearchingText |
string |
searching... |
Searching status text. |
EmptyCellText |
string |
-- |
Placeholder for null/empty cells. |
ColumnFooterRows |
List<CloudDataGridFooterRow> |
[] |
Summary rows aligned with the data columns. |
FixedColumnFooter |
bool |
true |
Keeps column summary rows visible at the bottom of the table viewport. |
RowHeight |
double? |
null |
Overrides --cloudgrid-row-height in px. |
RowNoteHeight |
double |
24 |
Fixed note-line height used by virtualization. |
ReserveRowNoteSpace |
bool |
false |
Reserves note space before later infinite-scroll pages with notes are loaded. |
ShowRowNotes |
bool |
true |
Shows or hides notes supplied by rows. |
EnableRowCategories |
bool |
true |
Groups rows that provide CategoryKey. |
AllowCategoryCollapse |
bool |
true |
Lets users collapse and expand category headers. |
CollapsedCategories |
HashSet<string>? |
null |
Collapsed category keys; supports @bind-CollapsedCategories. |
CollapsedCategoriesChanged |
EventCallback<HashSet<string>> |
— | Raised when category expansion changes. |
CategoryHeaderTemplate |
RenderFragment<CloudDataGridCategoryContext>? |
null |
Custom category header content. |
RowsPerPage |
int? |
null |
Desired body rows in viewport and page size sent to provider. |
HeightMode |
CloudDataGridHeightMode |
FullHeight |
How the grid is sized vertically: FullHeight (default, fills parent), RowHeight (fixed to RowsPerPage rows), or Auto (grows with content, optionally capped by MaxHeight). |
MaxHeight |
double? |
null |
Maximum height in pixels when HeightMode is Auto. Ignored for other modes. |
PagingMode |
CloudDataGridPagingMode |
Pages |
Pages, LoadMore, or InfiniteScroll. |
LoadMoreText |
string |
load more |
Label for load-more button mode. |
AdditionalAttributes |
Dictionary<string, object>? |
null |
Captures unmatched attributes on root element. |
CloudDataGridHeaderOptions
| Property | Type | Default | Description |
|---|---|---|---|
Label |
string? |
null |
Header title. |
Actions |
List<CloudDataGridAction> |
[] |
Unified action list for header/bulk/row/more menu placement. |
OnActionClicked |
EventCallback<CloudDataGridActionEventArgs> |
— | Callback for button action clicks. |
AllowSearch |
bool |
false |
Enables built-in search element action. |
SearchDebounceMilliseconds |
int |
300 |
Debounce delay for search callback. |
OnSearchChanged |
EventCallback<string?> |
— | Debounced search query callback. |
AllowRefresh |
bool |
true |
Enables built-in refresh button action. |
OnRefresh |
EventCallback |
— | Callback for built-in refresh click. |
AllowExport |
bool |
true |
Injects built-in export action in More menu. |
ExtraActions |
RenderFragment? |
null |
Optional custom trailing content in header action area. |
Models reference
Core data models
CloudDataGridColumnLabel,Key,Width,MinWidth,Sortable,Resizable,IsImagePinned(None,Left,Right),CssClass,Style,HeaderCssClass,HeaderStyleCellTemplate(RenderFragment<CloudDataGridCellContext>) for custom Razor components
CloudDataGridRowId,Link,Cells,Attributes,CssClass,StyleNote,NoteCssClass,NoteStylefor a viewport-anchored line beneath the rowCategoryKey,CategoryLabelfor collapsible grouping
CloudDataGridCell- Optional wrapper around a value with
CssClass,Style,Attributes, and a per-cellTemplate
- Optional wrapper around a value with
CloudDataGridFooterRow- Column-aligned footer
Cells, plus row-level styling and attributes
- Column-aligned footer
CloudDataGridDataRequestPage,PageSize,Search,Sort,IsAppend,Total
CloudDataGridDataResultRows,Page,PageSize,Total,ErrorMessage
CloudDataGridSortColumn,ColumnIndex,Direction,Key
Action models
CloudDataGridAction- Supports
Link,Button,Elementmodes viaCloudDataGridActionType - Placement flags:
ShowOnHeader,ShowInMore,ShowOnBulkHeader,ShowOnRow - Optional icon/text/tooltips and deactivation hooks for element actions
- Supports
CloudDataGridActionEventArgsAction,RecordIds
Enums
CloudDataGridPagingMode:Pages,LoadMore,InfiniteScrollCloudDataGridPaginationType:LeftArrow,RightArrowCloudDataGridSortDirection:Ascending,DescendingCloudDataGridActionType:Link,Button,Element
Paging modes
Pages (default)
- Footer shows previous/next paging controls
- New page replaces current rows
- Best for classic server paging
LoadMore
- Renders a load-more button at list end
- Emits next-page request and expects rows to be appended
InfiniteScroll
- Uses Blazor virtualization to fetch next page near list end
- Also expects append behavior
In append modes, ensure your DataProvider returns incremented Page and updated Total.
Pinning, styling, templates, totals, and row notes
Plain values in CloudDataGridRow.Cells remain supported. Wrap only the cells that need individual customization:
<CloudDataGrid Columns="_columns"
DataProvider="LoadAsync"
PagingMode="CloudDataGridPagingMode.InfiniteScroll"
ReserveRowNoteSpace="true"
ColumnFooterRows="_totals" />
@code {
private List<CloudDataGridColumn> _columns =
[
new() { Label = "Name", Pinned = CloudDataGridPinnedPosition.Left },
new() { Label = "Amount", Pinned = CloudDataGridPinnedPosition.Right },
new() { Label = "Status", CellTemplate = StatusTemplate }
];
private RenderFragment<CloudDataGridCellContext> StatusTemplate => context =>
@<StatusBadge Value="@(context.Value is true)" />;
private List<CloudDataGridFooterRow> _totals =
[
new() { Cells = ["Total", new CloudDataGridCell { Value = 1234, Style = "font-weight:700" }] }
];
private CloudDataGridRow ToRow(Order order) => new()
{
Id = order.Id,
CssClass = order.IsLate ? "late" : null,
Style = order.IsPriority ? "background:#fff7ed" : null,
Note = order.Note,
Cells =
[
order.Name,
new CloudDataGridCell { Value = order.Amount, Style = "color:#166534" },
order.IsActive
]
};
}
Column styles are defaults; a CloudDataGridCell style is appended afterward and can override them. The row note uses a fixed height so Blazor's virtualizer can calculate exact item positions. For infinite data where the first page has no notes but later pages might, set ReserveRowNoteSpace="true".
Collapsible row categories
Assign the same stable key to related rows. The grid inserts category headers into the same virtualized item stream as data rows:
<CloudDataGrid DataProvider="LoadAsync"
EnableRowCategories="true"
AllowCategoryCollapse="true"
@bind-CollapsedCategories="_collapsed"
CategoryHeaderTemplate="CategoryHeader" />
@code {
private HashSet<string> _collapsed = [];
private CloudDataGridRow ToRow(Employee employee) => new()
{
Id = employee.Id,
CategoryKey = employee.DepartmentId,
CategoryLabel = employee.DepartmentName,
Cells = [employee.Name, employee.Email]
};
private RenderFragment<CloudDataGridCategoryContext> CategoryHeader => category => @<text>
<strong>@category.Label</strong>
<span>@category.VisibleRowCount loaded</span>
</text>;
}
EnableRowCategories can be switched at runtime. CollapsedCategories uses stable keys, so expansion state survives data refreshes and paging.
Body height modes
FullHeight (default)
- Grid fills the full height of its parent container
- Header and footer stay fixed, only the row area between them scrolls
- Requires a parent with a definite height (e.g., a fixed-height wrapper or a flex/grid item that stretches)
- Best for admin dashboards, split-pane layouts, or full-page grids
<div style="height: 600px;">
<CloudDataGrid HeightMode="CloudDataGridHeightMode.FullHeight" ... />
</div>
RowHeight
- Grid is exactly tall enough to show
RowsPerPagerows (no more, no less) - Calculated as
RowsPerPage × var(--cloudgrid-row-height) - The body scrolls internally if accumulating paging (
LoadMore/InfiniteScroll) appends beyond that height - Best for embedding a grid in a content flow without forcing a container height
<CloudDataGrid HeightMode="CloudDataGridHeightMode.RowHeight" RowsPerPage="10" ... />
Auto
- Grid grows vertically to fit its content (all rows visible, no internal scroll by default)
- Optional
MaxHeightparameter caps the grid's height — once content exceeds the cap, it behaves likeFullHeight - Best for small record sets or dynamic-height scenarios where you want to avoid an artificial viewport
<CloudDataGrid HeightMode="CloudDataGridHeightMode.Auto" MaxHeight="500" ... />
Sorting behavior
If OnSortChanged is handled:
- grid updates visual sort indicator
- consumer reloads data server-side using
CloudDataGridSort.Key+Direction
If no handler is attached:
- grid sorts currently loaded rows locally
- nulls are pushed last
- mixed values are compared as case-insensitive text
Actions (header, row, bulk, more)
You can define one CloudDataGridAction list and control placement using flags.
new CloudDataGridAction
{
Key = "delete-selected",
Text = "Delete",
Type = CloudDataGridActionType.Button,
ShowOnBulkHeader = true,
ShowOnHeader = false
}
Placement guidance:
ShowOnHeader = true: direct header action areaShowInMore = true: appears in More (⋯) menuShowOnBulkHeader = true: appears only when rows are selectedShowOnRow = true: appears per row
Element actions can expand inline content and are cancellable.
Selection
Enable row selection:
<CloudDataGrid ... AllowSelection="true" @bind-SelectedRecords="_selected" />
Details:
- select-all operates on currently loaded rows
- selected IDs are exposed through two-way binding
- hidden input
#SelectedRecordsis rendered for legacy integrations
Row reordering
Enable and listen:
<CloudDataGrid ... AllowReordering="true" OnRowsReordered="HandleReorder" />
CloudDataGridRowReorder provides:
- moved
RecordId OldIndex,NewIndex- full
OrderedRecordIdsafter drop
Export
When Header.AllowExport = true (default), grid injects an export action in the More menu.
Built-in export options:
- Current page
- All records (using current search/sort)
- Selection (only shown when rows are selected)
Files are downloaded as CSV using the package JS module.
Styling and theming
The component uses scoped styles authored in *.razor.less and compiled to *.razor.css.
Core classes
.cloudgrid.cloudgrid-head,.cloudgrid-headcell.cloudgrid-row,.cloudgrid-cell.cloudgrid-status.cloudgridheader,.cloudgridheader-action
State classes
._busy._resizing._rowdragging._selectable- sorted state adjectives on head cells
CSS variables
| Variable | Default |
|---|---|
--cloudgrid-font-size |
14px |
--cloudgrid-row-height |
32px |
--cloudgrid-color |
#505050 |
--cloudgrid-background |
#fff |
--cloudgrid-accent-color |
#000 |
--cloudgrid-border-color |
rgba(0,0,0,0.15) |
--cloudgrid-head-background |
#f8f8f8 |
--cloudgrid-hover-background |
#e8e8e8 |
--cloudgrid-selected-background |
#f8f8f8 |
Header-specific variables (--cloudgridheader-*) fall back to matching --cloudgrid-* values.
Example:
:root {
--cloudgrid-accent-color: #0a5dc2;
--cloudgrid-row-height: 40px;
}
Troubleshooting
“Grid never loads data”
- Confirm
DataProvideris assigned. - Verify callback returns non-null
CloudDataGridDataResult.
“Sorting doesn’t affect backend data”
- Implement
OnSortChangedand applyrequest.Sortin your server query.
“LoadMore/InfiniteScroll keeps requesting”
- In append mode, stop adding rows once end is reached; keep
Totalaccurate.
“No export action visible”
- Ensure
Headeris set andAllowExportis true.
License
See repository licensing terms.
Angry Monkey Cloud
This project is part of the Angry Monkey Cloud open-source ecosystem. Follow the shared AI development instructions and browse the project catalog and GitHub organization.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- AngryMonkey.CloudComponents.Icons (>= 4.2.1)
- Microsoft.AspNetCore.Components.Web (>= 10.0.8)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on AngryMonkey.CloudComponents.DataGrid:
| Package | Downloads |
|---|---|
|
AngryMonkey.CloudLogin.Components
Package Description |
|
|
AngryMonkey.CDM.Components
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.