CleanCodeJN.GenericApis.DataGrid 1.3.4

dotnet add package CleanCodeJN.GenericApis.DataGrid --version 1.3.4
                    
NuGet\Install-Package CleanCodeJN.GenericApis.DataGrid -Version 1.3.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CleanCodeJN.GenericApis.DataGrid" Version="1.3.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CleanCodeJN.GenericApis.DataGrid" Version="1.3.4" />
                    
Directory.Packages.props
<PackageReference Include="CleanCodeJN.GenericApis.DataGrid" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CleanCodeJN.GenericApis.DataGrid --version 1.3.4
                    
#r "nuget: CleanCodeJN.GenericApis.DataGrid, 1.3.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CleanCodeJN.GenericApis.DataGrid@1.3.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CleanCodeJN.GenericApis.DataGrid&version=1.3.4
                    
Install as a Cake Addin
#tool nuget:?package=CleanCodeJN.GenericApis.DataGrid&version=1.3.4
                    
Install as a Cake Tool

CleanCodeJN.GenericApis.DataGrid

A generic, server-side MudBlazor table component for CleanCodeJN.GenericApis.

Drop <CCJNDataGrid> onto any Blazor page and point it at your GraphQL endpoint — columns, types, paging, sorting and search are all handled automatically.

Requirements

  • The backend must use CleanCodeJN.GenericApis with HotChocolate's auto-wiring (UseProjection, UseFiltering, UseSorting)
  • MudBlazor must be configured in the host app (wwwroot/index.html / App.razor)

Installation

dotnet add package CleanCodeJN.GenericApis.DataGrid

Setup

Register the services in Program.cs:

builder.Services.AddCleanCodeJNDataGrid();

This registers MudServices, the named HttpClient and GraphQLDataGridService in one call.

Add the MudBlazor layout components to your App.razor or MainLayout.razor if not already present:

<MudThemeProvider />
<MudPopoverProvider />
<MudDialogProvider />
<MudSnackbarProvider />

Usage

@using CleanCodeJN.GenericApis.DataGrid.Components

<CCJNDataGrid TDto="CustomerGetDto"
              GraphQLEndpoint="https://your-api/graphql"
              EntityName="customer"
              Title="Customers" />

EntityName is the lowercase GraphQL query field name — matches typeof(TEntity).Name.ToLowerInvariant() as generated by AutoQueryTypeExtensions.

Parameters

Parameter Type Required Default Description
GraphQLEndpoint string yes Full URL of the GraphQL endpoint
EntityName string yes Lowercase GraphQL query field name (e.g. "customer")
Title string no "" Heading rendered above the table
Searchable bool no true Show the search text field
Dense bool no false Compact row height
Striped bool no true Alternating row colours
Elevation int no 2 MudPaper shadow elevation
BearerToken string? no null Forwarded as Authorization: Bearer … header
ExcludedProperties HashSet<string> no [] DTO property names to hide (e.g. navigation properties)
PageSizeOptions int[] no [10,25,50,100] Page-size choices in the pager footer
ColumnHeaders Dictionary<string,string>? no null Custom column headers — maps property name → display label
HiddenProperties HashSet<string> no [] Requested from the server but given no column — for values a row dialog or cell template needs
Hover bool no true Highlight the row under the cursor
OnRowClick EventCallback<TDto> no Raised with the clicked row's item; the edit and delete buttons do not trigger it
RowClass string? no null CSS class on every row — e.g. cursor-pointer for a clickable table
RowStyle string? no null Inline style on every row
RowClassFunc Func<TDto,int,string>? no null Per-row CSS class, added on top of RowClass
RowStyleFunc Func<TDto,int,string>? no null Per-row inline style, added on top of RowStyle
ViewFormContent RenderFragment<TDto>? no null Read-only detail dialog opened by a row click, with nothing but a close button
ViewTitle string? no null Heading of that dialog; falls back to Title
CloseLabel string no "Close" Label of that dialog's only button
Columns RenderFragment? no null Explicit CCJNColumn children; replaces auto-detection
EditOnRowClick bool no false A row click opens the edit dialog; the pencil button is dropped
SubmitLabel string no "Save" Save button in the add and edit dialogs
CancelLabel string no "Cancel" Cancel button in every dialog
DeleteLabel string no "Delete" Confirming button in the delete dialog
DeleteTitle string no "Confirm Delete" Heading of the delete dialog
AddTitle string? no null Heading of the add dialog; falls back to Add {Title}
EditTitle string? no null Heading of the edit dialog; falls back to Edit {Title}
SearchLabel string no "Search..." Placeholder of the search field
NoRecordsLabel string no "No entries found..." Shown when the query came back empty
LoadingLabel string no "Data will be loaded..." Shown while rows are being fetched
DeleteConfirmText string no "Are you sure…" Question asked before deleting

Clickable rows

OnRowClick gives you the item, RowClass the cursor:

<CCJNDataGrid TDto="InvoiceGetDto" ...
              RowClass="cursor-pointer"
              OnRowClick="OpenAsync" />

For a plain detail view there is no need to write a dialog at all — ViewFormContent opens one that carries just a close button:

