AstrolUI AstrolUI
Yellow Orange Red Green Blue Purple Custom color
Light mode
Grid

1. Demo AstrolGrid

Note:
In this example, confirmations, notifications, and buttons are implemented. It is advisable to refer to the documentation of each component for more details.
Full name
Age
1
Juan Pérez
34.56
Widower
True
25
01/01/2022
2
María García
23.14
Married
False
32
15/03/2021
3
Pedro Rodríguez
36.32
Single
True
45
30/06/2020
4
Laura Fernández
56.09
Divorced
False
19
28/02/2022
5
Carlos Sánchez
12.05
Married
True
56
01/12/2019
of 4
@using Astrol.Component.Basic.Grid
@using Astrol.Component.Basic.Button
@using Astrol.Component.Basic.Confirm
@using Astrol.Entities.Basic.Static.Notification
@using Astrol.Entities.Basic.UI
@using Astrol.JSInterop.Base
@inject AstrolJSInterop jsI
 
<AstrolConfirm @ref="_conf" />
<AstrolGrid TItem="Client" PageSize="5" Data="dataList" @ref="_grid">
 <Columns>
 <Column Name="@nameof(Client.Id)" Title="Id" Width="55px" Sortable="true" Resizable="true">
 <span>@context.Id</span>
 </Column>
 <Column Name="@nameof(Client.FullName)" Title="Full name" Width="200px" Filtrable="true" Resizable="true" />
 <Column ClassHead="blue-head" ClassRow="blue-row" Name="@nameof(Client.Points)" Title="Points" Sortable="true" Filtrable="true" Resizable="true" />
 <Column Name="@nameof(Client.MaritalStatus)" Title="Marital status" Sortable="true" Filtrable="true" Resizable="true" />
 <Column Name="@nameof(Client.Sex)" Title="Sex" Width="80px" Sortable="true" Filtrable="true" Resizable="true" />
 <Column Name="@nameof(Client.Age)" Title="Age" Filtrable="true" Resizable="true" />
 <Column Name="@nameof(Client.RegistrationDate)" Title="Date" Format="dd/MM/yyyy" TypeOf="typeof(DateOnly)" Sortable="true" Filtrable="true" Resizable="true" />
 <Column Width="60px">
 <AstrolButton Icon="astrol-trash" Title="Delete" Style="AstrolStyle.Red" OnClick="() => DeleteItem(context)" />
 </Column>
 </Columns>
</AstrolGrid>
<style>
 /* !important: the grid header and cells use scoped css */
 .blue-head {
 background-color: rgb(from var(--color-base) r g b / 80%) !important;
 }
 .blue-row {
 background-color: rgb(from var(--color-base) r g b / 40%) !important;
 }
