Skip to content

Commit

Permalink
PR to fix template and grid issues introduced with 4.4.0 (#1447)
Browse files Browse the repository at this point in the history
* Fix #1436

* Fix #1444, Fix #1433, Fix #1437

* Cleanup IssueTester

* Fix #1461
  • Loading branch information
vnbaaij committed Feb 6, 2024
1 parent 47025fb commit 639ad8f
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1348,7 +1348,7 @@
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.NoTabbing">
<summary>
Gets or sets a value indicating whether the component will not add itself to the tab queue.
Gets or sets a value indicating whether the component will not add itself to the tab queue.
Default is false.
</summary>
</member>
Expand All @@ -1375,12 +1375,13 @@
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.RowClass">
<summary>
Optionally defines a class to be applied to a rendered row.
Optionally defines a class to be applied to a rendered row.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.RowStyle">
<summary>
Optionally defines a style to be applied to a rendered row.
Optionally defines a style to be applied to a rendered row.
Do not use to dynamically update a row style after rendering as this will interfere with the script that use this attribute. Use <see cref="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.RowClass"/> instead.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.EmptyContent">
Expand Down
2 changes: 1 addition & 1 deletion examples/Demo/Shared/Pages/Lab/IssueTester.razor
Original file line number Diff line number Diff line change
@@ -1 +1 @@
@page "/IssueTester"
@page "/IssueTester"
107 changes: 66 additions & 41 deletions src/Core/Components/DataGrid/FluentDataGrid.razor
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
class="@GridClass()"
style="@Style"
aria-rowcount="@(_ariaBodyRowCount + 1)"
@onrowfocus=HandleOnRowFocus
@onrowfocus=HandleOnRowFocusAsync

Check failure on line 23 in src/Core/Components/DataGrid/FluentDataGrid.razor

View workflow job for this annotation

GitHub Actions / Build and deploy Demo site

The name 'HandleOnRowFocusAsync' does not exist in the current context

Check failure on line 23 in src/Core/Components/DataGrid/FluentDataGrid.razor

View workflow job for this annotation

GitHub Actions / Build and deploy Demo site

The name 'HandleOnRowFocusAsync' does not exist in the current context
@onclosecolumnoptions="CloseColumnOptions"
@attributes="AdditionalAttributes">
@if (GenerateHeader != GenerateHeaderOption.None)
Expand All @@ -33,55 +33,33 @@
</FluentDataGridRow>
}

@if (_ariaBodyRowCount == 0 && Loading)
@if (Loading)
{
<FluentDataGridRow TGridItem="TGridItem" Class="loading-content-row">
<FluentDataGridCell Class="loading-content-cell">
@if (LoadingContent is null)
{
<FluentStack HorizontalGap="3">
<FluentProgressRing Width="24px" /> <div>Loading...</div>
</FluentStack>
}
else
{
@LoadingContent
}
</FluentDataGridCell>
</FluentDataGridRow>
}
else if (_ariaBodyRowCount == 0 && !Loading && !_manualGrid)
{
<FluentDataGridRow TGridItem="TGridItem" Class="empty-content-row">
<FluentDataGridCell Class="empty-content-cell">
@if (EmptyContent is null)
{
@("No data to show!")
}
else
{
@EmptyContent
}
</FluentDataGridCell>
</FluentDataGridRow>
@_renderLoadingContent
}
else
{
@if (Virtualize)
{
<Virtualize @ref="@_virtualizeComponent"
TItem="(int RowIndex, TGridItem Data)"
ItemSize="@ItemSize"
ItemsProvider="@ProvideVirtualizedItems"
ItemContent="@(item => builder => RenderRow(builder, item.RowIndex, item.Data))"
Placeholder="@(placeholderContext => builder => RenderPlaceholderRow(builder, placeholderContext))" />
if (_ariaBodyRowCount == 0)
{
@_renderEmptyContent
}
else
{
<Virtualize @ref="@_virtualizeComponent"
TItem="(int RowIndex, TGridItem Data)"
ItemSize="@ItemSize"
ItemsProvider="@ProvideVirtualizedItemsAsync"

Check failure on line 53 in src/Core/Components/DataGrid/FluentDataGrid.razor

View workflow job for this annotation

GitHub Actions / Build and deploy Demo site

The name 'ProvideVirtualizedItemsAsync' does not exist in the current context

Check failure on line 53 in src/Core/Components/DataGrid/FluentDataGrid.razor

View workflow job for this annotation

GitHub Actions / Build and deploy Demo site

The name 'ProvideVirtualizedItemsAsync' does not exist in the current context
ItemContent="@(item => builder => RenderRow(builder, item.RowIndex, item.Data))"
Placeholder="@(placeholderContext => builder => RenderPlaceholderRow(builder, placeholderContext))" />
}
}
else
{
@_renderNonVirtualizedRows
}
}

