Skip to content

Commit

Permalink
#502 [doc] Cleanup demos in documentation by using IDemoDataService -…
Browse files Browse the repository at this point in the history
… HxGrid (WIP)
  • Loading branch information
hakenr committed Jan 12, 2024
1 parent d51e819 commit 5e22010
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 140 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@inject IDemoDataService DemoDataService

<HxGrid TItem="EmployeeDto" DataProvider="GetGridData" PageSize="5" Responsive="true">
<Columns>
<HxGridColumn HeaderText="Name" ItemTextSelector="employee => employee.Name" />
<HxGridColumn HeaderText="Phone" ItemTextSelector="employee => employee.Phone" />
<HxGridColumn HeaderText="Salary" ItemTextSelector="@(employee => employee.Salary.ToString("c0"))" />
<HxGridColumn HeaderText="Position" ItemTextSelector="employee => employee.Position" />
<HxGridColumn HeaderText="Location" ItemTextSelector="employee => employee.Location" />
</Columns>
</HxGrid>

@code {
private async Task<GridDataProviderResult<EmployeeDto>> GetGridData(GridDataProviderRequest<EmployeeDto> request)
{
// you usually pass the data-request to your API/DataLayer
return new GridDataProviderResult<EmployeeDto>()
{
Data = await DemoDataService.GetEmployeesDataFragmentAsync(request.StartIndex, request.Count, request.CancellationToken),
TotalCount = await DemoDataService.GetEmployeesCountAsync(request.CancellationToken)
};
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
<HxGrid TItem="CultureInfo" Responsive="true" DataProvider="GetGridData" PageSize="10">
@inject IDemoDataService DemoDataService

<HxGrid TItem="EmployeeDto" DataProvider="GetGridData" PageSize="5" Responsive="true">
<Columns>
<HxGridColumn HeaderText="LCID" ItemTextSelector="@(item => item.LCID.ToString())" SortKeySelector="@(item => item.LCID)" IsDefaultSortColumn="true" />
<HxGridColumn HeaderText="DisplayName" ItemTextSelector="@(item => item.DisplayName)" SortKeySelector="@(item => item.DisplayName)" />
<HxGridColumn HeaderText="Name" ItemTextSelector="@(item => item.Name)" SortKeySelector="@(item => item.Name)" />
<HxGridColumn HeaderText="EnglishName" ItemTextSelector="@(item => item.EnglishName)" SortKeySelector="@(item => item.EnglishName)" />
<HxGridColumn HeaderText="Name" ItemTextSelector="employee => employee.Name" SortKeySelector=" employee => employee.Name" IsDefaultSortColumn="true" />
<HxGridColumn HeaderText="Phone" ItemTextSelector="employee => employee.Phone" SortKeySelector=" employee => employee.Phone" />
<HxGridColumn HeaderText="Salary" ItemTextSelector="@(employee => employee.Salary.ToString("c0"))" SortKeySelector="employee => employee.Salary" />
<HxGridColumn HeaderText="Position" ItemTextSelector="employee => employee.Position" SortKeySelector="employee => employee.Position" />
<HxGridColumn HeaderText="Location" ItemTextSelector="employee => employee.Location" SortKeySelector="employee => employee.Location" />
</Columns>
</HxGrid>

@code {
private List<CultureInfo> localCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).ToList();
private IEnumerable<EmployeeDto> employees;

protected override void OnInitialized()
{
employees = DemoDataService.GetAllEmployees();
}

private Task<GridDataProviderResult<CultureInfo>> GetGridData(GridDataProviderRequest<CultureInfo> request)
private Task<GridDataProviderResult<EmployeeDto>> GetGridData(GridDataProviderRequest<EmployeeDto> request)
{
return Task.FromResult(request.ApplyTo(localCultureInfos));
return Task.FromResult(request.ApplyTo(employees));
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@inject IDemoDataService DemoDataService

<HxGrid TItem="EmployeeDto" DataProvider="GetGridData" Responsive="true">
<Columns>
<HxGridColumn HeaderText="Name" ItemTextSelector="employee => employee.Name" />
<HxGridColumn HeaderText="Phone" ItemTextSelector="employee => employee.Phone" />
<HxGridColumn HeaderText="Salary" ItemTextSelector="@(employee => employee.Salary.ToString("c0"))" />
<HxGridColumn HeaderText="Position" ItemTextSelector="employee => employee.Position" />
<HxGridColumn HeaderText="Location" ItemTextSelector="employee => employee.Location" />
</Columns>
</HxGrid>

@code {
private async Task<GridDataProviderResult<EmployeeDto>> GetGridData(GridDataProviderRequest<EmployeeDto> request)
{
await Task.Delay(3000); // simulate server delay in demo (do not put this in your code)
return new GridDataProviderResult<EmployeeDto>
{
Data = null,
TotalCount = 0
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@inject IDemoDataService DemoDataService

<style>
.virtualized-table-container {
height: 400px;
overflow: auto;
}
</style>

<HxGrid TItem="EmployeeDto"
DataProvider="GetGridData"
TableContainerCssClass="virtualized-table-container"
ContentNavigationMode="GridContentNavigationMode.InfiniteScroll"
ItemRowHeight="41"
PageSize="5"
Responsive="true">
<Columns>
<HxGridColumn HeaderText="Name" ItemTextSelector="employee => employee.Name" />
<HxGridColumn HeaderText="Phone" ItemTextSelector="employee => employee.Phone" />
<HxGridColumn HeaderText="Salary" ItemTextSelector="@(employee => employee.Salary.ToString("c0"))" />
<HxGridColumn HeaderText="Position" ItemTextSelector="employee => employee.Position" />
<HxGridColumn HeaderText="Location" ItemTextSelector="employee => employee.Location" />
</Columns>
</HxGrid>

<p class="mt-3">@debugOutput</p>

@code {
string debugOutput;

private async Task<GridDataProviderResult<EmployeeDto>> GetGridData(GridDataProviderRequest<EmployeeDto> request)
{
debugOutput = $"Requesting data: StartIndex={request.StartIndex}, Count={request.Count}";
StateHasChanged();

await Task.Delay(500); // simulate server delay in demo (do not put this in your code)
return new GridDataProviderResult<EmployeeDto>()
{
Data = await DemoDataService.GetEmployeesDataFragmentAsync(request.StartIndex, request.Count, request.CancellationToken),
TotalCount = await DemoDataService.GetEmployeesCountAsync(request.CancellationToken)
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@
@code {
private async Task<GridDataProviderResult<EmployeeDto>> GetGridData(GridDataProviderRequest<EmployeeDto> request)
{
await Task.Delay(100); // simulate server delay
var query = DemoDataService.GetEmployeesAsQueryable(); // this can be dbContext.Employees or whatever IQueryable<> you have
var query = DemoDataService.GetEmployeesAsQueryable();
// query = query.Where();
await Task.Delay(100); // simulate server delay in demo (do not put this in your code)
return new GridDataProviderResult<EmployeeDto>()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
<HxGrid @ref="gridComponent" TItem="CultureInfo" Responsive="true" DataProvider="GetGridData" PageSize="5">
<Columns>
<HxGridColumn HeaderText="LCID" ItemTextSelector="@(item => item.LCID.ToString())" SortKeySelector="@(item => item.LCID)" IsDefaultSortColumn="true" />
<HxGridColumn HeaderText="DisplayName" ItemTextSelector="@(item => item.DisplayName)" SortKeySelector="@(item => item.DisplayName)" />
<HxGridColumn HeaderText="Name" ItemTextSelector="@(item => item.Name)" SortKeySelector="@(item => item.Name)" />
<HxGridColumn HeaderText="EnglishName" ItemTextSelector="@(item => item.EnglishName)" SortKeySelector="@(item => item.EnglishName)" />
@inject IDemoDataService DemoDataService

<HxGrid @ref="gridComponent" TItem="EmployeeDto" DataProvider="GetGridData" PageSize="5" Responsive="true">
<Columns>
<HxGridColumn HeaderText="Name" ItemTextSelector="employee => employee.Name" />
<HxGridColumn HeaderText="Phone" ItemTextSelector="employee => employee.Phone" />
<HxGridColumn HeaderText="Salary" ItemTextSelector="@(employee => employee.Salary.ToString("c0"))" />
<HxGridColumn HeaderText="Position" ItemTextSelector="employee => employee.Position" />
<HxGridColumn HeaderText="Location" ItemTextSelector="employee => employee.Location" />
</Columns>
</HxGrid>

<HxButton Text="Refresh data" OnClick="HandleButtonClick" Color="ThemeColor.Primary" />

@code {
private HxGrid<CultureInfo> gridComponent;
private List<CultureInfo> localCultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures).ToList();
private HxGrid<EmployeeDto> gridComponent;

private async Task<GridDataProviderResult<EmployeeDto>> GetGridData(GridDataProviderRequest<EmployeeDto> request)
{
await Task.Delay(1000); // simulate 1s server delay in demo (do not put this in your code)
private async Task<GridDataProviderResult<CultureInfo>> GetGridData(GridDataProviderRequest<CultureInfo> request)
{
await Task.Delay(1000); // simulate 1sec data-gathering latency
return request.ApplyTo(localCultureInfos);
}
return new GridDataProviderResult<EmployeeDto>()
{
Data = await DemoDataService.GetEmployeesDataFragmentAsync(request.StartIndex, request.Count, request.CancellationToken),
TotalCount = await DemoDataService.GetEmployeesCountAsync(request.CancellationToken)
};
}

private async Task HandleButtonClick()
{
await gridComponent.RefreshDataAsync();
}
}
private async Task HandleButtonClick()
{
await gridComponent.RefreshDataAsync();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,94 @@
<ComponentApiDoc Type="typeof(HxGrid<TItem>)">
<MainContent>

<DocHeading Title="Data binding" />
<DocHeading Title="Basic usage" />
<p>
Implement the <code>@nameof(HxGrid<object>.DataProvider)</code> method which is provided with a "request"
(requested sorting and paging) and returns a "result" (items to display and total count of items).
To define <strong>columns</strong>, use the <code>HxGridColumn</code> components.
You can specify the <code>HeaderText</code> and <code>ItemTextSelector</code> parameters.
</p>
<p>
To connect the grid to your <strong>data</strong>, implement the <code>@nameof(HxGrid<object>.DataProvider)</code> method.
This method receives a "request" (for sorting and paging requirements) and yields a "result" (items for display along with the total item count).
</p>
<Demo Type="typeof(HxGrid_Demo_DataProvider)" />
<Demo Type="typeof(HxGrid_Demo)" Tabs="false" />
<DocAlert Type="DocAlertType.Warning">
The <code>@nameof(HxGrid).@nameof(HxGrid<object>.DataProvider)</code> should always return
an instance of <code>@nameof(GridDataProviderResult<object>)</code>, <code>null</code> is not allowed.
The method you provide should be <code>async</code> and should
<code>await</code> the data if needed (loading progress is indicated in the meantime).
</DocAlert>


<DocHeading Title="Automatic sorting and paging" Id="ApplyTo" />
<p>
If you have your <code>IEnumerable</code> data-source ready (all items), you can use the <code>request.ApplyTo(data)</code>
extension method to apply sorting and paging automatically.
If you have your <code>IEnumerable</code> data-source ready (all items preloaded in memory),
you can use the <code>request.ApplyTo(data)</code> extension method to apply sorting and paging automatically.
</p>
<Demo Type="typeof(HxGrid_Demo_ApplyTo)" />

<DocHeading Title="IQueryable usage" Id="Queryable" Level="3" />
<p>
If you have <code>IQueryable</code> as a data-source provider, you can use the <code>data.ApplyGridDataProviderRequest(request)</code>
method to apply sorting and paging to your data source. Then you must query data on your own, because we do not have access to cancellable async methods
in the components (CountAsync, ToListAsync) and it is quite crucial to use cancellable methods, mainly for infinite scroll.
</p>
<Demo Type="typeof(HxGrid_Demo_Queryable)" />

<DocHeading Title="Using IQueryable" Id="IQueryable" Level="3" />
<p>
When utilizing <code>IQueryable</code> as your data source provider, commonly seen in Blazor Server applications,
you can employ the <code>data.ApplyGridDataProviderRequest(request)</code> method.
</p>
<p>
This method enables the application of sorting and paging to your data source.
Subsequently, you are required to "execute" the queries independently.
This necessity arises because our components lack access to cancellable asynchronous methods
such as <code>CountAsync</code> and <code>ToListAsync</code>.
Employing cancellable methods is particularly critical in scenarios like infinite scrolling.
</p>
<Demo Type="typeof(HxGrid_Demo_Queryable)" />

<DocAlert Type="DocAlertType.Warning">
The <code>@nameof(HxGrid).@nameof(HxGrid<object>.DataProvider)</code> should always return an instance of <code>@nameof(GridDataProviderResult<object>)</code>, <code>null</code> is not allowed.
The method you provide is <code>async</code> and should <code>await</code> the data if needed (loading progress is indicated in the meantime).
</DocAlert>

<DocHeading Title="Refreshing data" Id="RefreshData" />
<p>
Whenever you need to refresh data in the grid (e.g. when the filter to be applied changes),
call the <code>gridComponent.RefreshDataAsync()</code> method to let the grid know
it should ask the <code>DataProvider</code> for fresh data.
To refresh data in the grid, such as when there's a change in the filter being applied,
use the <code>gridComponent.RefreshDataAsync()</code> method.
This action informs the grid to request updated data from the <code>DataProvider</code>.
</p>
<Demo Type="typeof(HxGrid_Demo_RefreshData)" />


<DocHeading Title="Empty data" />
<p>When the <code>DataProvider</code> returns no data, the <code>EmptyDataTemplate</code> is rendered (when not set, the <code>&lt;HxGridDefaultEmptyDataTemplateContent /&gt;</code> is used).</p>
<Demo Type="typeof(HxGrid_EmptyDataDemo)" />
<p>
When the <code>DataProvider</code> returns no data, the <code>EmptyDataTemplate</code> is rendered.
If you do not set your own content, the <code>&lt;HxGridDefaultEmptyDataTemplateContent /&gt;</code> is used.
</p>
<Demo Type="typeof(HxGrid_Demo_EmptyData)" />



<DocHeading Title="Content navigation modes" />
<p>
<code>HxGrid</code> has several navigation modes, which can be set using the <code>ContentNavigationMode</code> parameter.
The default navigation mode is <code>Pagination</code>.
</p>
<code>HxGrid</code> offers various navigation modes, configurable through the <code>ContentNavigationMode</code> parameter.
The default mode is set to <code>Pagination</code>.
</p>


<DocHeading Title="Infinite scroll (Virtualized)" Id="InfiniteScroll" Level="3" />
<p>
You can switch from paging to infinite-scroll by setting <code>ContentNavigationMode="GridContentNavigationMode.InfiniteScroll"</code>.
Use a Placeholder (<code>&lt;Placeholder&gt;...&lt;/Placeholder&gt;</code>) to display content until the item data is available.
To transition from paging to infinite scroll, set <code>ContentNavigationMode="GridContentNavigationMode.InfiniteScroll"</code>.
</p>
<DocAlert Type="DocAlertType.Warning">
The <code>ItemRowHeight</code> parameter should be set for the virtualization to work properly. The default value is 41 pixels (default table row height in Bootstrap).
</DocAlert>
<Demo Type="typeof(HxGrid_VirtualizedDemo)" />
It's important to specify the <code>ItemRowHeight</code> for effective virtualization. By default, it is 41 pixels, aligning with the standard table row height in Bootstrap.
</DocAlert>
<Demo Type="typeof(HxGrid_Demo_InfiniteScroll)" />


<DocHeading Title="Load more button" Id="LoadMore" Level="3" />
<p>With <code>ContentNavigationMode.LoadMore</code> you can allow loading additional items with a <i>Load more</i> button.</p>
<Demo Type="typeof(HxGrid_Demo_LoadMore)" />
<Demo Type="typeof(HxGrid_Demo_LoadMore)" />
<p>
Button text can be customized with <code>LoadMoreButtonText</code> or you can create your own navigation with
<code>LoadMoreTemplate</code> (with the help of the <code>context.LoadMoreAsync()</code> method).<br />
Customize the button text using <code>LoadMoreButtonText</code>, or design your own navigation interface with <code>LoadMoreTemplate</code>.
This customization can be achieved using the <code>context.LoadMoreAsync()</code> method.
</p>
<p>
You can combine <i>Load more</i> button with pagination by using <code>GridContentNavigationMode.PaginationAndLoadMore</code>.
It's also possible to combine the <i>Load More</i> button with pagination by opting for <code>GridContentNavigationMode.PaginationAndLoadMore</code>.
</p>


<DocHeading Title="Context menu" Id="context-menu" />
<p>Use <code>HxContextMenuGridColumn</code> to add context-menu to the grid.</p>
<Demo Type="typeof(HxGrid_Demo_ContextMenu)" />
Expand Down

This file was deleted.

Loading

0 comments on commit 5e22010

Please sign in to comment.