</style>
@code {
 private AstrolGrid<Client>? _grid;
 private AstrolConfirm? _conf;
 private List<Client> dataList = new List<Client> {
 new Client { Id = 1, Points= 34.56F, Name = "Juan", Surnames = "Pérez", Sex = true, MaritalStatus = MaritalStatus.Widower, Age = 25, RegistrationDate = new DateTime(2022, 1, 1) },
 new Client { Id = 2, Points= 23.14F, Name = "María", Surnames = "García", Sex = false, MaritalStatus = MaritalStatus.Married, Age = 32, RegistrationDate = new DateTime(2021, 3, 15) },
 new Client { Id = 3, Points= 36.32F, Name = "Pedro", Surnames = "Rodríguez", Sex = true, Age = 45, MaritalStatus = MaritalStatus.Single, RegistrationDate = new DateTime(2020, 6, 30) },
 new Client { Id = 4, Points= 56.09F , Name = "Laura", Surnames = "Fernández", Sex = false, Age = 19, MaritalStatus = MaritalStatus.Divorced,RegistrationDate = new DateTime(2022, 2, 28) },
 new Client { Id = 5, Points= 12.05F, Name = "Carlos", Surnames = "Sánchez", Sex = true, Age = 56,MaritalStatus = MaritalStatus.Married, RegistrationDate = new DateTime(2019, 12, 1) },
 new Client { Id = 6,Points= 15.26F, Name = "Ana", Surnames = "Gómez", Age = 29, Sex = false, RegistrationDate = new DateTime(2021, 7, 10) },
 new Client { Id = 7,Points= 14.34F , Name = "Pablo", Surnames = "Martínez", Sex = true, Age = 41, MaritalStatus = MaritalStatus.Married, RegistrationDate = new DateTime(2022, 4, 5) },
 new Client { Id = 8,Points= 5.2F, Name = "Lucía", Surnames = "Jiménez", Age = 22,Sex = false, RegistrationDate = new DateTime(2023, 1, 2) },
 new Client { Id = 9,Points= 88.53F, Name = "Javier", Surnames = "Hernández",Sex = true, Age = 37,MaritalStatus = MaritalStatus.Married, RegistrationDate = new DateTime(2022, 9, 15) },
 new Client { Id = 10,Points= 45.23F , Name = "Sofía", Surnames = "Ruiz",Sex = false, Age = 28, RegistrationDate = new DateTime(2023, 3, 20) },
 new Client { Id = 11,Points= 32.54F, Name = "Miguel", Surnames = "López",Sex = true, Age = 60, MaritalStatus = MaritalStatus.Other, RegistrationDate = new DateTime(2020, 5, 11) },
 new Client { Id = 12,Points= 14.52F, Name = "Carmen", Surnames = "González",Sex = false, Age = 31, RegistrationDate = new DateTime(2021, 11, 16) },
 new Client { Id = 13,Points= 78.8F, Name = "Antonio", Surnames = "Santos",Sex = true, Age = 48, RegistrationDate = new DateTime(2020, 3, 7) },
 new Client { Id = 14,Points= 65.456F, Name = "Isabel", Surnames = "Ortega",Sex = false, Age = 20,MaritalStatus = MaritalStatus.Other, RegistrationDate = new DateTime(2022, 7, 31) },
 new Client { Id = 15,Points= 56, Name = "David", Surnames = "Ramírez",Sex = true,Age = 43, RegistrationDate = new DateTime(2019, 10, 25) },
 new Client { Id = 16,Points= 34.01F, Name = "Raquel", Surnames = "Pardo",Sex = false, Age = 26,MaritalStatus = MaritalStatus.Other, RegistrationDate = new DateTime(2021, 2, 14) },
 };
 private async Task DeleteItem(Client item) {
 if (await _conf!.Confirmation("Are you sure?", "Do you want to delete the item?")) {
 dataList.Remove(item);
 await jsI.Notification("Item removed successfully.".NotificationSuccess("astrol-ok"));
 await _grid!.RefreshGrid();
 }
 }
 public class Client {
 public int Id { get; set; }
 public string? Name { get; set; }
 public bool Sex { get; set; }
 public string? Surnames { get; set; }
 public int Age { get; set; }
 public float Points { get; set; }
 public DateTime RegistrationDate { get; set; }
 public MaritalStatus MaritalStatus { get; set; }
 public string FullName => $"{Name} {Surnames}";
 }
 public enum MaritalStatus {
 Single,
 Married,
 Divorced,
 Widower,
 Other
 }
}

Supported parameters

  • TItem (object), type of the grid rows.
  • Data (IEnumerable<TItem>), in-memory data: the grid sorts, filters and pages on the client without copying or modifying the list. If the content changes without changing the list, call RefreshGrid() or change DataVersion.
  • DataVersion (object), change it to force a refresh when the content of Data changes without changing the reference or the number of items. It also works with ReadItems (calls the server again).
  • ReadItems (EventCallback<GridResponse<TItem>>), server-side loading (see below). When set, Data is not used.
  • ShowLoad (bool), shows the loading animation while data is being fetched (default true).
  • IconLoad (string), loading icon (default astrol-spin5 ).
  • Pageable (bool), paging (default true).
  • PageSize (int), items per page (default 10).
  • PageSizeList (List<int>), page size options (default { 5, 10, 20, 50, 100, int.MaxValue }; int.MaxValue means "All").
  • Selectable (bool), rows selectable with a checkbox (default false).
  • KeySelector (Func<TItem, object?>), unique key of each row: keeps the selection across pages and reloads and improves performance when reordering.
  • OnSelected (EventCallback<List<TItem>>), raised when the selection changes, with the selected rows.
  • Virtualize (bool), renders only the visible rows; useful for large pages or no paging. RowHeight (float, approximate row height, default 41) and OverscanCount (int, default 5).
  • Options (RenderFragment), top area for grid buttons or options.
  • Texts (string): NoSearchResultText, PagePaginationText, OfPaginationText, PageSizePaginationText, ItemPaginationText, AllPaginationText, SelectAllText, SelectRowText. When not set, they follow the app language (English or Spanish). The pagination navigation button labels always come from AstrolText.
  • Methods and properties: RefreshGrid(resetSelection = true) reloads the data (by default it clears the selection without raising OnSelected; use RefreshGrid(false) to keep it), GridInfo (current page, sort and filters) and CurrentPageItems (visible rows).
  • Columns (RenderFragment), grid columns (<Column />). Inside a column, context is the row.
    • Name (string): property to display, sort and filter; supports paths like "Customer.Name". It is the value sent to the server in ColumnSort / ColumnFilter.
    • Field (Expression): typed alternative to Name, e.g. Field="x => x.Customer.Name".
    • Title (string): header text.
    • Format (string): value format when there is no custom content, e.g. "dd/MM/yyyy" or "N2".
    • Width (string): column width (default auto).
    • Sortable (bool): sorting when clicking the header (ascending, descending, none); requires Name or Field (default false).
    • Filtrable (bool): header filter based on the property type: text, number, date (DateOnly), date and time (DateTime), time (TimeOnly / TimeSpan), bool or enum; other types show no filter (default false).
    • FilterPlaceholder (string): filter placeholder.
    • TypeOf (Type): type used to choose the filter when it cannot be inferred, e.g. typeof(DateOnly).
    • DefaultValue (object): initial filter value.
    • Resizable (bool): width can be changed by dragging the right edge; it is kept when paging or sorting (default false).
    • Id (string): column identifier (optional).
    • ClassHead / ClassRow (string): css classes for the header and the cells.
    • ChildContent (RenderFragment<TItem>): custom cell content; the row is context.
  • ReadItems (EventCallback<GridResponse<TItem>>), loading from your API. It receives GridInfo and must fill AstrolPaginatedResponse:
    • GridInfo: Page (int), PageSize (int), SortInfo (ColumnSort, SortDirection: None / Ascending / Descending) and FilterInfo (list of ColumnFilter / ValueFilter).
    • AstrolPaginatedResponse<TItem>: TotalItems (int) and PageItems (IEnumerable<TItem>).
    • On the server you can use query.SortList(gridInfo.SortInfo).Paginate(gridInfo): it builds expressions that EF Core translates to SQL.
    • Filters are not applied automatically on the server: loop through FilterInfo and apply them to your query (ValueFilter arrives as text). Computed properties (e.g. FullName) sort in memory but EF Core cannot translate them to SQL.