@if (_manualGrid)
{
@ChildContent
Expand All @@ -95,9 +73,16 @@
{
var initialRowIndex = (GenerateHeader != GenerateHeaderOption.None) ? 2 : 1; // aria-rowindex is 1-based, plus 1 if there is a header
var rowIndex = initialRowIndex;
foreach (var item in _currentNonVirtualizedViewItems)
if (_currentNonVirtualizedViewItems.Any())
{
RenderRow(__builder, rowIndex++, item);
foreach (var item in _currentNonVirtualizedViewItems)
{
RenderRow(__builder, rowIndex++, item);
}
}
else
{
RenderEmptyContent(__builder);
}
}

Expand All @@ -122,7 +107,7 @@

private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext)
{
string? _rowsDataSize = Loading ? "height: 100%;" : $"height: {ItemSize}px;";
string? _rowsDataSize = $"height: {ItemSize}px";

<FluentDataGridRow GridTemplateColumns=@GridTemplateColumns aria-rowindex="@(placeholderContext.Index + 1)" Style="@_rowsDataSize" TGridItem="TGridItem">
@for (var colIndex = 0; colIndex < _columns.Count; colIndex++)
Expand Down Expand Up @@ -161,4 +146,44 @@
</FluentDataGridCell>
}
}

private void RenderEmptyContent(RenderTreeBuilder __builder)
{
@if (_manualGrid)
{
return;
}
// If we use the Blazor components here the renderer gets upset/lost, so we use the web components directly
<fluent-data-grid-row class="empty-content-row">
<fluent-data-grid-cell class="empty-content-cell">
@if (EmptyContent is null)
{
@("No data to show!")
}
else
{
@EmptyContent
}
</fluent-data-grid-cell>
</fluent-data-grid-row>

}

private void RenderLoadingContent(RenderTreeBuilder __builder)
{
<FluentDataGridRow TGridItem="TGridItem" Class="loading-content-row">
<FluentDataGridCell Class="loading-content-cell">
@if (LoadingContent is null)
{
<FluentStack HorizontalGap="3">
<FluentProgressRing Width="24px" /> <div>Loading...</div>
</FluentStack>
}
else
{
@LoadingContent
}
</FluentDataGridCell>
</FluentDataGridRow>
}
}
30 changes: 21 additions & 9 deletions src/Core/Components/DataGrid/FluentDataGrid.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public partial class FluentDataGrid<TGridItem> : FluentComponentBase, IHandleEve
[Parameter] public PaginationState? Pagination { get; set; }

/// <summary>
/// Gets or sets a value indicating whether the component will not add itself to the tab queue.
/// Gets or sets a value indicating whether the component will not add itself to the tab queue.
/// Default is false.
/// </summary>
[Parameter]
Expand Down Expand Up @@ -120,12 +120,12 @@ public partial class FluentDataGrid<TGridItem> : FluentComponentBase, IHandleEve
public EventCallback<FluentDataGridCell<TGridItem>> OnCellFocus { get; set; }

/// <summary>
/// Optionally defines a class to be applied to a rendered row.
/// Optionally defines a class to be applied to a rendered row.
/// </summary>
[Parameter] public Func<TGridItem, string>? RowClass { get; set; }

/// <summary>
/// Optionally defines a style to be applied to a rendered row.
/// Optionally defines a style to be applied to a rendered row.
/// Do not use to dynamically update a row style after rendering as this will interfere with the script that use this attribute. Use <see cref="RowClass"/> instead.
/// </summary>
[Parameter] public Func<TGridItem, string>? RowStyle { get; set; }
Expand All @@ -135,7 +135,6 @@ public partial class FluentDataGrid<TGridItem> : FluentComponentBase, IHandleEve
/// </summary>
[Parameter] public RenderFragment? EmptyContent { get; set; }


/// <summary>
/// Gets or sets a value indicating whether the grid is in a loading data state.
/// </summary>
Expand All @@ -146,7 +145,6 @@ public partial class FluentDataGrid<TGridItem> : FluentComponentBase, IHandleEve
/// A default fragment is used if loading content is not specified.
/// </summary>
[Parameter] public RenderFragment? LoadingContent { get; set; }

[Inject] private IServiceProvider Services { get; set; } = default!;
[Inject] private IJSRuntime JSRuntime { get; set; } = default!;

Expand All @@ -172,13 +170,17 @@ public partial class FluentDataGrid<TGridItem> : FluentComponentBase, IHandleEve
private bool _checkColumnOptionsPosition;
private bool _manualGrid;

// The associated ES6 module, which uses document-level event listeners
private IJSObjectReference? Module;
private IJSObjectReference? _jsEventDisposable;
private IJSObjectReference? Module { get; set; }

// Caches of method->delegate conversions
private readonly RenderFragment _renderColumnHeaders;
private readonly RenderFragment _renderNonVirtualizedRows;

