diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor
index 5228ed1d2b00..3d61a1e2990f 100644
--- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor
+++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/QuickGrid.razor
@@ -77,9 +77,11 @@
private void RenderPlaceholderRow(RenderTreeBuilder __builder, PlaceholderContext placeholderContext)
{
- @foreach (var col in _columns)
+ @foreach (var col in _columns)
{
- @{ col.RenderPlaceholderContent(__builder, placeholderContext); }
+ var hasCustomPlaceholder = col.PlaceholderTemplate is not null;
+ var placeholderClass = hasCustomPlaceholder ? "grid-cell-placeholder" : "grid-cell-placeholder default";
+ @{ col.RenderPlaceholderContent(__builder, placeholderContext); }
}
}
diff --git a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/Themes/Default.css b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/Themes/Default.css
index e11b358f9927..4b7313256ff8 100644
--- a/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/Themes/Default.css
+++ b/src/Components/QuickGrid/Microsoft.AspNetCore.Components.QuickGrid/src/Themes/Default.css
@@ -75,7 +75,7 @@
border-radius: 0.3rem;
}
-.quickgrid[theme=default] > tbody > tr > td.grid-cell-placeholder:after {
+.quickgrid[theme=default] > tbody > tr > td.grid-cell-placeholder.default:after {
content: '\2026';
opacity: 0.75;
}
diff --git a/src/Components/test/E2ETest/Tests/VirtualizationTest.cs b/src/Components/test/E2ETest/Tests/VirtualizationTest.cs
index cb1b221c117d..d45269677490 100644
--- a/src/Components/test/E2ETest/Tests/VirtualizationTest.cs
+++ b/src/Components/test/E2ETest/Tests/VirtualizationTest.cs
@@ -110,6 +110,39 @@ public void AlwaysFillsVisibleCapacity_Async()
int GetPlaceholderCount() => Browser.FindElements(By.Id("async-placeholder")).Count;
}
+ [Fact]
+ public void PlaceholdersHaveCorrectValue_Async()
+ {
+ var component = Browser.MountTestComponent();
+
+ var finishLoadingButton = Browser.Exists(By.Id("finish-loading-button"));
+ var startLoadingButton = Browser.Exists(By.Id("start-loading-button"));
+ //Load the initial data.
+ finishLoadingButton.Click();
+
+ Browser.True(() => GetItemCount() > 0);
+ Browser.Equal(0, () => GetPlaceholderCount());
+
+ //Start loading the second set of data to check for placeholders.
+ startLoadingButton.Click();
+ Browser.ExecuteJavaScript("const container = document.getElementById('async-container'); container.scrollTop = container.scrollHeight * 0.5;");
+
+ Browser.Equal(0, () => GetItemCount());
+ int placeholderCount = GetPlaceholderCount();
+ Browser.True(() => GetPlaceholderCount() > 0);
+
+ Assert.Equal("\"…\"", Browser.ExecuteJavaScript(@"
+ const p = document.querySelector('td.grid-cell-placeholder.default');
+ return p ? getComputedStyle(p, '::after').content : null;"));
+ Assert.Equal("none", Browser.ExecuteJavaScript(@"
+ const p = document.querySelector('td.grid-cell-placeholder:not(.default)');
+ return p ? getComputedStyle(p, '::after').content : null;"));
+ Browser.Equal("LOADING DATA", () => Browser.Exists(By.CssSelector(".grid-cell-placeholder .async-placeholder")).Text);
+
+ int GetItemCount() => Browser.FindElements(By.CssSelector("#async-container tbody td.async-id:not(.grid-cell-placeholder)")).Count;
+ int GetPlaceholderCount() => Browser.FindElements(By.CssSelector("#async-container tbody .async-id.grid-cell-placeholder")).Count;
+ }
+
[Fact]
public void RerendersWhenItemSizeShrinks_Sync()
{
diff --git a/src/Components/test/testassets/BasicTestApp/Index.razor b/src/Components/test/testassets/BasicTestApp/Index.razor
index 6e8d20b391a2..23262b501bd4 100644
--- a/src/Components/test/testassets/BasicTestApp/Index.razor
+++ b/src/Components/test/testassets/BasicTestApp/Index.razor
@@ -117,6 +117,7 @@
Virtualization MaxItemCount
Virtualization MaxItemCount (via AppContext)
Virtualization HTML table
+ Virtualization QuickGrid component
Render on hot reload
Sections test
Sections with Cascading parameters test
diff --git a/src/Components/test/testassets/BasicTestApp/VirtualizationQuickGrid.razor b/src/Components/test/testassets/BasicTestApp/VirtualizationQuickGrid.razor
new file mode 100644
index 000000000000..58e7fc1eb7e8
--- /dev/null
+++ b/src/Components/test/testassets/BasicTestApp/VirtualizationQuickGrid.razor
@@ -0,0 +1,82 @@
+@using Microsoft.AspNetCore.Components.QuickGrid
+
+
+@if (RendererInfo.IsInteractive)
+{
+ FinishLoading(200))">Finish loading
+ StartNewAsyncLoad())">Start new load
+
+
+
+
+
+
+
+
+
+ LOADING DATA
+
+
+
+
+
+
+
+}
+
+@code {
+ record DataItem(int Id, int SecondNum);
+ QuickGrid asyncGrid;
+
+ int asyncTotalItemCount = 200;
+ int asyncCancellationCount = 0;
+
+ TaskCompletionSource asyncTcs = new TaskCompletionSource();
+
+ private async ValueTask> GetItemsAsync(GridItemsProviderRequest request)
+ {
+ var loadingTask = asyncTcs.Task;
+ var registration = request.CancellationToken.Register(() => CancelLoading(request.CancellationToken));
+
+ try
+ {
+ await loadingTask.WaitAsync(request.CancellationToken);
+
+ var items = Enumerable.Range(request.StartIndex, request.Count ?? 200)
+ .Select(i => new DataItem(i, i * 2))
+ .ToArray();
+
+ return GridItemsProviderResult.From(items, asyncTotalItemCount);
+ }
+ catch (OperationCanceledException)
+ {
+ throw;
+ }
+ finally
+ {
+ registration.Dispose();
+ }
+ }
+
+
+ void StartNewAsyncLoad()
+ {
+ asyncTcs = new TaskCompletionSource();
+ StateHasChanged();
+ }
+
+ void FinishLoading(int totalItemCount)
+ {
+ asyncTotalItemCount = totalItemCount;
+ asyncTcs.SetResult();
+ StateHasChanged();
+ }
+
+ void CancelLoading(System.Threading.CancellationToken cancellationToken)
+ {
+ asyncTcs.TrySetCanceled(cancellationToken);
+ asyncTcs = new TaskCompletionSource();
+ asyncCancellationCount++;
+ StateHasChanged();
+ }
+}
diff --git a/src/Components/test/testassets/Components.TestServer/RazorComponents/ComplexValidationComponent.razor b/src/Components/test/testassets/Components.TestServer/RazorComponents/ComplexValidationComponent.razor
index 2e4f4f958a69..e1f611d8d81c 100644
--- a/src/Components/test/testassets/Components.TestServer/RazorComponents/ComplexValidationComponent.razor
+++ b/src/Components/test/testassets/Components.TestServer/RazorComponents/ComplexValidationComponent.razor
@@ -3,7 +3,7 @@
@using Microsoft.AspNetCore.Components.Forms
@if(RendererInfo.IsInteractive) {
-
+ 111
}
@if (_invalid)