# Grid
> AstrolGrid is a Blazor component used to represent information, providing a grid system to display organized data using rows and columns. It allows for essential functionalities such as applying filters, sorting, pagination, and more.
Source page: https://doc.astrolui.com/basic-component/grid
## 1. Demo AstrolGrid
In this example, [confirmations](/basic-component/confirm), [notifications](/basic-component/notification), and [buttons](/basic-component/button) are implemented. It is advisable to refer to the documentation of each component for more details.
```razor
@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
@context.Id
@code {
```
```csharp
private AstrolGrid? _grid;
private AstrolConfirm? _conf;
private List dataList = new List {
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)**, 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>)**, 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)**, 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)**, unique key of each row: keeps the selection across pages and reloads and improves performance when reordering.
- OnSelected **(EventCallback>)**, 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 (****). 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): custom cell content; the row is **context**.
- ReadItems **(EventCallback>)**, 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**: **TotalItems** (int) and **PageItems** (IEnumerable).
- 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
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.
```razor
@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
@code {
```
```csharp
private AstrolGrid? _gridServer;
private List _selected = new();
// Simulates the database table (on a real server: an EF Core IQueryable).
private List _db = new List { /* same data as example 1 */ };
private async Task ReadItems(GridResponse 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 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
}
}
```