private readonly RenderFragment _renderEmptyContent;
private readonly RenderFragment _renderLoadingContent;

// We try to minimize the number of times we query the items provider, since queries may be expensive
// We only re-query when the developer calls RefreshDataAsync, or if we know something's changed, such
// as sort order, the pagination state, or the data source itself. These fields help us detect when
Expand All @@ -203,6 +205,8 @@ public FluentDataGrid()
_currentPageItemsChanged = new(EventCallback.Factory.Create<PaginationState>(this, RefreshDataCoreAsync));
_renderColumnHeaders = RenderColumnHeaders;
_renderNonVirtualizedRows = RenderNonVirtualizedRows;
_renderEmptyContent = RenderEmptyContent;
_renderLoadingContent = RenderLoadingContent;

// As a special case, we don't issue the first data load request until we've collected the initial set of columns
// This is so we can apply default sort order (or any future per-column options) before loading data
Expand Down Expand Up @@ -331,6 +335,7 @@ public async Task RefreshDataAsync()
public void SetLoadingState(bool loading)
{
Loading = loading;
StateHasChanged();
}

// Same as RefreshDataAsync, except without forcing a re-render. We use this from OnParametersSetAsync
Expand All @@ -339,7 +344,7 @@ private async Task RefreshDataCoreAsync()
{
// Move into a "loading" state, cancelling any earlier-but-still-pending load
_pendingDataLoadCancellationTokenSource?.Cancel();
CancellationTokenSource? thisLoadCts = _pendingDataLoadCancellationTokenSource = new CancellationTokenSource();
var thisLoadCts = _pendingDataLoadCancellationTokenSource = new CancellationTokenSource();

if (_virtualizeComponent is not null)
{
Expand All @@ -363,7 +368,7 @@ private async Task RefreshDataCoreAsync()
_ariaBodyRowCount = _currentNonVirtualizedViewItems.Count;
Pagination?.SetTotalItemCountAsync(result.TotalItemCount);
_pendingDataLoadCancellationTokenSource = null;
if (_ariaBodyRowCount > 0 ) Loading = false;
Loading = false;
}
_internalGridContext.ResetRowIndexes(startIndex);
}
Expand Down Expand Up @@ -408,7 +413,10 @@ private async Task RefreshDataCoreAsync()
_ariaBodyRowCount = Pagination is null ? providerResult.TotalItemCount : Pagination.ItemsPerPage;

Pagination?.SetTotalItemCountAsync(providerResult.TotalItemCount);
if (_ariaBodyRowCount > 0) Loading = false;
if (_ariaBodyRowCount > 0)
{
Loading = false;
}

// We're supplying the row _index along with each row's data because we need it for aria-rowindex, and we have to account for
// the virtualized start _index. It might be more performant just to have some _latestQueryRowStartIndex field, but we'd have
Expand Down Expand Up @@ -460,9 +468,13 @@ private string AriaSortValue(ColumnBase<TGridItem> column)
{
string? value = $"{Class} {(_pendingDataLoadCancellationTokenSource is null ? null : "loading")}".Trim();
if (string.IsNullOrEmpty(value))
{
return null;
}
else
{
return value;
}
}

private static string? ColumnClass(ColumnBase<TGridItem> column) => column.Align switch
Expand Down
11 changes: 7 additions & 4 deletions src/Core/Components/DataGrid/FluentDataGridRow.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,20 @@ public partial class FluentDataGridRow<TGridItem> : FluentComponentBase, IHandle
public int? RowIndex { get; set; }

/// <summary>
/// String that gets applied to the css gridTemplateColumns attribute for the row
/// Gets or sets the string that gets applied to the css gridTemplateColumns attribute for the row.
/// </summary>
[Parameter]
public string? GridTemplateColumns { get; set; } = null;

/// <summary>
/// Gets or sets the type of row. See <see cref="DataGridRowType"/>
/// Gets or sets the type of row. See <see cref="DataGridRowType"/>.
/// </summary>
[Parameter]
public DataGridRowType? RowType { get; set; } = DataGridRowType.Default;

[Parameter]
public VerticalAlignment VerticalAlignment { get; set; } = VerticalAlignment.Center;

/// <summary>
/// Gets or sets the content to be rendered inside the component.
/// </summary>
Expand Down Expand Up @@ -75,8 +78,8 @@ internal void Unregister(FluentDataGridCell<TGridItem> cell)

private async Task HandleOnCellFocus(DataGridCellFocusEventArgs args)
{
string? cellId = args.CellId;
if (cells.TryGetValue(cellId!, out FluentDataGridCell<TGridItem>? cell))
var cellId = args.CellId;
if (cells.TryGetValue(cellId!, out var cell))
{
await Owner.Grid.OnCellFocus.InvokeAsync(cell);
}
Expand Down

0 comments on commit 639ad8f

Please sign in to comment.