Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,12 @@
If specified, grids render this fragment when there is no content.
</summary>
</member>
<member name="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.LoadingContent">
<summary>
Gets or sets the content to render when <see cref="P:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.Loading"/> is true.
A default fragment is used if loading content is not specified.
</summary>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1.#ctor">
<summary>
Constructs an instance of <see cref="T:Microsoft.FluentUI.AspNetCore.Components.FluentDataGrid`1"/>.
Expand Down Expand Up @@ -4148,7 +4154,7 @@
Called whenever the selection changed.
</summary>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentOption`1.OnSelectHandler">
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentOption`1.OnClickHandlerAsync">
<summary />
</member>
<member name="T:Microsoft.FluentUI.AspNetCore.Components.FluentPersona">
Expand Down Expand Up @@ -4407,9 +4413,6 @@
<member name="M:Microsoft.FluentUI.AspNetCore.Components.ListComponentBase`1.GetListOptions(System.Collections.Generic.IEnumerable{`0})">
<summary />
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.ListComponentBase`1.OnChangedHandlerAsync(Microsoft.AspNetCore.Components.ChangeEventArgs)">
<summary />
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.ListComponentBase`1.RemoveSelectedItem(`0)">
<summary />
</member>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
@inject NavigationManager NavManager

<div style="height: 434px; overflow:auto;" tabindex="-1">
<FluentDataGrid ItemsProvider="foodRecallProvider" Virtualize="true" ItemSize="46" GenerateHeader="GenerateHeaderOption.Sticky" TGridItem="FoodRecall" >
<FluentDataGrid Loading="true" ItemsProvider="foodRecallProvider" Virtualize="true" ItemSize="46" GenerateHeader="GenerateHeaderOption.Sticky" TGridItem="FoodRecall" >
<PropertyColumn Title="ID" Property="@(c => c!.Event_Id)" />
<PropertyColumn Property="@(c => c!.State)" Style="color:burlywood" />
<PropertyColumn Property="@(c => c!.City)" />
Expand Down Expand Up @@ -38,6 +38,9 @@
});

var response = await Http.GetFromJsonAsync<FoodRecallQueryResult>(url, req.CancellationToken);

// Simulate a slow data retrieval process
await Task.Delay(5500);
return GridItemsProviderResult.From(
items: response!.Results,
totalItemCount: response!.Meta.Results.Total);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@inject DataSource Data


<FluentDataGrid Items="@FilteredItems" ResizableColumns=true Pagination="@pagination" GridTemplateColumns="0.2fr 1fr 0.2fr 0.2fr 0.2fr 0.2fr" RowClass="@rowClass" RowStyle="@rowStyle" Style="height: 405px; overflow:auto;">
<FluentDataGrid Items="@FilteredItems" ResizableColumns=true Pagination="@pagination" GridTemplateColumns="0.2fr 1fr 0.2fr 0.2fr 0.2fr 0.2fr" RowClass="@rowClass" RowStyle="@rowStyle" Style="overflow:auto;">
<TemplateColumn Tooltip="true" TooltipText="@(c => "Flag of " + c.Name)" Title="Rank" SortBy="@rankSort" Align="Align.Center" InitialSortDirection="SortDirection.Ascending" IsDefaultSortColumn=true>
<img class="flag" src="_content/FluentUI.Demo.Shared/flags/@(context.Code).svg" alt="Flag of @(context.Code)" />
</TemplateColumn>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
<div style="height: 400px; overflow-y: scroll;">
<FluentDataGrid Items=@items Virtualize="true" ItemSize="54" GridTemplateColumns="1fr 1fr 1fr 1fr">
<FluentDataGrid @ref="grid" Items=@items Virtualize="true" ItemSize="54" GridTemplateColumns="1fr 1fr 1fr 1fr" Style="height: 100%;">
<ChildContent>
<PropertyColumn Property="@(c => c.Item1)" Sortable="true" />
<PropertyColumn Property="@(c => c.Item2)" />
<PropertyColumn Property="@(c => c.Item3)" Align="Align.Center" />
<PropertyColumn Property="@(c => c.Item4)" Align="Align.End" />
</ChildContent>
<EmptyContent>
<FluentIcon Value="@(new Icons.Filled.Size24.Crown())" Color="@Color.Accent"/>&nbsp; Nothing to see here. Carry on!
<FluentIcon Value="@(new Icons.Filled.Size24.Crown())" Color="@Color.Accent" />&nbsp; Nothing to see here. Carry on!
</EmptyContent>
<LoadingContent>
<FluentStack Orientation="Orientation.Vertical" HorizontalAlignment="HorizontalAlignment.Center">
Loading...<br />
<FluentProgress Width="240px" />
</FluentStack>
</LoadingContent>
</FluentDataGrid>
</div>
<br />
<FluentSwitch @bind-Value="@_clearItems"
@bind-Value:after="ToggleItems"
<FluentSwitch @bind-Value="@_clearItems"
@bind-Value:after="ToggleItems"
UncheckedMessage="Clear all results"
CheckedMessage="Restore all results">
</FluentSwitch>
<FluentButton OnClick="SimulateDataLoading">Simulate data loading</FluentButton>


@code {
FluentDataGrid<SampleGridData>? grid;

bool _clearItems = false;
public record SampleGridData(string Item1, string Item2, string Item3, string Item4);

Expand All @@ -43,12 +52,19 @@
private void ToggleItems()
{
if (_clearItems)
{
items = null;
}
else
{
items =GenerateSampleGridData(5000);;
}
{
items = null;
}
else
{
items = GenerateSampleGridData(5000);
}
}

private async Task SimulateDataLoading()
{
grid?.SetLoadingState(true);
await Task.Delay(2500);
grid?.SetLoadingState(false);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@page "/Autocomplete"

@using FluentUI.Demo.Shared.Pages.Autocomplete.Examples
@using FluentUI.Demo.Shared.Pages.List.Autocomplete.Examples

<h1>Autocomplete</h1>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@page "/Combobox"

@using FluentUI.Demo.Shared.Pages.Combobox.Examples;
@using FluentUI.Demo.Shared.Pages.List.Combobox.Examples;

<h1>Combobox</h1>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@page "/Listbox"

@using FluentUI.Demo.Shared.Pages.Listbox.Examples
@using FluentUI.Demo.Shared.Pages.List.Listbox.Examples

<h1>Listbox</h1>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@

List<Option<int>> intOptions = new()
{
{ new Option<int> { Value = 1, Text = 1, Disabled = true } },
{ new Option<int> { Value = 2, Text = 2 } },
{ new Option<int> { Value = 3, Text = 3 } }
{ new Option<int> { Value = 1, Text = 1, Disabled = true, Icon = (new Icons.Regular.Size24.NumberCircle1(), Color.Neutral, "start" ) } },
{ new Option<int> { Value = 2, Text = 2, Icon = (new Icons.Regular.Size24.NumberCircle2(), Color.Neutral, "start" ) } },
{ new Option<int> { Value = 3, Text = 3, Icon = (new Icons.Regular.Size24.NumberCircle3(), Color.Neutral, "start" ) } }

};
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@page "/Select"

@using FluentUI.Demo.Shared.Pages.Select.Examples
@using FluentUI.Demo.Shared.Pages.List.Select.Examples

<h1>Select</h1>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@using FluentUI.Demo.Shared.SampleData
@using FluentUI.Demo.Shared.Pages.Listbox.Examples;
@using FluentUI.Demo.Shared.Pages.List.Listbox.Examples;

<FluentTabs ShowClose="true"
@bind-ActiveTabId="@SelectedTabId"
Expand Down
56 changes: 38 additions & 18 deletions src/Core/Components/DataGrid/FluentDataGrid.razor
Original file line number Diff line number Diff line change
Expand Up @@ -37,38 +37,58 @@
</FluentDataGridRow>
}

@if (_ariaBodyRowCount == 0 && !_manualGrid)
@if (Loading)
{
<div class="empty-content-row" role="row">
<div class="empty-content-cell" role="gridcell">
@if (EmptyContent is null)
<FluentDataGridRow TGridItem="TGridItem" Class="loading-content-row">
<FluentDataGridCell Class="loading-content-cell">
@if (LoadingContent is null)
{
@("No data to show!")
;
<FluentStack HorizontalGap="3">
<FluentProgressRing Width="24px" /> <div>Loading...</div>
</FluentStack>
}
else
{
@EmptyContent
@LoadingContent
}
</div>
</div>
</FluentDataGridCell>
</FluentDataGridRow>
}
else
{
@if (Virtualize)
@if (_ariaBodyRowCount == 0 && !_manualGrid)
{
<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))" />
<FluentDataGridRow TGridItem="TGridItem" Class="empty-content-row">
<FluentDataGridCell Class="empty-content-cell">
@if (EmptyContent is null)
{
@("No data to show!")
}
else
{
@EmptyContent
}
</FluentDataGridCell>
</FluentDataGridRow>
}
else
{
@_renderNonVirtualizedRows
@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))" />
}
else
{
@_renderNonVirtualizedRows
}
}
}

@if (_manualGrid)
{
@ChildContent
Expand Down Expand Up @@ -109,7 +129,7 @@

private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext)
{
string? _rowsDataSize = $"height: {ItemSize}px";
string? _rowsDataSize = Loading ? "height: 100%;" : $"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
16 changes: 16 additions & 0 deletions src/Core/Components/DataGrid/FluentDataGrid.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@ public partial class FluentDataGrid<TGridItem> : FluentComponentBase, IHandleEve
/// </summary>
[Parameter] public RenderFragment? EmptyContent { get; set; }

[Parameter] public bool Loading { get; set; }

/// <summary>
/// Gets or sets the content to render when <see cref="Loading"/> is true.
/// 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 Down Expand Up @@ -317,6 +325,12 @@ public async Task RefreshDataAsync()
//StateHasChanged();
}

public void SetLoadingState(bool loading)
{
Loading = loading;
StateHasChanged();
}

// Same as RefreshDataAsync, except without forcing a re-render. We use this from OnParametersSetAsync
// because in that case there's going to be a re-render anyway.
private async Task RefreshDataCoreAsync()
Expand Down Expand Up @@ -347,6 +361,7 @@ private async Task RefreshDataCoreAsync()
_ariaBodyRowCount = _currentNonVirtualizedViewItems.Count;
Pagination?.SetTotalItemCountAsync(result.TotalItemCount);
_pendingDataLoadCancellationTokenSource = null;
Loading = false;
}
_internalGridContext.ResetRowIndexes(startIndex);
}
Expand Down Expand Up @@ -391,6 +406,7 @@ private async Task RefreshDataCoreAsync()
_ariaBodyRowCount = Pagination is null ? providerResult.TotalItemCount : Pagination.ItemsPerPage;

Pagination?.SetTotalItemCountAsync(providerResult.TotalItemCount);
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
18 changes: 8 additions & 10 deletions src/Core/Components/DataGrid/FluentDataGrid.razor.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ fluent-data-grid {
--col-gap: 1rem;
}

::deep .empty-content-row {
::deep .empty-content-row,
::deep .loading-content-row {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}

::deep .empty-content-cell {
display: flex;
justify-content: center;
align-items: center;
::deep .empty-content-cell,
::deep .loading-content-cell {

font-weight: 600;
}

Expand All @@ -30,7 +30,6 @@ fluent-data-grid {

[dir=rtl] .col-options {
left: unset;

}

.col-justify-end .col-options, .col-justify-right .col-options {
Expand Down Expand Up @@ -59,7 +58,6 @@ fluent-data-grid {
cursor: col-resize;
}

.col-width-draghandle:hover, .col-width-draghandle:active {
background: var(--neutral-stroke-divider-rest);
}

.col-width-draghandle:hover, .col-width-draghandle:active {
background: var(--neutral-stroke-divider-rest);
}
3 changes: 2 additions & 1 deletion src/Core/Components/DataGrid/FluentDataGridRow.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ public partial class FluentDataGridRow<TGridItem> : FluentComponentBase, IHandle
private InternalGridContext<TGridItem> Owner { get; set; } = default!;

protected string? StyleValue => new StyleBuilder(Style)
.AddStyle("height", $"{Owner.Grid.ItemSize}px", () => Owner.Grid.Virtualize && RowType == DataGridRowType.Default)
.AddStyle("height", $"{Owner.Grid.ItemSize}px", () => Owner.Grid.Virtualize && !Owner.Grid.Loading && RowType == DataGridRowType.Default)
.AddStyle("height", "100%", () => Owner.Grid.Loading && RowType == DataGridRowType.Default)
.AddStyle("align-items", "center", () => Owner.Grid.Virtualize && RowType == DataGridRowType.Default && string.IsNullOrEmpty(Style))
.Build();

Expand Down
Loading