2. Demo AstrolGrid selectable with options

Note:
This example simulates loading data from the server; rows are selectable and column filtering has been disabled.
KeySelector is needed to keep the selection across pages when data comes from the server (each read returns new objects). After changing the data call RefreshGrid() through @ref (it clears the selection; RefreshGrid(false) keeps it). DataVersion is optional: change it to force a refresh from parameters.
Age
1
Juan Pérez
34.56
Widower
True
25
01/01/2022
2
María García
23.14
Married
False
32
15/03/2021
3
Pedro Rodríguez
36.32
Single
True
45
30/06/2020
4
Laura Fernández
56.09
Divorced
False
19
28/02/2022
5
Carlos Sánchez
12.05
Married
True
56
01/12/2019
of 4
OnSelected:
@using Astrol.Component.Basic.Grid
@using Astrol.Component.Basic.Button
@using Astrol.Entities.Basic.UI
@using Astrol.Entities.Basic.UI.Grid
@using Astrol.Entities.Basic.Response
@using Astrol.Entities.Basic.Static.Extensions
 
<AstrolGrid TItem="Client" PageSize="5" ReadItems="ReadItems" Selectable="true"
 KeySelector="x => x.Id" OnSelected="OnSelected" @ref="_gridServer">
 <Options>
 <AstrolButton Icon="astrol-trash" Style="AstrolStyle.Red" Text="Delete"
 OnClick="DeleteSelected" Status="@(_selected.Count > 0)" />
 </Options>
 <Columns>
 <Column Name="@nameof(Client.Id)" Title="Id" Width="55px" Sortable="true" />
 <Column Name="@nameof(Client.FullName)" Title="Full name" Sortable="true" />
 <Column Name="@nameof(Client.Points)" Title="Points" Sortable="true" />
 <Column Name="@nameof(Client.MaritalStatus)" Title="Marital status" Sortable="true" />
 <Column Name="@nameof(Client.Sex)" Title="Sex" Width="80px" Sortable="true" />
 <Column Name="@nameof(Client.Age)" Title="Age" />
 <Column Name="@nameof(Client.RegistrationDate)" Title="Date" Format="dd/MM/yyyy" Sortable="true" />
 </Columns>
</AstrolGrid>
@code {
 private AstrolGrid<Client>? _gridServer;
 private List<Client> _selected = new();
 // Simulates the database table (on a real server: an EF Core IQueryable).
 private List<Client> _db = new List<Client> { /* same data as example 1 */ };
 
 private async Task ReadItems(GridResponse<Client> request) {
 await Task.Delay(200); // simulated latency
 // Sorts, counts and pages (Astrol.Entities.Basic.Static.Extensions)
 request.AstrolPaginatedResponse = _db.AsQueryable().ToPaginatedResponse(request.GridInfo);
 
 // Async EF Core: same steps with SortList + Paginate
 // var query = dbContext.Clients.SortList(request.GridInfo.SortInfo);
 // request.AstrolPaginatedResponse = new() {
 // TotalItems = await query.CountAsync(),
 // PageItems = await query.Paginate(request.GridInfo).ToListAsync() };
 }
 private void OnSelected(List<Client> selected) => _selected = selected;
 private async Task DeleteSelected() {
 var ids = _selected.Select(x => x.Id).ToHashSet();
 _db.RemoveAll(x => ids.Contains(x.Id));
 _selected = new();
 await _gridServer!.RefreshGrid(); // reads again and clears the selection
 }
}
Markdown for AI © 2026 AstrolUI v10.0.13