<CCJNDataGrid TDto="InvoiceGetDto" ...
              RowClass="cursor-pointer"
              ViewTitle="Invoice"
              CloseLabel="Close"
              HiddenProperties="@(new HashSet<string> { "Notes" })">
    <ViewFormContent Context="row">
        <MudText Typo="Typo.subtitle2">@row.Number</MudText>
        <MudText Typo="Typo.body2" Style="white-space:pre-wrap">@row.Notes</MudText>
    </ViewFormContent>
</CCJNDataGrid>

The grid carries several templated parameters, so Blazor wants each fragment's item named — Context="row" above. Writing @context without it does not compile.

Notes is listed under HiddenProperties: the dialog needs the value, the table does not need the column. ExcludedProperties would drop it from the query as well and the dialog would stay empty.

The same switches exist on CCJNDataGridDialog itself (ShowSubmit, ShowCancel, CloseLabel) if you open it yourself.

Where rows are editable, a read-only view is usually one dialog too many. EditOnRowClick sends the click straight into the edit dialog and drops the pencil button; the action column disappears entirely once nothing is left in it:

<CCJNDataGrid TDto="InvoiceGetDto" ...
              AllowEdit="true" EditOnRowClick="true"
              RowClass="cursor-pointer"
              SubmitLabel="Speichern" CancelLabel="Abbrechen" />

Explicit columns

Declare CCJNColumn children to control which columns appear, in which order, and how a cell is rendered. As soon as one is declared, auto-detection is off and the declared columns are the table:

<CCJNDataGrid TDto="InvoiceGetDto" ... >
    <Columns>
        <CCJNColumn TDto="InvoiceGetDto" Property="Number" Title="Invoice" />
        <CCJNColumn TDto="InvoiceGetDto" Title="Customer" SortBy="CustomerName"
                    Fields="@(new[] { "CustomerName", "CustomerEmail" })">
            <CellTemplate Context="row">
                <div>@row.CustomerName</div>
                <MudText Typo="Typo.caption">@row.CustomerEmail</MudText>
            </CellTemplate>
        </CCJNColumn>
        <CCJNColumn TDto="InvoiceGetDto" Property="Status">
            <CellTemplate Context="row">
                <MudChip T="string" Size="Size.Small">@row.Status</MudChip>
            </CellTemplate>
        </CCJNColumn>
    </Columns>
</CCJNDataGrid>
Column parameter Type Description
Property string? DTO property shown; omit for a column built entirely by the template
Title string? Header text; falls back to the property name split on capitals
Sortable bool? Defaults to on for property-backed columns, off for template-only ones
SortBy string? Property to sort by when it differs from Property
Fields string[]? Further properties the template reads; requested but given no column
CellTemplate RenderFragment<TDto>? Custom cell rendering, receiving the row item — name it via Context

The key property is always requested, whether or not it has a column — edit and delete need it. The same goes for the fields of the edit form: it writes all of them back, so a value that was never loaded would be saved as its default and quietly overwrite what was there.

Column auto-detection

Columns are discovered automatically from the DTO via reflection. Scalar types are included; complex objects and collections are skipped.

Supported types: string, bool, char, byte, short, int, long, float, double, decimal, DateTime, DateTimeOffset, DateOnly, TimeOnly, TimeSpan, Guid, and all enum types (including nullable variants).

Property names are converted to headers by inserting spaces before each capital letter (FirstNameFirst Name). Override any header via ColumnHeaders.

The search field queries all scalar columns simultaneously via a single GraphQL where: { or: [...] } clause:

  • String columnscontains (case-insensitive, server-side)
  • Numeric / Guid / bool columnseq (only applied when the search term is parseable as that type)

Search fires 500 ms after the last keystroke (debounce). The clear button resets immediately.

Example with all options

<CCJNDataGrid TDto="InvoiceGetDto"
              GraphQLEndpoint="@Endpoint"
              EntityName="invoice"
              Title="Invoices"
              Searchable="true"
              Dense="true"
              Striped="false"
              Elevation="4"
              BearerToken="@_token"
              ExcludedProperties="@(new HashSet<string> { "Customer", "InternalNotes" })"
              PageSizeOptions="@(new[] { 5, 10, 25 })"
              ColumnHeaders="@(new Dictionary<string, string>
              {
                  ["Id"]         = "Invoice ID",
                  ["CustomerId"] = "Customer",
                  ["Amount"]     = "Amount (€)",
              })" />

Programmatic reload

Expose a reference to the component and call ReloadTable() from code:

<CCJNDataGrid @ref="_grid" TDto="CustomerGetDto" ... />

@code {
    private CCJNDataGrid<CustomerGetDto> _grid = default!;

    private async Task Refresh() => await _grid.ReloadTable();
}

License

MIT

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
1.3.4 8 8/14/2026
1.3.3 9 8/14/2026
1.3.2 33 8/14/2026
1.3.1 31 8/14/2026
1.3.0 48 8/14/2026
1.2.0 138 3/31/2026
1.1.0 113 3/30/2026
1.0.0 118 3/27/2026

Rows and columns are now yours to shape. OnRowClick, RowClass, RowStyle, RowClassFunc and RowStyleFunc make the table clickable,
     ViewFormContent opens a read-only detail dialog on a row click, and CCJNDataGridDialog gained ShowSubmit, ShowCancel and CloseLabel
     so a dialog can carry nothing but a close button. Declaring CCJNColumn children switches auto-detection off and puts the set of
     columns, their order and their cell rendering under your control, while HiddenProperties keeps values in the query that deserve
     no column of their own.