Add new BitDataGrid component (#12502)#12504
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
Walkthrough
BitDataGrid buildout
BitQuickGrid extraction
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (18)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cs-12-13 (1)
12-13:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winDeterministic claim is broken by
DateTime.TodayLine 29 makes generated data drift day-to-day, so the “reproducible” promise in Line 12 is not true across dates.
Suggested fix
public static List<Product> Generate(int count, int seed = 42) { var rng = new Random(seed); + var baseDate = new DateTime(2024, 1, 1); var categories = Enum.GetValues<Category>(); var list = new List<Product>(count); @@ - ReleaseDate = DateTime.Today.AddDays(-rng.Next(0, 2000)), + ReleaseDate = baseDate.AddDays(-rng.Next(0, 2000)),Also applies to: 29-29
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cs` around lines 12 - 13, The Generate method in the SampleData class claims to be deterministic and reproducible in its summary, but it uses DateTime.Today on line 29 which changes daily and breaks the deterministic guarantee. Replace the DateTime.Today usage with a fixed, seed-based date value that remains consistent regardless of when the method is called. This ensures the data generation is truly reproducible and matches the claim in the method's XML summary comment.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs-223-225 (1)
223-225:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winExample 16 sample is missing the
OnCellDoubleClickhandlerLine 224 wires
OnCellDoubleClick, but the paired C# snippet (Lines 230-231) does not define it.Suggested fix
void OnCellClick(BitDataGridCellEventArgs<Product> e) { /* e.Item, e.ColumnTitle, e.Value */ } +void OnCellDoubleClick(BitDataGridCellEventArgs<Product> e) { /* ... */ } void OnCellContextMenu(BitDataGridCellEventArgs<Product> e) { /* e.Mouse.ClientX / e.Mouse.ClientY */ }Also applies to: 230-231
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs` around lines 223 - 225, The Razor component in Example 16 declares an OnCellDoubleClick event handler in the markup, but the corresponding C# method is missing from the code-behind. Add the OnCellDoubleClick handler method in the C# section of BitDataGridDemo.razor.samples.cs following the same pattern and signature as the existing OnCellClick and OnCellContextMenu handler methods. Ensure the method is defined in the appropriate location within the Example 16 sample code block so it matches the event binding in the markup.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs-148-163 (1)
148-163:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winHonor all sort descriptors in the read handlers.
Both handlers only apply
request.Sorts.FirstOrDefault(), so additional sort descriptors are ignored and multi-sort requests produce incorrect ordering.Suggested fix
- var sort = request.Sorts.FirstOrDefault(); - if (sort is not null) + IOrderedEnumerable<Product>? ordered = null; + foreach (var sort in request.Sorts) { Func<Product, object> key = sort.ColumnId switch { nameof(Product.Name) => p => p.Name, nameof(Product.Category) => p => p.Category, nameof(Product.Supplier) => p => p.Supplier, nameof(Product.Price) => p => p.Price, nameof(Product.Stock) => p => p.Stock, + nameof(Product.Rating) => p => p.Rating, _ => p => p.Id }; - query = sort.Direction == BitDataGridSortDirection.Descending - ? query.OrderByDescending(key) - : query.OrderBy(key); + ordered = ordered is null + ? (sort.Direction == BitDataGridSortDirection.Descending + ? query.OrderByDescending(key) + : query.OrderBy(key)) + : (sort.Direction == BitDataGridSortDirection.Descending + ? ordered.ThenByDescending(key) + : ordered.ThenBy(key)); } + if (ordered is not null) query = ordered;Also applies to: 182-198
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs` around lines 148 - 163, The current implementation only processes the first sort descriptor using request.Sorts.FirstOrDefault(), which causes multi-sort requests to be ignored. Replace the if statement that checks for a single sort with a loop that iterates through all items in request.Sorts collection. For each sort descriptor, apply the appropriate sort operation (OrderBy or OrderByDescending based on sort.Direction) to the query in sequence. The switch statement logic for mapping sort.ColumnId to the appropriate property key should remain the same, but needs to be executed for every sort descriptor in the collection rather than just the first one.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs-203-205 (1)
203-205:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winHandle empty final batches in infinite-scroll status text.
When no rows are returned, the current log renders an inverted range (
start > end), which is misleading.Suggested fix
- var end = request.Skip + batch.Count; - infiniteLog = $"Batch #{infiniteRequests} → loaded rows {request.Skip + 1}–{end} ({batch.Count} rows)"; + if (batch.Count == 0) + { + infiniteLog = $"Batch #{infiniteRequests} → no more rows to load."; + } + else + { + var end = request.Skip + batch.Count; + infiniteLog = $"Batch #{infiniteRequests} → loaded rows {request.Skip + 1}–{end} ({batch.Count} rows)"; + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs` around lines 203 - 205, The infiniteLog message construction does not handle the case when batch.Count is zero (empty final batch), resulting in a misleading inverted range display (e.g., "loaded rows 101–100"). Add a conditional check before assigning to infiniteLog to detect when batch.Count equals zero and either skip the log update entirely or provide an alternative status message that clearly indicates no additional rows were loaded, while preserving the current log message logic for non-empty batches.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cs-126-130 (1)
126-130:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winClear stale accessor when
Fieldis removed.Line 128 sets
Accessoronly whenHasFieldis true; ifFieldchanges from populated to null/empty, the previous accessor remains active.Proposed fix
protected override void OnParametersSet() { if (HasField) Accessor = BitDataGridPropertyAccessor<TItem>.For(Field!); + else + Accessor = null; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cs` around lines 126 - 130, In the OnParametersSet method of the BitDataGridColumn class, the Accessor is only set when HasField is true, but when Field is cleared or removed (HasField becomes false), the previous accessor remains active and is never cleared. Add an else clause after the if (HasField) condition that sets Accessor to null when HasField is false, ensuring stale accessors are properly cleaned up when the Field parameter changes from a value to null or empty.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss-8-8 (1)
8-8:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix Stylelint
value-keyword-caseviolation in font stack.Line 8 currently triggers lint errors; quote named font families so lint passes without changing fallback behavior.
Proposed fix
- --bit-dtg-font: 14px/1.4 system-ui, -apple-system, Segoe UI, Roboto, sans-serif; + --bit-dtg-font: 14px/1.4 system-ui, -apple-system, "Segoe UI", "Roboto", sans-serif;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss` at line 8, The font stack in the --bit-dtg-font custom property on line 8 of BitDataGrid.scss triggers a stylelint value-keyword-case violation because font family names are not properly quoted. Quote all font family names in the font stack (system-ui, -apple-system, Segoe UI, Roboto, and sans-serif) individually in the declaration to ensure stylelint compliance while maintaining the same fallback behavior.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cs-20-20 (1)
20-20:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
CancellationTokenis never populated by the grid.The
CancellationTokenproperty exists but is never set when constructingBitDataGridReadRequestinstances inLoadNextBatchAsyncorLoadServerDataAsync. Consumers will always receiveCancellationToken.None, making this property ineffective for request cancellation.Consider wiring a
CancellationTokenSourcethat cancels on component disposal or when a new request supersedes an in-flight one.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cs` at line 20, The CancellationToken property in BitDataGridReadRequest is declared but never initialized when instances are created in LoadNextBatchAsync and LoadServerDataAsync methods. To fix this, create a CancellationTokenSource field in the grid component and pass its Token property to the CancellationToken property when constructing each BitDataGridReadRequest instance. Additionally, dispose the previous CancellationTokenSource and create a new one for each request to handle superseding in-flight requests, and ensure the CancellationTokenSource is disposed when the component is disposed to properly clean up resources.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs-557-566 (1)
557-566:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winDead code:
|| truemakes!MultiSortineffective.Line 557's condition
(!MultiSort || true)always evaluates totrue, making the!MultiSortcheck dead code. Additionally, line 560 redundantly re-checks!additive.This appears to be leftover from refactoring. Simplify to the intended logic:
🧹 Proposed fix
- if (!additive && (!MultiSort || true)) - { - // Single sort: clear others unless additive - if (!additive) - { - var keep = existing; - _sorts.Clear(); - if (keep is not null) _sorts.Add(keep); - } - } + if (!additive) + { + // Single sort: clear others + var keep = existing; + _sorts.Clear(); + if (keep is not null) _sorts.Add(keep); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs` around lines 557 - 566, The condition in the BitDataGrid.razor.cs sort handling logic contains `|| true` on line 557, which makes the `!MultiSort` check ineffective and represents dead code. Additionally, the inner if statement on line 560 redundantly re-checks the `!additive` condition that was already evaluated in the outer if. To fix this, remove the `|| true` portion from the outer condition so it properly checks both `!additive && !MultiSort`, and remove the redundant inner `if (!additive)` block, moving its contents (the sort clearing logic) to directly execute within the outer if block since the condition already guarantees additive is false.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs-1087-1101 (1)
1087-1101:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winCSV export may throw if
GetFormattedValuereturns null.
GetFormattedValue(item)at line 1094 could potentially returnnull, and passingnulltoEscape()would cause aNullReferenceExceptionon the.Contains()call.🐛 Proposed fix
public string ToCsv() { var cols = VisibleColumns.Where(c => c.HasField).ToList(); var sb = new System.Text.StringBuilder(); sb.AppendLine(string.Join(",", cols.Select(c => Escape(c.DisplayTitle)))); var rows = IsServerMode ? _pageItems : _view; foreach (var item in rows) - sb.AppendLine(string.Join(",", cols.Select(c => Escape(c.GetFormattedValue(item))))); + sb.AppendLine(string.Join(",", cols.Select(c => Escape(c.GetFormattedValue(item) ?? "")))); return sb.ToString(); static string Escape(string v) - => v.Contains(',') || v.Contains('"') || v.Contains('\n') + => v is null ? "" : v.Contains(',') || v.Contains('"') || v.Contains('\n') ? "\"" + v.Replace("\"", "\"\"") + "\"" : v; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs` around lines 1087 - 1101, The ToCsv() method passes the return value of GetFormattedValue(item) directly to the Escape() helper function, but GetFormattedValue can return null, causing a NullReferenceException when Escape tries to call .Contains() on the null value. Fix this by adding null handling to the Escape() method—either at the start of the method by converting null to an empty string using the null coalescing operator, or by using the null coalescing operator when calling GetFormattedValue(item) in the Select expression to ensure Escape always receives a non-null string value.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs-74-84 (1)
74-84:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winReject empty/whitespace paths up front
For("")/For(" ")currently builds an accessor for the entire item object, which silently masks misconfigured columns and leads to incorrect sort/filter behavior.Suggested patch
public static BitDataGridPropertyAccessor<TItem> For(string path) - => Cache.GetOrAdd(path, Build); +{ + if (string.IsNullOrWhiteSpace(path)) + throw new ArgumentException("Property path cannot be null, empty, or whitespace.", nameof(path)); + + return Cache.GetOrAdd(path, Build); +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs` around lines 74 - 84, The For method does not validate the input path parameter before caching and building the accessor. Add validation at the start of the For method to check if the path is null, empty, or contains only whitespace characters. If the path is invalid, throw an appropriate exception to reject the invalid input and prevent the silent masking of misconfigured columns that currently occurs when an empty or whitespace-only path is passed to For.src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor-107-107 (1)
107-107:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix virtualized placeholder
aria-rowindexoffset.Line 107 should account for the header row. Non-virtual rows start at index 2 (Line 54), but placeholders currently start at 1, which misreports row positions to assistive tech.
Suggested fix
- <tr aria-rowindex="@(placeholderContext.Index + 1)"> + <tr aria-rowindex="@(placeholderContext.Index + 2)">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor` at line 107, The aria-rowindex attribute in the virtualized placeholder row template is not accounting for the header row offset. The placeholder row on line 107 uses placeholderContext.Index + 1, but it should use placeholderContext.Index + 2 to match the offset used in non-virtual rows (which start at index 2 to account for the header). Update the aria-rowindex expression to add 2 instead of 1 to ensure correct row position reporting to assistive technologies.src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss-4-5 (1)
4-5:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRemove
.scssextensions in new imports to satisfy Stylelint.Lines 4-5 currently violate
scss/load-partial-extension.Suggested fix
-@import "../Components/QuickGrid/BitQuickGrid.scss"; -@import "../Components/QuickGrid/Pagination/BitQuickGridPaginator.scss"; +@import "../Components/QuickGrid/BitQuickGrid"; +@import "../Components/QuickGrid/Pagination/BitQuickGridPaginator";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss` around lines 4 - 5, Remove the `.scss` file extensions from the `@import` statements on lines 4-5. Change the imports for BitQuickGrid.scss and BitQuickGridPaginator.scss to remove the `.scss` extension so they reference just the partial names without the extension, which satisfies the scss/load-partial-extension Stylelint rule that disallows explicit file extensions in SCSS imports.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs-129-134 (1)
129-134:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winTypo in XML documentation.
Line 131 has a typo: "A callback that supplies data for the rid" should be "A callback that supplies data for the grid".
📝 Proposed fix
/// <summary> - /// A callback that supplies data for the rid. + /// A callback that supplies data for the grid. /// /// You should supply either <see cref="Items"/> or <see cref="ItemsProvider"/>, but not both. /// </summary>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs` around lines 129 - 134, Fix the typo in the XML documentation comment for the ItemsProvider parameter where it currently states "A callback that supplies data for the rid" should be corrected to "A callback that supplies data for the grid". Locate the summary element in the XML comment block preceding the ItemsProvider property declaration and change the word "rid" to "grid" to accurately describe what the callback supplies data for.src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs-346-353 (1)
346-353:⚠️ Potential issue | 🟡 MinorAwait
SetTotalItemCountAsynccalls to ensure exceptions are not swallowed.
Pagination?.SetTotalItemCountAsync(result.TotalItemCount)is not awaited. The method can perform asynchronous work throughTotalItemCountChangedSubscribable.InvokeCallbacksAsync()orSetCurrentPageIndexAsync(), either of which may trigger component updates and can throw exceptions. Without awaiting, any exceptions from these async operations will be silently swallowed. The same pattern appears at line 392.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs` around lines 346 - 353, The SetTotalItemCountAsync method call on the Pagination object is not being awaited, which means any exceptions thrown by async operations within it (such as TotalItemCountChangedSubscribable.InvokeCallbacksAsync or SetCurrentPageIndexAsync) will be silently swallowed. Add the await keyword before the Pagination?.SetTotalItemCountAsync(result.TotalItemCount) call to properly handle exceptions. Apply the same fix to both occurrences of this pattern in the BitQuickGrid.razor.cs file.src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scss-15-16 (1)
15-16:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix transition declaration so the delay is applied.
At Line 15,
transition-delayis overridden by the shorthand on Line 16, so the delay never takes effect.💡 Suggested fix
- transition-delay: 25ms; - transition: opacity linear 100ms; + transition: opacity linear 100ms 25ms;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scss` around lines 15 - 16, The shorthand transition property on line 16 overrides the transition-delay specified on line 15, causing the delay to be lost. Combine both properties into a single shorthand transition declaration that includes the delay value as the fourth parameter: change the two separate lines to a single transition property that specifies opacity, linear, the 100ms duration, and the 25ms delay in the correct order.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cs-31-35 (1)
31-35:⚠️ Potential issue | 🟡 MinorUpdate XML documentation generic type references.
The class
BitQuickGridSort<TGridItem>has mismatched generic parameters in four methods' XML documentation. All instances use<see cref="BitQuickGridSort{T}"/>instead of<see cref="BitQuickGridSort{TGridItem}"/>, which will produce unresolved-cref warnings.Apply the following changes to all four methods:
Required fixes
- ByAscending method (lines 31, 35): Replace
BitQuickGridSort{T}withBitQuickGridSort{TGridItem}in both the summary and returns documentation.- ByDescending method (lines 41, 45): Replace
BitQuickGridSort{T}withBitQuickGridSort{TGridItem}in both the summary and returns documentation.- ThenAscending method (lines 51, 55): Replace
BitQuickGridSort{T}withBitQuickGridSort{TGridItem}in both the summary and returns documentation.- ThenDescending method (lines 68, 72): Replace
BitQuickGridSort{T}withBitQuickGridSort{TGridItem}in both the summary and returns documentation.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cs` around lines 31 - 35, In the BitQuickGridSort class, update the XML documentation for the four sorting methods (ByAscending, ByDescending, ThenAscending, and ThenDescending) to use the correct generic type parameter. Replace all instances of `BitQuickGridSort{T}` with `BitQuickGridSort{TGridItem}` in the see cref tags within both the summary and returns elements of each method's documentation to match the actual class generic parameter name and resolve cref warnings.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor-20-20 (1)
20-20:⚠️ Potential issue | 🟡 MinorAdd
Relattribute to protect thetarget="_blank"link.BitLink does not automatically apply
rel="noopener noreferrer"for external links. AddRel="BitLinkRels.NoOpener | BitLinkRels.NoReferrer"to prevent opener access:<BitLink Href="https://www.nuget.org/packages/Bit.BlazorUI.Extras" Target="_blank" Rel="BitLinkRels.NoOpener | BitLinkRels.NoReferrer">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor` at line 20, The BitLink component with Target="_blank" is missing the Rel attribute which is needed for security protection against opener access. Add the Rel attribute to the BitLink component (around line 20) with the value "BitLinkRels.NoOpener | BitLinkRels.NoReferrer" to properly secure the external link. This will prevent the opened page from accessing the window.opener object.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor-101-101 (1)
101-101:⚠️ Potential issue | 🟡 MinorUse distinct
@refvariables for the two product grids.At lines 101 and 116, both
BitQuickGridinstances share the same component reference@ref="productsDataGrid", causing the second grid to overwrite the first. TheODataSampleNameFilterproperty setter (in code-behind) refreshes only the last rendered grid instance, breaking the intended refresh behavior for the virtualized grid.Suggested fix
-<BitQuickGrid `@ref`="productsDataGrid" ItemsProvider="`@productsItemsProvider`" ItemKey="(p => p.Id)" TGridItem="ProductDto" Virtualize> +<BitQuickGrid `@ref`="odataProductsDataGrid" ItemsProvider="`@productsItemsProvider`" ItemKey="(p => p.Id)" TGridItem="ProductDto" Virtualize> -<BitQuickGrid `@ref`="productsDataGrid" ItemsProvider="`@productsItemsProvider`" ItemKey="(p => p.Id)" TGridItem="ProductDto" Pagination="pagination3"> +<BitQuickGrid `@ref`="loadingTemplateProductsDataGrid" ItemsProvider="`@productsItemsProvider`" ItemKey="(p => p.Id)" TGridItem="ProductDto" Pagination="pagination3">Also declare these fields in
BitQuickGridDemo.razor.csand update theODataSampleNameFiltersetter to refresh the correct grid reference.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor` at line 101, The two BitQuickGrid instances in the template are sharing the same `@ref` variable "productsDataGrid", causing the second grid to overwrite the first reference. Create distinct `@ref` variables for each BitQuickGrid component (one for the virtualized grid and one for the other grid), then declare corresponding fields in the BitQuickGridDemo.razor.cs code-behind file for each of these new references. Finally, update the ODataSampleNameFilter property setter to refresh the correct grid instance based on which grid should be updated when the filter changes.
🧹 Nitpick comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs (1)
447-462: 💤 Low valueConsider avoiding repeated
List<string>allocations.
GetRowClassandGetRowStyle(lines 447-479) allocate a newList<string>on every row render. For grids with many rows, this could add GC pressure. Consider using aStringBuilderor direct string concatenation since you're only combining at most two values.♻️ Possible simplification
private string? GetRowClass(TGridItem item) { - var classes = new List<string>(); - - if (RowClass is not null) - { - classes.Add(RowClass); - } - - if (RowClassSelector is not null) - { - classes.Add(RowClassSelector(item)); - } - - return classes.Any() ? string.Join(' ', classes) : null; + var baseClass = RowClass; + var selectorClass = RowClassSelector?.Invoke(item); + + return (baseClass, selectorClass) switch + { + (not null, not null) => $"{baseClass} {selectorClass}", + (not null, null) => baseClass, + (null, not null) => selectorClass, + _ => null + }; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs` around lines 447 - 462, The GetRowClass and GetRowStyle methods allocate a new List<string> on every row render, which creates unnecessary garbage collection pressure when rendering large grids. Replace the List<string> allocation and join pattern with direct string concatenation in both methods. Since you're combining at most two values in each method (RowClass and RowClassSelector for GetRowClass, and similarly for GetRowStyle), you can build the result string directly by checking the conditions and concatenating the values with a space separator only when both values exist, avoiding the List allocation entirely.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs`:
- Around line 448-475: In the LoadNextBatchAsync method, the OnLoadMore callback
invocation can throw an exception that causes the _infiniteLoading flag to
remain true, permanently blocking further loads. Wrap the entire logic starting
from the OnLoadMore call through the state updates in a try-finally block,
ensuring that _infiniteLoading is set to false and StateHasChanged is called in
the finally clause. This guarantees that _infiniteLoading will be reset even if
OnLoadMore throws an exception, allowing users to recover and retry loading more
data.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cs`:
- Around line 144-153: The Sum and Average aggregation calculations in the
BitDataGridDataProcessor class use double type for accumulating values, which
loses precision for decimal/currency columns. Replace the double sum variable
and the TryToDouble method calls with decimal-based logic to preserve numeric
precision. Ensure the accumulation and calculation logic in the Sum case (around
lines 147-152) uses decimal arithmetic throughout, and apply the same fix to the
related aggregation logic mentioned in lines 174-180 to maintain consistency
across all numeric aggregate operations.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs`:
- Around line 95-97: The compiled getter in BitDataGridPropertyAccessor for
nested property paths like Address.City is not null-safe. When an intermediate
property (like Address) is null, the expression throws an exception instead of
returning null. Modify the expression tree construction before creating the
Expression.Lambda to include null checks at each level of the property chain.
This should use Expression.Condition to test if each intermediate property
access is null and return null early if any level is null, allowing sorting and
filtering to handle partial object graphs gracefully without runtime failures.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cs`:
- Around line 7-10: The BitDataGridReadResult constructor accepts `items` and
`totalCount` parameters without validation, which allows null items and negative
totalCount values to pass through and corrupt the grid state. Add argument guard
clauses at the start of the BitDataGridReadResult constructor to validate that
items is not null and totalCount is greater than or equal to zero, throwing
appropriate ArgumentException or ArgumentNullException if validation fails,
ensuring invalid OnRead outputs fail immediately rather than causing downstream
paging issues.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.ts`:
- Line 47: The call to colOptions.scrollIntoViewIfNeeded() is using a
non-standard browser API that is not supported in Firefox and will cause runtime
errors. Replace this single method call with a check that first tests if the
method exists before calling it, and falls back to the standard scrollIntoView()
API if scrollIntoViewIfNeeded is not available. This ensures the column-options
interaction works across all browsers including Firefox.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor`:
- Around line 108-110: The icon-only buttons with class "bit-qkg-cob" that
trigger Grid.ShowColumnOptions(this) at lines 110 and 129 lack accessible names,
making them unannounced to assistive technologies. Add an aria-label attribute
to both button elements that provides a descriptive name for the column options
button (such as "Column options" or similar descriptive text). This ensures
screen readers will properly announce the button's purpose to users with
disabilities.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cs`:
- Around line 657-660: In the code where the OData filter string is constructed
using the query.Add method, the user input from _odataSampleNameFilter is being
directly interpolated without escaping, which creates an OData injection
vulnerability. To fix this, before interpolating _odataSampleNameFilter into the
filter string literal, escape any single quotes in the user input by replacing
each single quote character with two consecutive single quotes, as required by
the OData specification. This ensures that user input containing single quotes
like test' or '1'='1 will be treated as literal string data rather than being
able to break out of or modify the filter expression.
- Line 669: In the productsItemsProvider method at the GetFromJsonAsync call on
line 669, add the cancellation token parameter req.CancellationToken as the
third argument to match the pattern already established in the
foodRecallItemsProvider method. This will ensure the HTTP request can properly
respond to cancellation requests from the grid.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scss`:
- Line 12: The stylelint rule `selector-pseudo-element-no-unknown` flags
`::deep` pseudo-elements at lines 12, 62, 89, and 122 in the
BitQuickGridDemo.razor.scss file because `::deep` is a Blazor-specific
pseudo-element not part of standard CSS. Fix this by adding
`"selector-pseudo-element-no-unknown": null` to the rules section in
`.stylelintrc.json` to globally disable this rule (recommended approach), or
alternatively wrap each `::deep` block with stylelint disable and re-enable
comments (/* stylelint-disable-next-line selector-pseudo-element-no-unknown */
before and /* stylelint-enable */ after) if a file-local approach is preferred.
---
Minor comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs`:
- Around line 557-566: The condition in the BitDataGrid.razor.cs sort handling
logic contains `|| true` on line 557, which makes the `!MultiSort` check
ineffective and represents dead code. Additionally, the inner if statement on
line 560 redundantly re-checks the `!additive` condition that was already
evaluated in the outer if. To fix this, remove the `|| true` portion from the
outer condition so it properly checks both `!additive && !MultiSort`, and remove
the redundant inner `if (!additive)` block, moving its contents (the sort
clearing logic) to directly execute within the outer if block since the
condition already guarantees additive is false.
- Around line 1087-1101: The ToCsv() method passes the return value of
GetFormattedValue(item) directly to the Escape() helper function, but
GetFormattedValue can return null, causing a NullReferenceException when Escape
tries to call .Contains() on the null value. Fix this by adding null handling to
the Escape() method—either at the start of the method by converting null to an
empty string using the null coalescing operator, or by using the null coalescing
operator when calling GetFormattedValue(item) in the Select expression to ensure
Escape always receives a non-null string value.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss`:
- Line 8: The font stack in the --bit-dtg-font custom property on line 8 of
BitDataGrid.scss triggers a stylelint value-keyword-case violation because font
family names are not properly quoted. Quote all font family names in the font
stack (system-ui, -apple-system, Segoe UI, Roboto, and sans-serif) individually
in the declaration to ensure stylelint compliance while maintaining the same
fallback behavior.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cs`:
- Around line 126-130: In the OnParametersSet method of the BitDataGridColumn
class, the Accessor is only set when HasField is true, but when Field is cleared
or removed (HasField becomes false), the previous accessor remains active and is
never cleared. Add an else clause after the if (HasField) condition that sets
Accessor to null when HasField is false, ensuring stale accessors are properly
cleaned up when the Field parameter changes from a value to null or empty.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs`:
- Around line 74-84: The For method does not validate the input path parameter
before caching and building the accessor. Add validation at the start of the For
method to check if the path is null, empty, or contains only whitespace
characters. If the path is invalid, throw an appropriate exception to reject the
invalid input and prevent the silent masking of misconfigured columns that
currently occurs when an empty or whitespace-only path is passed to For.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cs`:
- Line 20: The CancellationToken property in BitDataGridReadRequest is declared
but never initialized when instances are created in LoadNextBatchAsync and
LoadServerDataAsync methods. To fix this, create a CancellationTokenSource field
in the grid component and pass its Token property to the CancellationToken
property when constructing each BitDataGridReadRequest instance. Additionally,
dispose the previous CancellationTokenSource and create a new one for each
request to handle superseding in-flight requests, and ensure the
CancellationTokenSource is disposed when the component is disposed to properly
clean up resources.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor`:
- Line 107: The aria-rowindex attribute in the virtualized placeholder row
template is not accounting for the header row offset. The placeholder row on
line 107 uses placeholderContext.Index + 1, but it should use
placeholderContext.Index + 2 to match the offset used in non-virtual rows (which
start at index 2 to account for the header). Update the aria-rowindex expression
to add 2 instead of 1 to ensure correct row position reporting to assistive
technologies.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs`:
- Around line 129-134: Fix the typo in the XML documentation comment for the
ItemsProvider parameter where it currently states "A callback that supplies data
for the rid" should be corrected to "A callback that supplies data for the
grid". Locate the summary element in the XML comment block preceding the
ItemsProvider property declaration and change the word "rid" to "grid" to
accurately describe what the callback supplies data for.
- Around line 346-353: The SetTotalItemCountAsync method call on the Pagination
object is not being awaited, which means any exceptions thrown by async
operations within it (such as
TotalItemCountChangedSubscribable.InvokeCallbacksAsync or
SetCurrentPageIndexAsync) will be silently swallowed. Add the await keyword
before the Pagination?.SetTotalItemCountAsync(result.TotalItemCount) call to
properly handle exceptions. Apply the same fix to both occurrences of this
pattern in the BitQuickGrid.razor.cs file.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scss`:
- Around line 15-16: The shorthand transition property on line 16 overrides the
transition-delay specified on line 15, causing the delay to be lost. Combine
both properties into a single shorthand transition declaration that includes the
delay value as the fourth parameter: change the two separate lines to a single
transition property that specifies opacity, linear, the 100ms duration, and the
25ms delay in the correct order.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cs`:
- Around line 31-35: In the BitQuickGridSort class, update the XML documentation
for the four sorting methods (ByAscending, ByDescending, ThenAscending, and
ThenDescending) to use the correct generic type parameter. Replace all instances
of `BitQuickGridSort{T}` with `BitQuickGridSort{TGridItem}` in the see cref tags
within both the summary and returns elements of each method's documentation to
match the actual class generic parameter name and resolve cref warnings.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Around line 4-5: Remove the `.scss` file extensions from the `@import`
statements on lines 4-5. Change the imports for BitQuickGrid.scss and
BitQuickGridPaginator.scss to remove the `.scss` extension so they reference
just the partial names without the extension, which satisfies the
scss/load-partial-extension Stylelint rule that disallows explicit file
extensions in SCSS imports.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs`:
- Around line 148-163: The current implementation only processes the first sort
descriptor using request.Sorts.FirstOrDefault(), which causes multi-sort
requests to be ignored. Replace the if statement that checks for a single sort
with a loop that iterates through all items in request.Sorts collection. For
each sort descriptor, apply the appropriate sort operation (OrderBy or
OrderByDescending based on sort.Direction) to the query in sequence. The switch
statement logic for mapping sort.ColumnId to the appropriate property key should
remain the same, but needs to be executed for every sort descriptor in the
collection rather than just the first one.
- Around line 203-205: The infiniteLog message construction does not handle the
case when batch.Count is zero (empty final batch), resulting in a misleading
inverted range display (e.g., "loaded rows 101–100"). Add a conditional check
before assigning to infiniteLog to detect when batch.Count equals zero and
either skip the log update entirely or provide an alternative status message
that clearly indicates no additional rows were loaded, while preserving the
current log message logic for non-empty batches.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs`:
- Around line 223-225: The Razor component in Example 16 declares an
OnCellDoubleClick event handler in the markup, but the corresponding C# method
is missing from the code-behind. Add the OnCellDoubleClick handler method in the
C# section of BitDataGridDemo.razor.samples.cs following the same pattern and
signature as the existing OnCellClick and OnCellContextMenu handler methods.
Ensure the method is defined in the appropriate location within the Example 16
sample code block so it matches the event binding in the markup.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cs`:
- Around line 12-13: The Generate method in the SampleData class claims to be
deterministic and reproducible in its summary, but it uses DateTime.Today on
line 29 which changes daily and breaks the deterministic guarantee. Replace the
DateTime.Today usage with a fixed, seed-based date value that remains consistent
regardless of when the method is called. This ensures the data generation is
truly reproducible and matches the claim in the method's XML summary comment.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor`:
- Line 20: The BitLink component with Target="_blank" is missing the Rel
attribute which is needed for security protection against opener access. Add the
Rel attribute to the BitLink component (around line 20) with the value
"BitLinkRels.NoOpener | BitLinkRels.NoReferrer" to properly secure the external
link. This will prevent the opened page from accessing the window.opener object.
- Line 101: The two BitQuickGrid instances in the template are sharing the same
`@ref` variable "productsDataGrid", causing the second grid to overwrite the first
reference. Create distinct `@ref` variables for each BitQuickGrid component (one
for the virtualized grid and one for the other grid), then declare corresponding
fields in the BitQuickGridDemo.razor.cs code-behind file for each of these new
references. Finally, update the ODataSampleNameFilter property setter to refresh
the correct grid instance based on which grid should be updated when the filter
changes.
---
Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs`:
- Around line 447-462: The GetRowClass and GetRowStyle methods allocate a new
List<string> on every row render, which creates unnecessary garbage collection
pressure when rendering large grids. Replace the List<string> allocation and
join pattern with direct string concatenation in both methods. Since you're
combining at most two values in each method (RowClass and RowClassSelector for
GetRowClass, and similarly for GetRowStyle), you can build the result string
directly by checking the conditions and concatenating the values with a space
separator only when both values exist, avoiding the List allocation entirely.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7038154f-12e2-424f-a8d9-7750b95219c1
📒 Files selected for processing (86)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (5)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 15
🧹 Nitpick comments (5)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss (1)
218-227: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winRespect reduced-motion user preference for spinner/shimmer animations.
The grid always animates loading indicators. Add a
prefers-reduced-motionfallback so motion-sensitive users are not forced into continuous animation.Suggested fix
`@keyframes` bit-dtg-spin { to { transform: rotate(360deg); } } @@ `@keyframes` bit-dtg-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } } + +@media (prefers-reduced-motion: reduce) { + .bit-dtg-spinner, + .bit-dtg-skeleton { + animation: none; + } +}Also applies to: 231-243
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss` around lines 218 - 227, The BitDataGrid spinner and shimmer animations do not respect user accessibility preferences for reduced motion. Wrap the animation properties in the `.bit-dtg-spinner` rule and the related animation rules (lines 231-243) in a `@media (prefers-reduced-motion: no-preference)` query so animations only play for users who have not requested reduced motion. For users with `prefers-reduced-motion: reduce`, provide fallback styles that disable the animation property, ensuring the spinner/shimmer elements remain visible but static.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor (2)
265-270: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winAdd
@keyto virtualized row for identity consistency.The infinite (line 246) and paged (line 275) render paths use
@key="item", but the virtualized path does not. Adding@keyensures consistent item identity tracking across all rendering modes, which helps Blazor optimize DOM updates when items are reordered or modified.♻️ Suggested fix
else if (UseVirtualization) { <Virtualize Items="VirtualRows" ItemSize="RowHeight" Context="item" TItem="TItem"> - <BitDataGridRow TItem="TItem" Grid="this" Item="item" /> + <BitDataGridRow TItem="TItem" Grid="this" Item="item" `@key`="item" /> </Virtualize> }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor` around lines 265 - 270, The virtualized rendering path in the UseVirtualization condition is missing the `@key` directive on the BitDataGridRow component, while the infinite and paged rendering paths both include `@key`="item". Add `@key`="item" to the BitDataGridRow component inside the Virtualize block to ensure consistent item identity tracking across all rendering modes and allow Blazor to properly optimize DOM updates when items are reordered or modified.
336-338: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winCache
VirtualRowsto avoid repeated list allocation.
VirtualRowscallsToList()on every access when_viewis not anICollection<TItem>. SinceVirtualizemay accessItemsmultiple times during rendering, this creates unnecessary allocations. Consider caching the list when the view changes instead of computing it on each access.♻️ Suggested approach
Add a cached field that is populated when
_viewchanges (e.g., inProcessClientDataorRefreshAsync):// In code-behind private ICollection<TItem>? _cachedVirtualRows; // Update when _view changes _cachedVirtualRows = _view as ICollection<TItem> ?? _view.ToList();Then in the Razor:
-private ICollection<TItem> VirtualRows => _view as ICollection<TItem> ?? _view.ToList(); +private ICollection<TItem> VirtualRows => _cachedVirtualRows ?? [];🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor` around lines 336 - 338, The VirtualRows property currently calls ToList() on every access when _view is not an ICollection<TItem>, causing repeated allocations during rendering cycles. Add a private cached field to store the computed virtual rows collection, then populate this cache whenever _view changes (such as in ProcessClientData or RefreshAsync methods). Update the VirtualRows property to return the cached field instead of computing the collection on each access, ensuring the cache remains synchronized whenever the underlying _view is modified.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs (1)
220-222: 🧹 Nitpick | 🔵 Trivial | 💤 Low valueConsider caching
VisibleColumnsto avoid repeated allocations.
VisibleColumnscreates a new list on every property access via.ToList(). This property is accessed frequently during rendering (inBitDataGridRow, keyboard navigation, column spanning, etc.). Consider caching the result and invalidating when columns change.♻️ Suggested caching pattern
+ private IReadOnlyList<BitDataGridColumn<TItem>>? _visibleColumnsCache; + private int _columnsVersion; - internal IReadOnlyList<BitDataGridColumn<TItem>> VisibleColumns => _columns.Where(c => c.Visible).ToList(); + internal IReadOnlyList<BitDataGridColumn<TItem>> VisibleColumns => _visibleColumnsCache ??= _columns.Where(c => c.Visible).ToList(); internal void AddColumn(BitDataGridColumn<TItem> column) { if (_columns.Contains(column)) return; _columns.Add(column); _columnsById[column.Id] = column; + _visibleColumnsCache = null; InvokeAsync(StateHasChanged); } internal void RemoveColumn(BitDataGridColumn<TItem> column) { if (_columns.Remove(column)) { _columnsById.Remove(column.Id); + _visibleColumnsCache = null; InvokeAsync(StateHasChanged); } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs` around lines 220 - 222, The VisibleColumns property in the BitDataGrid class creates a new list on every access via .ToList(), causing unnecessary allocations since this property is accessed frequently during rendering. Implement caching by creating a private backing field to store the visible columns list, update this cached list whenever the underlying _columns collection changes (add invalidation logic in methods that modify _columns such as column add/remove operations), and modify the VisibleColumns property to return the cached list instead of recomputing it with .Where().ToList() on each access. Ensure the cache is refreshed whenever columns are added, removed, or their visibility changes.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cs (1)
1-26: 🧹 Nitpick | 🔵 Trivial | 💤 Low valueEvent args exposes mutable
Columnreference; document stability assumption.The
Columnproperty holds a mutable reference toBitDataGridColumn<TItem>. While event args should ideally be immutable snapshots, this design is acceptable in the Blazor component context—columns are stable objects throughout the grid's lifetime. However, for future maintainers, consider adding an inline comment documenting this assumption so any refactoring (e.g., if columns become dynamically mutated) surfaces the design risk.Alternatively, if column mutability becomes a concern, capture immutable column metadata (Id, DisplayTitle) directly into the event args instead of the Column reference itself.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cs` around lines 1 - 26, The `Column` property in the `BitDataGridCellEventArgs<TItem>` class holds a mutable reference to a `BitDataGridColumn<TItem>` object, which violates the principle that event args should be immutable snapshots. Add an inline XML comment above the `Column` property that documents the design assumption that column objects remain stable throughout the grid's lifetime and warns future maintainers about the refactoring risk if columns become dynamically mutated. Alternatively, if mutable column objects become a concern, refactor the event args to capture only the immutable column metadata directly (such as `Id` and `DisplayTitle`) instead of holding a reference to the entire mutable Column object.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.ts`:
- Around line 10-33: The dispose method only removes the scroll event listener,
but the setTimeout on line 28 and requestAnimationFrame on line 22 can schedule
the check function to execute after disposal, causing the
dotNetRef.invokeMethodAsync call on line 15 to run on a disposed component and
trigger unhandled rejections. Add a disposed flag that is set to true in the
dispose function, then guard the check function to return early if disposed
before calling dotNetRef.invokeMethodAsync, ensuring no interop calls occur
after the component has been cleaned up.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cs`:
- Around line 87-90: The Path property in BitDataGridGroup is being constructed
using keyText, which is a formatted display value from
column.FormatValue(g.Key). This can cause path collisions when different keys
produce identical display values, leading to incorrect collapse/expand state
reuse. Change the path construction on line 89 to use the actual key value g.Key
instead of the formatted keyText when building the path identifier, while
keeping keyText available for display purposes elsewhere.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs`:
- Around line 115-124: The setter construction in the nested property handling
(around the Expression.Assign call in the setter creation block) does not
include null checks for intermediate properties in the chain, unlike the getter
which safely handles nulls. Add null-guard checks in the expression tree to
verify that intermediate properties are not null before attempting to assign to
nested properties. This should prevent SetValue from throwing exceptions when
intermediate nodes in the property path are null.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cs`:
- Around line 8-9: The Priority property in BitDataGridSortDescriptor class has
no default value, causing it to default to 0 in C#. Since the documentation
states "1 = primary" and the sorting logic uses ascending Priority values, a
default of 0 makes unset descriptors become higher priority than those
explicitly set to 1, contradicting the documented behavior. Assign a default
value to the Priority property (consider using int.MaxValue or another
appropriate high value) so that explicitly set priorities take precedence over
uninitialized descriptors and align with the documented sort precedence where 1
is primary.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs`:
- Around line 373-377: The count calculation on line 376 within the Pagination
null check in the BitQuickGrid class can produce negative values when
request.StartIndex exceeds the remaining items in the page window, which then
causes invalid negative arguments to be passed to Take() method calls downstream
around lines 416-419. Modify the count assignment to clamp the result to a
minimum of zero by wrapping the subtraction expression with Math.Max(0, ...) to
ensure count is never negative, preventing the negative Take argument issue.
- Around line 327-337: The `_pendingDataLoadCancellationTokenSource`
CancellationTokenSource instances are not being properly disposed, causing
resource leaks on frequent refreshes. When canceling the previous token source
at the start of the method and when setting the field to null (in both the
Virtualize branch and the other branch referenced at line 346-352), you must
explicitly dispose each replaced instance before assigning a new one or clearing
the field. Ensure that any old CancellationTokenSource is disposed immediately
after Cancel is called, and dispose the current instance before setting it to
null.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scss`:
- Around line 68-69: The border-inline-start property on line 69 uses a
hardcoded black color instead of the theme token variable used on line 68 for
border-color. Replace the hardcoded black value in the border-inline-start
property with the same theme variable (--bit-clr-brd-pri) to ensure the
resize-handle border color is consistent with the theme and follows the same
design token pattern.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.ts`:
- Around line 41-45: The transform style on colOptions is only set when overhang
exists in the if block, but when the popup is opened again without overhang, the
previous transform value persists and causes misalignment. Add an else clause
after the overhang check to explicitly clear the transform by setting
colOptions.style.transform to an empty string or "none" when neither
leftOverhang nor rightOverhang is true.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cs`:
- Line 36: The InvalidOperationException thrown in the
AsyncQueryExecutorSupplier class references a non-existent package
Microsoft.AspNetCore.Components.BitQuickGrid.EntityFrameworkAdapter and method
AddBitQuickGridEntityFrameworkAdapter that do not exist in the codebase. Update
the exception message to instead reference the actual correct approach using the
IAsyncQueryExecutor abstraction that is mentioned in the existing comments,
providing clear guidance on how developers should implement a custom query
executor to handle Entity Framework queries properly. Ensure the updated message
includes actionable steps or references to documentation so developers can
resolve the issue.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Around line 4-5: Remove the .scss file extensions from the two import
statements in the extra-components.scss file. The imports for BitQuickGrid and
BitQuickGridPaginator should reference the files without the .scss extension
(e.g., change `@import` "../Components/QuickGrid/BitQuickGrid.scss" to `@import`
"../Components/QuickGrid/BitQuickGrid"). This will comply with the
scss/load-partial-extension stylelint rule.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs`:
- Around line 331-344: The LoadData sample in the filtering and sorting sections
always applies operations to the Name property regardless of which column was
actually requested. Modify the filtering loop to check the field/column name
from the filter request (likely available as a property on the filter object)
and conditionally apply the Contains filter to the appropriate property (Name,
Id, or Price). Similarly, update the sorting section to check which column is
being sorted from the sort request object and apply OrderBy or OrderByDescending
to the correct property instead of always using Name.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor`:
- Around line 164-166: The BitButton component used for the row expand/collapse
toggle lacks an accessible label for assistive technologies. Add an
accessibility attribute (such as AriaLabel or Title) to the BitButton element
that contains the ChevronDown/ChevronRight icon. The label should clearly
describe the button's purpose, such as indicating whether it will expand or
collapse the row details, and should update dynamically based on the same
condition used to toggle the IconName property
(expandedRowTemplateCodes.Contains(context.Code)).
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cs`:
- Around line 68-69: The Description strings in the BitQuickGridDemo class
contain user-facing typos at multiple locations. On line 68, the word "rid"
should be corrected to "grid" in the description text. Additionally, fix any
other grammar or wording errors in the Description properties at lines 160 and
254. Review each Description string for clarity and ensure they are properly
formatted for documentation display purposes.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cs`:
- Around line 726-729: The OData filter query being constructed in the query.Add
call with the contains function is vulnerable to syntax errors when
_odataSampleNameFilter contains single quotes. Escape the user input value by
applying Replace("'", "''") to _odataSampleNameFilter before interpolating it
into the OData filter string. This will properly escape single quotes according
to OData standards and prevent filter syntax breakage.
- Line 738: The GetFromJsonAsync method calls in the sample code are missing the
cancellation token parameter. Add req.CancellationToken as a parameter to both
GetFromJsonAsync calls at lines 738 and 906 to ensure proper cancellation
propagation, making the sample code consistent with the runtime demo provider
implementation.
---
Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor`:
- Around line 265-270: The virtualized rendering path in the UseVirtualization
condition is missing the `@key` directive on the BitDataGridRow component, while
the infinite and paged rendering paths both include `@key`="item". Add `@key`="item"
to the BitDataGridRow component inside the Virtualize block to ensure consistent
item identity tracking across all rendering modes and allow Blazor to properly
optimize DOM updates when items are reordered or modified.
- Around line 336-338: The VirtualRows property currently calls ToList() on
every access when _view is not an ICollection<TItem>, causing repeated
allocations during rendering cycles. Add a private cached field to store the
computed virtual rows collection, then populate this cache whenever _view
changes (such as in ProcessClientData or RefreshAsync methods). Update the
VirtualRows property to return the cached field instead of computing the
collection on each access, ensuring the cache remains synchronized whenever the
underlying _view is modified.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs`:
- Around line 220-222: The VisibleColumns property in the BitDataGrid class
creates a new list on every access via .ToList(), causing unnecessary
allocations since this property is accessed frequently during rendering.
Implement caching by creating a private backing field to store the visible
columns list, update this cached list whenever the underlying _columns
collection changes (add invalidation logic in methods that modify _columns such
as column add/remove operations), and modify the VisibleColumns property to
return the cached list instead of recomputing it with .Where().ToList() on each
access. Ensure the cache is refreshed whenever columns are added, removed, or
their visibility changes.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss`:
- Around line 218-227: The BitDataGrid spinner and shimmer animations do not
respect user accessibility preferences for reduced motion. Wrap the animation
properties in the `.bit-dtg-spinner` rule and the related animation rules (lines
231-243) in a `@media (prefers-reduced-motion: no-preference)` query so
animations only play for users who have not requested reduced motion. For users
with `prefers-reduced-motion: reduce`, provide fallback styles that disable the
animation property, ensuring the spinner/shimmer elements remain visible but
static.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cs`:
- Around line 1-26: The `Column` property in the
`BitDataGridCellEventArgs<TItem>` class holds a mutable reference to a
`BitDataGridColumn<TItem>` object, which violates the principle that event args
should be immutable snapshots. Add an inline XML comment above the `Column`
property that documents the design assumption that column objects remain stable
throughout the grid's lifetime and warns future maintainers about the
refactoring risk if columns become dynamically mutated. Alternatively, if
mutable column objects become a concern, refactor the event args to capture only
the immutable column metadata directly (such as `Id` and `DisplayTitle`) instead
of holding a reference to the entire mutable Column object.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 908cae7a-5590-47b0-bff5-7de18c8d32e9
📒 Files selected for processing (86)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (6)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 11
♻️ Duplicate comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cs (1)
89-92:⚠️ Potential issue | 🟠 Major | ⚡ Quick winUse a typed, culture-invariant identity for group path keys.
Line 91 still relies on string interpolation of
g.Key, which can collide when distinct keys produce identical text and causes incorrect collapse/expand state reuse.Suggested fix
var keyText = column.FormatValue(g.Key); var items = g.ToList(); // Use the raw key (not the formatted display text) for the path identifier so that // distinct keys producing identical display values don't collide and share collapse/expand state. - var path = $"{parentPath}/{level}:{g.Key}"; + var keyIdentity = g.Key is null + ? "null" + : g.Key is IFormattable f + ? $"{g.Key.GetType().FullName}:{f.ToString(null, CultureInfo.InvariantCulture)}" + : $"{g.Key.GetType().FullName}:{g.Key}"; + var path = $"{parentPath}/{level}:{descriptor.ColumnId}:{keyIdentity}";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cs` around lines 89 - 92, In the BitDataGridDataProcessor.cs file where the path variable is constructed using string interpolation with g.Key, replace the simple string concatenation of g.Key with a typed, culture-invariant identifier that prevents collisions between distinct keys producing identical text. Instead of relying on the string representation of g.Key which can be culture-dependent and cause identical display values to collide, use a robust uniqueness mechanism such as the key's hash code or another unique type-safe identifier that preserves the actual key identity across different key instances.
🧹 Nitpick comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cs (1)
9-9: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winConsider making
FormattedValuerequired or nullable for consistency.The
FormattedValueproperty has a default value ofstring.Emptybut is not marked asrequired, whileColumnIdis required. This creates an inconsistent initialization pattern. IfFormattedValueis always expected to have a value, mark itrequired; if it's truly optional, consider making itstring?with anulldefault instead.♻️ Proposed options
Option 1: Make it required
- public string FormattedValue { get; init; } = string.Empty; + public required string FormattedValue { get; init; }Option 2: Make it nullable
- public string FormattedValue { get; init; } = string.Empty; + public string? FormattedValue { get; init; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cs` at line 9, The `FormattedValue` property in the `BitDataGridAggregateResult` class has a default value of `string.Empty` but is not marked as `required`, creating an inconsistency with the `ColumnId` property which is required. To fix this, either mark `FormattedValue` as `required` to match the pattern of `ColumnId`, or change its type to `string?` and set the default value to `null` to properly represent it as an optional nullable property. Choose the approach that best represents the semantic intent of this property in your data model.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cs (1)
25-25: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winInconsistent use of
requiredmodifier.The
ValueandMouseproperties are not marked asrequired, but based on the construction code inBitDataGrid.razor.cs:947, they are always explicitly set:new() { Item = item, Column = column, Value = column.GetValue(item), Mouse = e }This is inconsistent with
ItemandColumnbeing markedrequired. Either markValueandMouseasrequiredfor consistency and compile-time safety, or document why they are intentionally optional.♻️ Proposed fix for consistency
/// <summary>The raw value of the cell.</summary> - public object? Value { get; init; } + public required object? Value { get; init; } /// <summary>The underlying browser mouse event.</summary> - public MouseEventArgs Mouse { get; init; } = new(); + public required MouseEventArgs Mouse { get; init; }Also applies to: 28-28
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cs` at line 25, The BitDataGridCellEventArgs class has inconsistent use of the required modifier. The Value property at line 25 and Mouse property at line 28 are not marked as required, while Item and Column properties are. Since the construction code in BitDataGrid.razor.cs always explicitly sets all four properties when creating new instances, either add the required modifier to the Value and Mouse properties to match Item and Column for consistency and compile-time safety, or add documentation comments explaining why these two properties are intentionally optional despite always being set during construction.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs`:
- Around line 161-162: The _selected HashSet stores TItem references, but when
items are refreshed from server or through infinite scrolling, new object
instances are created with the same key value. Since reference equality fails
for these new instances, previously selected rows appear unselected and
select-all state becomes incorrect. Change the selection mechanism to track
items by their KeyField value instead of object reference. This means either
storing the key values in the _selected collection instead of TItem instances,
or implementing a custom equality comparer for TItem that compares based on the
KeyField value. Apply the same fix to _expandedDetails which has the same issue
at lines 227-230 and 697-715.
- Around line 458-478: The LoadNextBatchAsync method has a race condition where
older OnLoadMore responses can still mutate state after newer requests are
initiated, causing stale data. Implement a version-guard pattern by tracking the
current request version before calling OnLoadMore (similar to how
ResetLoadCancellation is used), then verify this version matches the current
state before applying the response mutations to _infiniteItems, _view,
_pageItems, and _footerAggregates. Apply the same version-guard pattern to both
the LoadNextBatchAsync method shown in the diff and the other similar location
mentioned in the comment (lines 543-557).
- Around line 1137-1139: The ReorderStickyStyle, DetailStickyStyle, and
SelectStickyStyle properties hardcode "left:" for positioning but should use
"right:" when the page is in RTL (right-to-left) mode. Modify each of these
three property definitions to conditionally output either "left:" or "right:"
based on the current RTL state, similar to how the FrozenStyle property handles
directional positioning. Check the BitDataGrid component for any existing RTL
detection logic or boolean flag you can use to determine when to use "right:"
instead of "left:".
- Around line 581-587: The condition on line 581 in the sort-clearing logic uses
`if (!additive && !MultiSort)` which requires both conditions to be true, but
this causes existing sorts to persist when MultiSort=true and a non-additive
click occurs (without Ctrl/Meta). The fix is to change the condition to only
check `if (!additive)` so that prior sorts are cleared whenever it is a
non-additive action, regardless of the MultiSort setting, making the behavior
consistent with Line 393 where additive mode is tied to Ctrl/Meta detection.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razor`:
- Around line 38-45: The column spanning logic in BitDataGridRow.razor skips
rendering columns when span is greater than 1, but the keyboard focus and
navigation model still operates using the full VisibleColumns index space,
creating a mismatch where focus targets can point to non-existent cells. Update
the focus/navigation model to map column indices to account for spanned columns,
ensuring that when columns are skipped due to spanning in the rendering loop
(where skip is decremented and columns are skipped), the corresponding focus
targets and tabindex assignments properly exclude those skipped column indices
so that keyboard focus always lands on a valid rendered BitDataGridCell with
tabindex=0.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs`:
- Around line 374-381: The Task.Delay(100) call in the debounce logic does not
respect the cancellation token, causing unnecessary delays even when virtualized
requests have already been canceled. Pass the request.CancellationToken as a
parameter to Task.Delay so the delay can be interrupted early if cancellation is
requested. Change Task.Delay(100) to Task.Delay(100, request.CancellationToken)
in the debounce section to make the delay cancellation-aware.
- Around line 324-366: In the RefreshDataCoreAsync method, wrap the call to
ResolveItemsRequestAsync(request) in a try-catch block to explicitly handle
OperationCanceledException. When this exception is caught, it indicates the load
was superseded by a newer request, so ensure the cleanup logic (checking if this
load is still current and disposing the cancellation token source) still
executes properly before allowing the method to complete gracefully without
propagating the exception. This prevents noisy failures during rapid sort/page
refreshes and keeps the load-state cleanup paths robust.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.ts`:
- Around line 83-87: The column resize logic does not enforce a minimum width
constraint on the nextWidth calculation, allowing columns to become negative or
excessively small during drag operations. Add a minimum width constraint by
clamping nextWidth to a reasonable minimum value (such as 20 or 30 pixels)
before assigning it to updatedColumnWidth and applying it to th.style.width.
This prevents column collapse and maintains layout stability during resizing
operations.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs`:
- Around line 139-196: The LoadServerData method updates serverLoading and
serverLastRequest at the end but does not trigger a final StateHasChanged call
to re-render the parent component. Since this is a callback function, these
state changes may render late or not at all. Wrap the lines that set
serverLoading to false and update serverLastRequest in a finally block, and add
an await InvokeAsync(StateHasChanged) call within that finally block to ensure
the parent component always re-renders after the data loading operation
completes.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cs`:
- Around line 384-386: The Razor snippet in the
BitQuickGridDemo.razor.samples.cs file binds to `virtualSampleNameFilter` in the
`@bind-Value` attribute of the BitSearchBox component, but the corresponding C#
property is defined as `VirtualSampleNameFilter` in PascalCase. Update the
binding to use `VirtualSampleNameFilter` to match the actual property name
defined in the C# code-behind, ensuring the sample compiles correctly when
copied.
- Around line 1090-1093: The BitButton component at lines 1090-1093 that
controls row expansion lacks accessibility attributes. Add a dynamic AriaLabel
or Title attribute to the BitButton element that changes based on the expansion
state. The label should indicate whether clicking the button will expand or
collapse the row, similar to the implementation in the runtime demo. Reference
the expandedRowTemplateCodes collection to conditionally set the label, matching
the same logic used for the IconName attribute selection.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cs`:
- Around line 89-92: In the BitDataGridDataProcessor.cs file where the path
variable is constructed using string interpolation with g.Key, replace the
simple string concatenation of g.Key with a typed, culture-invariant identifier
that prevents collisions between distinct keys producing identical text. Instead
of relying on the string representation of g.Key which can be culture-dependent
and cause identical display values to collide, use a robust uniqueness mechanism
such as the key's hash code or another unique type-safe identifier that
preserves the actual key identity across different key instances.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cs`:
- Line 9: The `FormattedValue` property in the `BitDataGridAggregateResult`
class has a default value of `string.Empty` but is not marked as `required`,
creating an inconsistency with the `ColumnId` property which is required. To fix
this, either mark `FormattedValue` as `required` to match the pattern of
`ColumnId`, or change its type to `string?` and set the default value to `null`
to properly represent it as an optional nullable property. Choose the approach
that best represents the semantic intent of this property in your data model.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cs`:
- Line 25: The BitDataGridCellEventArgs class has inconsistent use of the
required modifier. The Value property at line 25 and Mouse property at line 28
are not marked as required, while Item and Column properties are. Since the
construction code in BitDataGrid.razor.cs always explicitly sets all four
properties when creating new instances, either add the required modifier to the
Value and Mouse properties to match Item and Column for consistency and
compile-time safety, or add documentation comments explaining why these two
properties are intentionally optional despite always being set during
construction.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: e5869d38-2410-48a4-ad7d-364183e27bec
📒 Files selected for processing (86)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (6)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs (1)
324-346:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnsure CTS cleanup also runs for the virtualized branch.
thisLoadCtscleanup is currently only guaranteed in the non-virtualizedfinally. IfRefreshDataAsync()throws in the virtualized path,_pendingDataLoadCancellationTokenSourcecan stay non-null and undisposed.Suggested minimal restructuring
private async Task RefreshDataCoreAsync() { var previousCts = _pendingDataLoadCancellationTokenSource; if (previousCts is not null) { previousCts.Cancel(); previousCts.Dispose(); } var thisLoadCts = _pendingDataLoadCancellationTokenSource = new CancellationTokenSource(); - - if (_virtualizeComponent is not null) - { - await _virtualizeComponent.RefreshDataAsync(); - if (ReferenceEquals(_pendingDataLoadCancellationTokenSource, thisLoadCts)) - { - thisLoadCts.Dispose(); - _pendingDataLoadCancellationTokenSource = null; - } - } - else + try { - _lastRefreshedPaginationStateHash = Pagination?.GetHashCode(); - var startIndex = Pagination is null ? 0 : (Pagination.CurrentPageIndex * Pagination.ItemsPerPage); - var request = new BitQuickGridItemsProviderRequest<TGridItem>( - startIndex, Pagination?.ItemsPerPage, _sortByColumn, _sortByAscending, thisLoadCts.Token); - try + if (_virtualizeComponent is not null) { - var result = await ResolveItemsRequestAsync(request); - if (!thisLoadCts.IsCancellationRequested) - { - _currentNonVirtualizedViewItems = result.Items; - _ariaBodyRowCount = _currentNonVirtualizedViewItems.Count; - await (Pagination?.SetTotalItemCountAsync(result.TotalItemCount) ?? Task.CompletedTask); - } + await _virtualizeComponent.RefreshDataAsync(); } - catch (OperationCanceledException) + else { - // This load was superseded by a newer request; swallow the cancellation and fall through - // to the cleanup below so the load-state remains consistent. + _lastRefreshedPaginationStateHash = Pagination?.GetHashCode(); + var startIndex = Pagination is null ? 0 : (Pagination.CurrentPageIndex * Pagination.ItemsPerPage); + var request = new BitQuickGridItemsProviderRequest<TGridItem>( + startIndex, Pagination?.ItemsPerPage, _sortByColumn, _sortByAscending, thisLoadCts.Token); + var result = await ResolveItemsRequestAsync(request); + if (!thisLoadCts.IsCancellationRequested) + { + _currentNonVirtualizedViewItems = result.Items; + _ariaBodyRowCount = _currentNonVirtualizedViewItems.Count; + await (Pagination?.SetTotalItemCountAsync(result.TotalItemCount) ?? Task.CompletedTask); + } } - finally - { - if (ReferenceEquals(_pendingDataLoadCancellationTokenSource, thisLoadCts)) - { - thisLoadCts.Dispose(); - _pendingDataLoadCancellationTokenSource = null; - } - } + } + catch (OperationCanceledException) when (thisLoadCts.IsCancellationRequested) + { + // Superseded by a newer request. + } + finally + { + if (ReferenceEquals(_pendingDataLoadCancellationTokenSource, thisLoadCts)) + { + _pendingDataLoadCancellationTokenSource = null; + } + thisLoadCts.Dispose(); } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs` around lines 324 - 346, The RefreshDataCoreAsync method's virtualized branch does not guarantee cleanup of thisLoadCts if an exception is thrown during the RefreshDataAsync() call on the _virtualizeComponent. The cleanup logic that disposes thisLoadCts and clears _pendingDataLoadCancellationTokenSource (the ReferenceEquals check) should be wrapped in a try-finally block around the virtualized code path to ensure it always executes even when RefreshDataAsync() throws, preventing resource leaks and keeping _pendingDataLoadCancellationTokenSource properly managed.
🧹 Nitpick comments (7)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs (1)
323-364: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winReset
loadinginfinallyand honor cancellation in the server-read sample.This sample can leave
loading = trueif an exception/cancellation happens before Line 362. SinceBitDataGridReadRequestexposesCancellationToken, it should be used in the simulated async work as well.Suggested snippet adjustment
private async Task<BitDataGridReadResult<Product>> LoadData(BitDataGridReadRequest request) { - loading = true; - await Task.Delay(250); // simulate a backend round-trip - - IEnumerable<Product> query = all; - - // filtering - foreach (var f in request.Filters) - { - var term = f.Value?.ToString() ?? ""; - query = f.ColumnId switch - { - nameof(Product.Name) => query.Where(p => p.Name.Contains(term, StringComparison.OrdinalIgnoreCase)), - nameof(Product.Price) => query.Where(p => p.Price.ToString().Contains(term)), - nameof(Product.Id) => query.Where(p => p.Id.ToString().Contains(term)), - _ => query - }; - } - - // sorting - var sort = request.Sorts.FirstOrDefault(); - if (sort is not null) - { - Func<Product, object> key = sort.ColumnId switch - { - nameof(Product.Name) => p => p.Name, - nameof(Product.Price) => p => p.Price, - _ => p => p.Id - }; - query = sort.Direction == BitDataGridSortDirection.Descending - ? query.OrderByDescending(key) - : query.OrderBy(key); - } - - // paging - var filtered = query.ToList(); - var items = filtered.Skip(request.Skip).Take(request.Take ?? filtered.Count).ToList(); - - loading = false; - return new BitDataGridReadResult<Product>(items, filtered.Count); + loading = true; + try + { + await Task.Delay(250, request.CancellationToken); // simulate a backend round-trip + + IEnumerable<Product> query = all; + + // filtering + foreach (var f in request.Filters) + { + var term = f.Value?.ToString() ?? ""; + query = f.ColumnId switch + { + nameof(Product.Name) => query.Where(p => p.Name.Contains(term, StringComparison.OrdinalIgnoreCase)), + nameof(Product.Price) => query.Where(p => p.Price.ToString().Contains(term)), + nameof(Product.Id) => query.Where(p => p.Id.ToString().Contains(term)), + _ => query + }; + } + + // sorting + var sort = request.Sorts.FirstOrDefault(); + if (sort is not null) + { + Func<Product, object> key = sort.ColumnId switch + { + nameof(Product.Name) => p => p.Name, + nameof(Product.Price) => p => p.Price, + _ => p => p.Id + }; + query = sort.Direction == BitDataGridSortDirection.Descending + ? query.OrderByDescending(key) + : query.OrderBy(key); + } + + // paging + var filtered = query.ToList(); + var items = filtered.Skip(request.Skip).Take(request.Take ?? filtered.Count).ToList(); + return new BitDataGridReadResult<Product>(items, filtered.Count); + } + finally + { + loading = false; + } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs` around lines 323 - 364, The LoadData method sets loading to true but only resets it to false at the end of the method, leaving it stuck at true if an exception occurs. Additionally, the simulated async work via Task.Delay does not honor the CancellationToken from the BitDataGridReadRequest. Wrap the method body in a try-finally block and move the loading = false assignment to the finally block to ensure it always executes regardless of exceptions. Also, pass request.CancellationToken to the Task.Delay call to respect cancellation requests.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor (2)
403-403: 🧹 Nitpick | 🔵 Trivial | 💤 Low value
int.Parsecould throw on malformed select value.While the
<select>only contains valid integer options, usingint.Parsewithout validation is fragile. Considerint.TryParsefor defensive coding.♻️ Defensive parsing
-<select class="bit-dtg-page-size" `@onchange`="e => SetPageSizeAsync(int.Parse((string)e.Value!))"> +<select class="bit-dtg-page-size" `@onchange`="e => { if (int.TryParse((string?)e.Value, out var size)) _ = SetPageSizeAsync(size); }">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor` at line 403, The select element's `@onchange` handler in the page size dropdown uses int.Parse without error handling, which can throw exceptions if the value is malformed. Replace int.Parse((string)e.Value!) with int.TryParse to safely attempt the conversion and gracefully handle parsing failures. Check the result of TryParse before calling SetPageSizeAsync, and only proceed if the conversion succeeds.
27-31: 🧹 Nitpick | 🔵 Trivial | ⚖️ Poor tradeoffCSV data URI export may fail for large datasets.
The CSV export uses a
data:text/csvURI which has browser-specific length limits (typically 2MB in modern browsers, but varies). For grids with thousands of rows, this approach may silently truncate or fail.Consider adding a fallback using Blob URLs or JS interop for larger exports if this becomes an issue.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor` around lines 27 - 31, The CSV export functionality in the BitDataGrid component uses a data:text/csv URI approach which has browser limitations (typically 2MB) and may silently fail for large datasets. Modify the CSV export section to check the size of the CSV data generated by the ToCsv() method, and if it exceeds a reasonable threshold (around 1-2MB), implement a fallback approach using Blob URLs or JavaScript interop to trigger the download instead of using the data URI. This ensures large exports work reliably while maintaining backward compatibility for smaller datasets that work fine with the current data URI approach.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs (3)
226-226: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
VisibleColumnsallocates a new list on every access.The property
VisibleColumnscalls.ToList()on every access, creating a new allocation each time. It's accessed frequently (header rendering, cell navigation, spanning, footer, etc.), causing unnecessary GC pressure.♻️ Consider caching the visible columns list
+ private IReadOnlyList<BitDataGridColumn<TItem>>? _visibleColumnsCache; + private int _visibleColumnsVersion; + - internal IReadOnlyList<BitDataGridColumn<TItem>> VisibleColumns => _columns.Where(c => c.Visible).ToList(); + internal IReadOnlyList<BitDataGridColumn<TItem>> VisibleColumns + { + get + { + // Invalidate cache when columns change + if (_visibleColumnsCache is null || _visibleColumnsVersion != _columns.Count) + { + _visibleColumnsCache = _columns.Where(c => c.Visible).ToList(); + _visibleColumnsVersion = _columns.Count; + } + return _visibleColumnsCache; + } + }Also invalidate the cache in
AddColumn,RemoveColumn, andSetColumnVisibilityAsync.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs` at line 226, The VisibleColumns property creates a new list allocation on every access via .ToList(), causing unnecessary garbage collection. Cache the filtered list result in a private field (e.g., _visibleColumnsCache) and update the VisibleColumns property to return the cached value. Invalidate the cache by resetting it to null in the AddColumn, RemoveColumn, and SetColumnVisibilityAsync methods so the list is only recalculated when columns are actually modified, not on every property access.
734-735: 🧹 Nitpick | 🔵 Trivial | 💤 Low valueMultiple enumerations over
_pageItemsfor selection state.
AllPageSelectedandSomePageSelectedboth call_pageItems.Where(CanSelectRow)multiple times, causing repeated enumeration. Consider caching the selectable items.♻️ Suggested optimization
- internal bool AllPageSelected => _pageItems.Where(CanSelectRow).Any() && _pageItems.Where(CanSelectRow).All(_selected.Contains); - internal bool SomePageSelected => _pageItems.Where(CanSelectRow).Any(_selected.Contains) && !AllPageSelected; + internal bool AllPageSelected + { + get + { + var selectable = _pageItems.Where(CanSelectRow).ToList(); + return selectable.Count > 0 && selectable.All(_selected.Contains); + } + } + + internal bool SomePageSelected + { + get + { + var selectable = _pageItems.Where(CanSelectRow).ToList(); + return selectable.Any(_selected.Contains) && !selectable.All(_selected.Contains); + } + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs` around lines 734 - 735, The AllPageSelected and SomePageSelected properties both enumerate _pageItems.Where(CanSelectRow) multiple times within their respective expressions, causing inefficient repeated filtering. Refactor both properties by caching the filtered enumerable result (the result of _pageItems.Where(CanSelectRow)) into a local variable first, then use that cached variable in the subsequent checks with Any, All, and Contains operations to avoid multiple enumerations.
1068-1072: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick winUnnecessary list allocation in
ResolveColSpan.
cols.ToList().IndexOf(column)creates a temporary list just to find the index. Use a loop or LINQ instead.♻️ Suggested fix
internal int ResolveColSpan(BitDataGridColumn<TItem> column, TItem item) { if (column.ColSpan is null) return 1; var span = column.ColSpan(item) ?? 1; if (span < 1) span = 1; var cols = VisibleColumns; - var idx = cols.ToList().IndexOf(column); + var idx = -1; + for (int i = 0; i < cols.Count; i++) + { + if (cols[i] == column) { idx = i; break; } + } if (idx < 0) return 1; return Math.Min(span, cols.Count - idx); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs` around lines 1068 - 1072, The ResolveColSpan method is creating an unnecessary temporary list by calling cols.ToList() solely to use the IndexOf method for finding the column's position. Replace this inefficient approach by either using LINQ enumeration-based indexing without materialization, or iterating through the cols collection with a counter to find the index position directly, avoiding the allocation of the temporary list.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor (1)
24-31: 🧹 Nitpick | 🔵 Trivial | 💤 Low valueSelect element has redundant value binding.
The
<select>element has bothvalue="@(GetString())"and each<option>hasselected="@(name == GetString())". The Blazorvaluebinding on<select>should suffice; the explicitselectedattribute is redundant and can cause inconsistent behavior in some browsers.♻️ Suggested simplification
- <select class="bit-dtg-editor" value="@(GetString())" `@onchange`="e => Set(e.Value)"> + <select class="bit-dtg-editor" `@bind`="`@_enumValue`" `@bind`:event="onchange" `@bind`:after="() => Set(_enumValue)"> `@foreach` (var name in Enum.GetNames(Column.Accessor!.UnderlyingType)) { - <option value="`@name`" selected="@(name == GetString())">`@name`</option> + <option value="`@name`">`@name`</option> } </select>Or simply remove the
selectedattribute sincevalueon<select>handles selection:- <option value="`@name`" selected="@(name == GetString())">`@name`</option> + <option value="`@name`">`@name`</option>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor` around lines 24 - 31, The Enum case in the BitDataGridCellEditor.razor component has redundant selection binding on the select element. Remove the explicit selected="@(name == GetString())" attribute from each option element within the foreach loop, as the value binding on the parent select element with value="@(GetString())" already handles selecting the correct option in Blazor. Keep only the value binding on the select element for proper Blazor two-way binding behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.ts`:
- Around line 11-18: The invokeMethodAsync call in the check function lacks
error handling for promise rejections that may occur if the Blazor circuit
disconnects between the disposed flag check and the async method invocation. Add
a .catch() handler to the
dotNetRef.invokeMethodAsync('OnInfiniteScrollNearEndAsync') call to gracefully
handle potential promise rejections and prevent unhandled rejection errors in
the console during circuit disconnects or navigation.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cs`:
- Around line 201-219: The filter evaluation in the method has incorrect null
comparison semantics. The early return on line 201-202 when filter.Value is null
causes all rows to match, which is incorrect for Equals and NotEquals operators.
Additionally, when the row value itself is null, null values are passed to the
comparer which can cause incorrect matches for LessThan and LessThanOrEqual
operators. Remove the early return for null filter values, and instead add
proper null handling logic that checks if the row value is null separately
before calling BitDataGridValueComparer.Instance.Compare(). When the row value
is null, return false for comparison operators (GreaterThan, GreaterThanOrEqual,
LessThan, LessThanOrEqual) and handle Equals/NotEquals based on whether the
filter value is also null.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs`:
- Around line 89-90: The Split call in BitDataGridPropertyAccessor.cs uses
StringSplitOptions.RemoveEmptyEntries which silently normalizes malformed paths
like "." and "Address..City" instead of rejecting them. Remove the
RemoveEmptyEntries option from the Split call and add validation logic to check
if any segments are empty or whitespace, then throw an appropriate exception
(such as ArgumentException) if found, ensuring that only valid property paths
are processed and preventing silent misbinding in sort/filter/edit operations.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs`:
- Around line 411-414: The ProvideVirtualizedItems method calls
ResolveItemsRequestAsync which can throw OperationCanceledException when the
virtualized request is superseded by a newer request after debounce. Wrap the
ResolveItemsRequestAsync call in a try-catch block to explicitly catch and
handle OperationCanceledException so it does not propagate out of the
ProvideVirtualizedItems method. Handle the exception appropriately by returning
an empty or default result set that the virtualization system expects.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs`:
- Around line 215-231: The LoadMore method currently applies only the first sort
descriptor from request.Sorts by using FirstOrDefault(), which causes
multi-column sorts to be ignored. Replace the single sort application logic with
a loop that iterates through all items in request.Sorts (if any exist) and
applies each sort descriptor sequentially to the query. Reuse the key selector
switch statement that maps sort.ColumnId to the Product properties for each sort
descriptor, applying OrderByDescending or OrderBy based on each sort's Direction
property to maintain proper multi-sort ordering.
---
Duplicate comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs`:
- Around line 324-346: The RefreshDataCoreAsync method's virtualized branch does
not guarantee cleanup of thisLoadCts if an exception is thrown during the
RefreshDataAsync() call on the _virtualizeComponent. The cleanup logic that
disposes thisLoadCts and clears _pendingDataLoadCancellationTokenSource (the
ReferenceEquals check) should be wrapped in a try-finally block around the
virtualized code path to ensure it always executes even when RefreshDataAsync()
throws, preventing resource leaks and keeping
_pendingDataLoadCancellationTokenSource properly managed.
---
Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor`:
- Line 403: The select element's `@onchange` handler in the page size dropdown
uses int.Parse without error handling, which can throw exceptions if the value
is malformed. Replace int.Parse((string)e.Value!) with int.TryParse to safely
attempt the conversion and gracefully handle parsing failures. Check the result
of TryParse before calling SetPageSizeAsync, and only proceed if the conversion
succeeds.
- Around line 27-31: The CSV export functionality in the BitDataGrid component
uses a data:text/csv URI approach which has browser limitations (typically 2MB)
and may silently fail for large datasets. Modify the CSV export section to check
the size of the CSV data generated by the ToCsv() method, and if it exceeds a
reasonable threshold (around 1-2MB), implement a fallback approach using Blob
URLs or JavaScript interop to trigger the download instead of using the data
URI. This ensures large exports work reliably while maintaining backward
compatibility for smaller datasets that work fine with the current data URI
approach.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs`:
- Line 226: The VisibleColumns property creates a new list allocation on every
access via .ToList(), causing unnecessary garbage collection. Cache the filtered
list result in a private field (e.g., _visibleColumnsCache) and update the
VisibleColumns property to return the cached value. Invalidate the cache by
resetting it to null in the AddColumn, RemoveColumn, and
SetColumnVisibilityAsync methods so the list is only recalculated when columns
are actually modified, not on every property access.
- Around line 734-735: The AllPageSelected and SomePageSelected properties both
enumerate _pageItems.Where(CanSelectRow) multiple times within their respective
expressions, causing inefficient repeated filtering. Refactor both properties by
caching the filtered enumerable result (the result of
_pageItems.Where(CanSelectRow)) into a local variable first, then use that
cached variable in the subsequent checks with Any, All, and Contains operations
to avoid multiple enumerations.
- Around line 1068-1072: The ResolveColSpan method is creating an unnecessary
temporary list by calling cols.ToList() solely to use the IndexOf method for
finding the column's position. Replace this inefficient approach by either using
LINQ enumeration-based indexing without materialization, or iterating through
the cols collection with a counter to find the index position directly, avoiding
the allocation of the temporary list.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor`:
- Around line 24-31: The Enum case in the BitDataGridCellEditor.razor component
has redundant selection binding on the select element. Remove the explicit
selected="@(name == GetString())" attribute from each option element within the
foreach loop, as the value binding on the parent select element with
value="@(GetString())" already handles selecting the correct option in Blazor.
Keep only the value binding on the select element for proper Blazor two-way
binding behavior.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs`:
- Around line 323-364: The LoadData method sets loading to true but only resets
it to false at the end of the method, leaving it stuck at true if an exception
occurs. Additionally, the simulated async work via Task.Delay does not honor the
CancellationToken from the BitDataGridReadRequest. Wrap the method body in a
try-finally block and move the loading = false assignment to the finally block
to ensure it always executes regardless of exceptions. Also, pass
request.CancellationToken to the Task.Delay call to respect cancellation
requests.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 181acf5c-8519-490b-bb7d-03de1ca65181
📒 Files selected for processing (86)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (6)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (1)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cs (1)
13-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider extracting common generation logic to reduce duplication.
The
GenerateandGeneratePersianmethods duplicate the entire Product generation algorithm. Only the string arrays differ (adjectives, nouns, suppliers). Extracting the common logic into a shared helper would improve maintainability and ensure consistency when updating the generation algorithm.♻️ Refactoring approach
Extract a private helper that accepts the string arrays as parameters:
+ private static List<Product> GenerateCore( + int count, + int seed, + string[] adjectives, + string[] nouns, + string[] suppliers) + { + var rng = new Random(seed); + var categories = Enum.GetValues<Category>(); + var list = new List<Product>(count); + var referenceDate = new DateTime(2024, 1, 1); + for (int i = 1; i <= count; i++) + { + list.Add(new Product + { + Id = i, + Name = $"{adjectives[rng.Next(adjectives.Length)]} {nouns[rng.Next(nouns.Length)]} {rng.Next(100, 999)}", + Category = categories[rng.Next(categories.Length)], + Price = Math.Round((decimal)(rng.NextDouble() * 990 + 5), 2), + Stock = rng.Next(0, 500), + Rating = Math.Round(rng.NextDouble() * 4 + 1, 1), + Discontinued = rng.Next(0, 5) == 0, + ReleaseDate = referenceDate.AddDays(-rng.Next(0, 2000)), + Supplier = suppliers[rng.Next(suppliers.Length)] + }); + } + return list; + } + public static List<Product> Generate(int count, int seed = 42) - { - var rng = new Random(seed); - var categories = Enum.GetValues<Category>(); - var list = new List<Product>(count); - var referenceDate = new DateTime(2024, 1, 1); - for (int i = 1; i <= count; i++) - { - list.Add(new Product - { - Id = i, - Name = $"{Adjectives[rng.Next(Adjectives.Length)]} {Nouns[rng.Next(Nouns.Length)]} {rng.Next(100, 999)}", - Category = categories[rng.Next(categories.Length)], - Price = Math.Round((decimal)(rng.NextDouble() * 990 + 5), 2), - Stock = rng.Next(0, 500), - Rating = Math.Round(rng.NextDouble() * 4 + 1, 1), - Discontinued = rng.Next(0, 5) == 0, - ReleaseDate = referenceDate.AddDays(-rng.Next(0, 2000)), - Supplier = Suppliers[rng.Next(Suppliers.Length)] - }); - } - return list; - } + => GenerateCore(count, seed, Adjectives, Nouns, Suppliers); public static List<Product> GeneratePersian(int count, int seed = 42) - { - var rng = new Random(seed); - var categories = Enum.GetValues<Category>(); - var list = new List<Product>(count); - var referenceDate = new DateTime(2024, 1, 1); - for (int i = 1; i <= count; i++) - { - list.Add(new Product - { - Id = i, - Name = $"{PersianAdjectives[rng.Next(PersianAdjectives.Length)]} {PersianNouns[rng.Next(PersianNouns.Length)]} {rng.Next(100, 999)}", - Category = categories[rng.Next(categories.Length)], - Price = Math.Round((decimal)(rng.NextDouble() * 990 + 5), 2), - Stock = rng.Next(0, 500), - Rating = Math.Round(rng.NextDouble() * 4 + 1, 1), - Discontinued = rng.Next(0, 5) == 0, - ReleaseDate = referenceDate.AddDays(-rng.Next(0, 2000)), - Supplier = PersianSuppliers[rng.Next(PersianSuppliers.Length)] - }); - } - return list; - } + => GenerateCore(count, seed, PersianAdjectives, PersianNouns, PersianSuppliers);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cs` around lines 13 - 68, The Generate and GeneratePersian methods contain duplicate code for the entire Product generation algorithm, differing only in which string arrays they use. Create a private helper method that accepts three string array parameters (for adjectives, nouns, and suppliers) and contains the common generation logic currently duplicated in both methods. Then refactor the Generate method to call this helper with Adjectives, Nouns, and Suppliers arrays, and the GeneratePersian method to call it with PersianAdjectives, PersianNouns, and PersianSuppliers arrays. This will eliminate duplication while maintaining the same external behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs`:
- Around line 456-498: The LoadNextBatchAsync method awaits the OnLoadMore
callback which receives a cancellation token from ResetLoadCancellation(). If
the provider honors the cancellation token, it will throw an
OperationCanceledException that breaks the component flow. Wrap the await
statement for OnLoadMore in a try-catch block to catch
OperationCanceledException and handle it gracefully by returning early, since
cancellation is expected behavior when requests are superseded by newer loads.
This same fix should also be applied to any other similar load methods mentioned
in the "Also applies to" section that use ResetLoadCancellation() tokens.
- Around line 1199-1212: The Escape static method within the ToCsv() method
currently only handles CSV delimiter escaping but does not prevent formula
injection. When cell values begin with =, +, -, or @, spreadsheet applications
can interpret them as formulas when the CSV file is opened. Modify the Escape
static method to detect if the input value starts with any of these dangerous
characters and prepend a single quote to prevent formula execution, in addition
to the existing CSV delimiter escaping logic.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razor`:
- Line 13: The `@onkeydown`="HandleKeyDown" binding at line 13 does not prevent
the default browser keyboard behavior, which can conflict with the grid
navigation logic implemented in the HandleKeyDown method (referenced around line
70). Modify the onkeydown event binding to include preventDefault:true parameter
to suppress native browser key handling and ensure the custom grid navigation
logic executes exclusively without browser defaults interfering with the
cell-navigation behavior.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor`:
- Around line 24-27: The enum editor case in BitDataGridCellEditor.razor does
not validate that Column.Accessor exists and that its UnderlyingType is actually
an enum before attempting to call Enum.GetNames on it. Add a guard condition
before the select element that checks whether Column.Accessor is not null and
whether Column.Accessor.UnderlyingType is a valid enum type using Type.IsEnum.
If the guard condition fails, render a fallback editor instead of the enum
select dropdown to prevent null reference exceptions and invalid type operations
at runtime.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs`:
- Around line 36-40: The ConvertValue method (referenced around lines 68-70) is
silently coercing conversion failures to default values for non-nullable
properties, which causes invalid user input to be silently overwritten with
defaults like 0. Instead of silently returning default(T) on conversion failure,
modify ConvertValue to throw an exception or return a result that indicates
conversion failure, then update the SetValue method to handle this exception or
failure result appropriately by either not setting the value or propagating the
error to the caller so users are aware their invalid input was rejected rather
than silently converted.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs`:
- Around line 302-306: The call to _js.BitQuickGridCheckColumnOptionsPosition on
line 305 discards the returned ValueTask using the discard pattern instead of
awaiting it. Since the containing method is already async, replace the line that
discards the result with `await
_js.BitQuickGridCheckColumnOptionsPosition(_tableReference);` to properly await
the interop call and ensure positioning errors are not hidden.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor`:
- Around line 156-161: The Math.Round(p.Rating) call on line 160 uses banker's
rounding (midpoint-to-even), which causes inconsistent star rendering when the
rating is exactly at a midpoint value like 4.5. To fix this, replace
Math.Round(p.Rating) with Math.Round(p.Rating, MidpointRounding.AwayFromZero) to
ensure values round away from zero, providing more intuitive and consistent
visual feedback in the star rating display within the span element.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs`:
- Around line 139-144: The LoadServerData method and other async loader methods
do not honor the CancellationToken provided in BitDataGridReadRequest, allowing
superseded requests to complete and update stale UI state. Pass
request.CancellationToken to the Task.Delay() calls, and check for cancellation
(using ThrowIfCancellationRequested or similar checks) before updating UI state
variables like serverLoading, serverLastRequest, and infiniteLog to prevent
stale data from being written when a newer request supersedes the current one.
Apply this fix to all async loader methods mentioned, including LoadServerData
and any other similar loaders at the specified locations.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs`:
- Around line 346-358: The sort logic in this sample applies only the first sort
descriptor using FirstOrDefault() and ignores all additional sorts. Instead of
handling only a single sort, iterate through all items in request.Sorts and
chain the sort operations using OrderBy/OrderByDescending for the first sort and
ThenBy/ThenByDescending for subsequent sorts based on their respective column
IDs and directions. Apply this same complete sorting logic to both the initial
query sorting section (around the switch statement with Product.Name,
Product.Price cases) and the LoadMore method (lines 382-386) which currently
ignores request.Sorts entirely, ensuring consistent sort semantics are applied
in both code paths.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cs`:
- Around line 629-630: The controller route definitions at lines 629, 736, 810,
and 904 use the attribute Route with pattern "[controller]/[action]" but the
client sample code expects routes prefixed with "api/". Update the Route
attribute in all four controller definitions (ProductsController and other
similar controllers) to include the "api/" prefix in the route pattern, changing
"[controller]/[action]" to "api/[controller]/[action]" to ensure consistency
between the server-side sample and the client-side usage.
---
Nitpick comments:
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cs`:
- Around line 13-68: The Generate and GeneratePersian methods contain duplicate
code for the entire Product generation algorithm, differing only in which string
arrays they use. Create a private helper method that accepts three string array
parameters (for adjectives, nouns, and suppliers) and contains the common
generation logic currently duplicated in both methods. Then refactor the
Generate method to call this helper with Adjectives, Nouns, and Suppliers
arrays, and the GeneratePersian method to call it with PersianAdjectives,
PersianNouns, and PersianSuppliers arrays. This will eliminate duplication while
maintaining the same external behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: ca5f25fb-53db-4b03-bab4-dc6a2e8df316
📒 Files selected for processing (86)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (6)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 7
♻️ Duplicate comments (2)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs (1)
141-147: 🩺 Stability & Availability | 🟠 MajorMove the cancellable delay inside
tryso cleanup always remains in scope.At Line 143,
await Task.Delay(250, request.CancellationToken)can throw before thetryblock at Line 146, causing thefinallycleanup (Lines 198–209) to be bypassed and leavingserverLoadingin an inconsistent state.Proposed fix
private async Task<BitDataGridReadResult<Product>> LoadServerData(BitDataGridReadRequest request) { serverLoading = true; await InvokeAsync(StateHasChanged); - await Task.Delay(250, request.CancellationToken); int total = 0; try { + await Task.Delay(250, request.CancellationToken); + IEnumerable<Product> query = serverAll;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs` around lines 141 - 147, The cancellable Task.Delay on line 143 can throw a cancellation exception before entering the try block that starts on line 146, which causes the finally cleanup block to be bypassed and leaves serverLoading in an inconsistent state. Move the await Task.Delay(250, request.CancellationToken) statement inside the try block so that the finally cleanup block (lines 198-209) will always execute regardless of whether the delay is cancelled, ensuring serverLoading is properly reset.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs (1)
1226-1235: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winQuote CSV fields containing carriage returns.
Line 1233 quotes
\nbut not\r, so CR-only values can split rows in spreadsheet parsers. Include\rin the quoting condition.Suggested fix
- return v.Contains(',') || v.Contains('"') || v.Contains('\n') + return v.Contains(',') || v.Contains('"') || v.Contains('\n') || v.Contains('\r') ? "\"" + v.Replace("\"", "\"\"") + "\"" : v;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs` around lines 1226 - 1235, The Escape method checks for newline characters (\n) when deciding whether to quote CSV fields, but it does not include carriage return characters (\r) in the quoting condition. Update the return statement in the Escape method to also check for \r using an additional .Contains('\r') condition alongside the existing checks for comma, double quote, and newline, so that fields containing carriage returns are properly quoted to prevent row splitting in spreadsheet parsers.
🧹 Nitpick comments (3)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cs (1)
4-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd XML documentation to properties.
All properties lack documentation summaries, reducing IntelliSense discoverability.
📝 Proposed XML documentation additions
public sealed class BitDataGridFilterDescriptor { + /// <summary>Identifier of the column being filtered.</summary> public required string ColumnId { get; init; } + /// <summary>The filter operation to apply (e.g., Contains, Equals, GreaterThan).</summary> public BitDataGridFilterOperator Operator { get; set; } = BitDataGridFilterOperator.Contains; + /// <summary>The filter value to compare against, or null for operators like IsNull.</summary> public object? Value { get; set; } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cs` around lines 4 - 9, The BitDataGridFilterDescriptor class properties (ColumnId, Operator, and Value) lack XML documentation comments, which prevents IntelliSense from displaying helpful information for developers using these properties. Add XML documentation summary comments above each property using the standard /// <summary> syntax to describe what each property represents and its purpose in the filter descriptor context.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cs (1)
4-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd XML documentation to properties for IntelliSense clarity.
All properties lack individual doc summaries. Even simple DTOs benefit from documentation that appears in IDE tooltips and API docs.
📝 Proposed XML documentation additions
public sealed class BitDataGridAggregateResult { + /// <summary>Identifier of the column this aggregate result applies to.</summary> public required string ColumnId { get; init; } + /// <summary>The type of aggregate function applied (sum, average, count, etc.).</summary> public BitDataGridAggregateType Type { get; init; } + /// <summary>The raw computed aggregate value, or null if computation produced no result.</summary> public object? Value { get; init; } + /// <summary>The formatted string representation of the aggregate value for display.</summary> public required string FormattedValue { get; init; } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cs` around lines 4 - 10, The BitDataGridAggregateResult class and its properties are missing XML documentation comments that would provide IntelliSense clarity in IDEs and API documentation. Add XML documentation comments above each property (ColumnId, Type, Value, and FormattedValue) in the BitDataGridAggregateResult class using the summary tags to describe what each property represents, its purpose, and any relevant details about its usage or constraints.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cs (1)
10-26: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd XML documentation to undocumented properties for better IntelliSense discoverability.
Properties
ColumnId,KeyText,Aggregates, and the computed propertyHasSubGroupslack XML documentation summaries, which reduces discoverability in IntelliSense and impacts documentation generation. Lines 14 and 30 demonstrate the pattern already in use.📝 Proposed XML documentation additions
public sealed class BitDataGridGroup<TItem> { + /// <summary>Identifier of the column used for grouping.</summary> public required string ColumnId { get; init; } + /// <summary>The grouping key value for this group.</summary> public required object? Key { get; init; } + /// <summary>Human-readable text representation of the grouping key.</summary> public string KeyText { get; init; } = string.Empty; /// <summary>Zero-based nesting depth (0 = top level).</summary> public int Level { get; init; } /// <summary>Stable, unique path identifying this group across the whole tree (used for collapse state).</summary> public required string Path { get; init; } /// <summary>All rows that fall under this group (across nested subgroups).</summary> public List<TItem> Items { get; init; } = new(); /// <summary>Child groups when this group is further grouped; empty for leaf groups.</summary> public List<BitDataGridGroup<TItem>> SubGroups { get; init; } = new(); + /// <summary>Computed aggregates (e.g., sum, average) for columns in this group.</summary> public List<BitDataGridAggregateResult> Aggregates { get; init; } = new(); + /// <summary>Indicates whether this group contains child groups (subgroups).</summary> public bool HasSubGroups => SubGroups.Count > 0;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cs` around lines 10 - 26, The properties ColumnId, KeyText, and Aggregates in the BitDataGridGroup class are missing XML documentation summaries, which reduces IntelliSense discoverability. Add XML documentation comments above each of these properties following the same pattern already used for Level, Path, Items, and SubGroups properties. Each summary should provide a brief description of what the property represents in the context of data grid grouping.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor`:
- Around line 124-141: The span element with the "bit-dtg-htext" class that
handles OnHeaderClick is not keyboard accessible because it lacks keyboard event
handling. Add a keyboard event handler (such as `@onkeydown`) to this span element
that triggers the sort action when Enter or Space keys are pressed. Create a new
event handler method (such as OnHeaderKeyDown) that checks if the pressed key is
Enter or Space and calls the appropriate sorting method to enable keyboard users
to activate column sorting.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs`:
- Around line 488-493: The catch block for OperationCanceledException is too
broad and swallows all operation cancellations, including unrelated ones or
provider-side timeouts. Instead of catching all OperationCanceledException
instances, you need to filter the catch block to only handle cancellations from
the grid's own request token. Add a condition inside the catch block or use a
filtered catch pattern to check if the cancellation exception's
CancellationToken property matches the expected grid request token (identify the
token field used for this load operation). If the cancellation is not from the
grid's own token, rethrow the exception so legitimate errors surface. Apply this
same filtering pattern to both occurrences mentioned (lines 488-493 and
583-588).
- Around line 433-448: In the ResetInfiniteAsync method, bump the load version
before awaiting the scrollToTop call to prevent race conditions where older
batches complete during the await and append stale rows to the freshly reset
list. The load version should be incremented immediately after clearing
_infiniteItems and before the try block that awaits
_infiniteHandle.InvokeVoidAsync("scrollToTop"), so that when
ResetLoadCancellation is called later in LoadNextBatchAsync, the version check
will correctly reject any stale batches that completed during the await window.
- Around line 280-289: The inputsChanged check in the BitDataGrid parameter
update logic only compares the Items reference using ReferenceEquals, which
fails to detect when a parent mutates the same collection instance in place
(adding/removing items without changing the reference). This leaves the cached
_view data stale in client-mode scenarios. Modify the inputsChanged condition to
include an additional check that forces a refresh in client-mode data scenarios
even when the Items reference remains the same, while keeping the existing
reference guard for server and infinite scroll modes. This ensures that
RefreshAsync is called when the actual collection contents may have changed.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cs`:
- Around line 1-9: Add XML documentation summaries for the three properties in
the BitDataGridFilterDescriptor class. For the ColumnId property, document that
it represents the identifier of the column being filtered and note that it is
immutable (required init property). For the Operator property, document its
purpose as specifying the filter operation and mention that it defaults to
BitDataGridFilterOperator.Contains. For the Value property, document that it
represents the filter value and note that it is nullable, explaining that its
meaning depends on the selected operator (e.g., not used for IsEmpty or
IsNotEmpty operators).
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs`:
- Around line 388-391: The LoadMore method's Task.Delay call does not respect
the cancellation token provided in the BitDataGridReadRequest parameter. Update
the await Task.Delay(350) statement to pass request.CancellationToken as the
second parameter to Task.Delay so that the sample code correctly honors
cancellation requests, matching the actual implementation behavior.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor`:
- Line 4: The `@using` directive on line 4 of BitQuickGridDemo.razor imports from
Demo.Shared.Dtos.QuickGridDemo, but this namespace does not exist. The actual
namespace is Bit.BlazorUI.Demo.Shared.Dtos.QuickGridDemo as used in the
code-behind file BitQuickGridDemo.razor.cs. Update the `@using` statement to use
the full namespace Bit.BlazorUI.Demo.Shared.Dtos.QuickGridDemo instead of the
abbreviated Demo.Shared.Dtos.QuickGridDemo to match the correct fully-qualified
namespace and allow the code to compile.
---
Duplicate comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs`:
- Around line 1226-1235: The Escape method checks for newline characters (\n)
when deciding whether to quote CSV fields, but it does not include carriage
return characters (\r) in the quoting condition. Update the return statement in
the Escape method to also check for \r using an additional .Contains('\r')
condition alongside the existing checks for comma, double quote, and newline, so
that fields containing carriage returns are properly quoted to prevent row
splitting in spreadsheet parsers.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs`:
- Around line 141-147: The cancellable Task.Delay on line 143 can throw a
cancellation exception before entering the try block that starts on line 146,
which causes the finally cleanup block to be bypassed and leaves serverLoading
in an inconsistent state. Move the await Task.Delay(250,
request.CancellationToken) statement inside the try block so that the finally
cleanup block (lines 198-209) will always execute regardless of whether the
delay is cancelled, ensuring serverLoading is properly reset.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cs`:
- Around line 10-26: The properties ColumnId, KeyText, and Aggregates in the
BitDataGridGroup class are missing XML documentation summaries, which reduces
IntelliSense discoverability. Add XML documentation comments above each of these
properties following the same pattern already used for Level, Path, Items, and
SubGroups properties. Each summary should provide a brief description of what
the property represents in the context of data grid grouping.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cs`:
- Around line 4-10: The BitDataGridAggregateResult class and its properties are
missing XML documentation comments that would provide IntelliSense clarity in
IDEs and API documentation. Add XML documentation comments above each property
(ColumnId, Type, Value, and FormattedValue) in the BitDataGridAggregateResult
class using the summary tags to describe what each property represents, its
purpose, and any relevant details about its usage or constraints.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cs`:
- Around line 4-9: The BitDataGridFilterDescriptor class properties (ColumnId,
Operator, and Value) lack XML documentation comments, which prevents
IntelliSense from displaying helpful information for developers using these
properties. Add XML documentation summary comments above each property using the
standard /// <summary> syntax to describe what each property represents and its
purpose in the filter descriptor context.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 5c2fdcdd-b19e-430a-8c6b-b05b04b60e5f
📒 Files selected for processing (86)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (6)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (6)
src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss (1)
7-8: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winRemove the
.scssextension from these imports.These two lines still violate
scss/load-partial-extension, so the touched stylesheet will keep failing stylelint.Suggested fix
-@import "../Components/QuickGrid/BitQuickGrid.scss"; -@import "../Components/QuickGrid/Pagination/BitQuickGridPaginator.scss"; +@import "../Components/QuickGrid/BitQuickGrid"; +@import "../Components/QuickGrid/Pagination/BitQuickGridPaginator";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss` around lines 7 - 8, The imports in extra-components.scss still include the .scss extension and violate scss/load-partial-extension; update the two `@import` statements to use partial-style paths without the extension. Keep the existing targets BitQuickGrid.scss and BitQuickGridPaginator.scss referenced via their current relative locations, but remove the trailing file extension so stylelint passes.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs (2)
610-617: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRecompute footer aggregates when infinite state is reset.
This clears the visible rows immediately, but
_footerAggregatesstill reflects the previous batch until the next load completes. WithShowFooter, the grid can briefly render totals for rows that are no longer on screen.Proposed fix
_infiniteLoading = false; _view = _infiniteItems; _pageItems = _infiniteItems; + _footerAggregates = BitDataGridDataProcessor.Aggregate(_infiniteItems, _columns);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs` around lines 610 - 617, Reset the infinite-loading state in ResetInfiniteAsync should also clear or recompute the footer aggregate state, because _footerAggregates is left stale after _infiniteItems and _view are reset. Update the ResetInfiniteAsync flow in BitDataGrid to invalidate the current footer totals alongside _infiniteItems, _infiniteHasMore, _infiniteLoading, _view, and _pageItems so ShowFooter does not display outdated aggregates before the next load.
358-362: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winThrow on live column-ID collisions during re-keying.
Returning here leaves
column.Idchanged while_columnsByIdand any existing descriptors stay keyed underoldId, so sort/filter/group lookups for that column stop matching the UI state.Proposed fix
- if (_columnsById.TryGetValue(column.Id, out var clash) && !ReferenceEquals(clash, column)) - return; + if (_columnsById.TryGetValue(column.Id, out var clash) && !ReferenceEquals(clash, column)) + throw new InvalidOperationException( + $"Duplicate {nameof(BitDataGridColumn<TItem>)} id '{column.Id}'. Set a unique ColumnId.");🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs` around lines 358 - 362, Throw an error when re-keying in BitDataGrid rather than returning silently from the collision check in the column-ID update path. In the code that handles the rename/rekey logic for the column registry, if _columnsById.TryGetValue finds a different live column for the new Id, raise an exception instead of leaving the renamed column partially updated. Keep the fix localized to the re-keying logic in BitDataGrid and preserve the existing duplicate-ID behavior used by AddColumn.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cs (1)
625-625: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse Razor expression syntax for
ItemKeyin both samples.These snippets still render
ItemKey="(p => p.Id)", so copied code binds a string literal instead of the delegate expressionBitQuickGridexpects.Suggested fix
- <BitQuickGrid `@ref`=""productsDataGrid"" ItemsProvider=""`@productsItemsProvider`"" ItemKey=""(p => p.Id)"" TGridItem=""ProductDto"" Virtualize ItemSize=""32""> + <BitQuickGrid `@ref`=""productsDataGrid"" ItemsProvider=""`@productsItemsProvider`"" ItemKey=""@(p => p.Id)"" TGridItem=""ProductDto"" Virtualize ItemSize=""32"">- <BitQuickGrid `@ref`=""productsDataGrid"" ItemsProvider=""`@productsItemsProvider`"" ItemKey=""(p => p.Id)"" TGridItem=""ProductDto"" Pagination=""pagination""> + <BitQuickGrid `@ref`=""productsDataGrid"" ItemsProvider=""`@productsItemsProvider`"" ItemKey=""@(p => p.Id)"" TGridItem=""ProductDto"" Pagination=""pagination"">Also applies to: 805-805
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cs` at line 625, The QuickGrid sample still passes ItemKey as a quoted string, so update the BitQuickGrid markup in the demo samples to use Razor expression syntax for the ItemKey delegate instead of a string literal. Fix both affected examples in the BitQuickGrid sample content so the ItemKey attribute is bound as an expression, matching what BitQuickGrid expects and using the existing productsDataGrid/productsItemsProvider sample setup.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scss (1)
12-12: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winSuppress stylelint's
::deepfalse positives in this file.These four
::deepblocks still triggerselector-pseudo-element-no-unknown, so the SCSS will keep failing lint until the rule is disabled locally here or configured for Blazor globally.Suggested fix
.custom-grid { + /* stylelint-disable selector-pseudo-element-no-unknown */ ::deep { ... } + /* stylelint-enable selector-pseudo-element-no-unknown */ }Apply the same pattern to the other
::deepblocks, or exempt::deepin the shared stylelint config.Also applies to: 62-62, 89-89, 122-122
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scss` at line 12, The four `::deep` selectors in `BitQuickGridDemo.razor.scss` are being flagged by `selector-pseudo-element-no-unknown`; suppress this false positive either by disabling that rule locally for this SCSS file or by updating the shared stylelint configuration to allow `::deep` for Blazor, and apply the same handling to every `::deep` block in this component.Source: Linters/SAST tools
src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cs (1)
3-6: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winKeep
BitDataGridPaginationStateas an obsolete compatibility shim.Renaming this public type breaks existing paginator code that already compiles against
BitDataGridPaginationState. Unless this release is intentionally breaking, keep the old name available and forward it to the new implementation.Suggested fix
public class BitQuickGridPaginationState { ... } + +[Obsolete("Use BitQuickGridPaginationState instead.")] +public class BitDataGridPaginationState : BitQuickGridPaginationState +{ +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cs` around lines 3 - 6, Keep BitDataGridPaginationState available as an obsolete compatibility shim instead of replacing it outright with BitQuickGridPaginationState; add or retain BitDataGridPaginationState as a public type that forwards to the new implementation so existing callers continue to compile, and mark it obsolete with guidance to use BitQuickGridPaginationState while keeping the new class as the primary implementation.
🧹 Nitpick comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cs (1)
23-35: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy liftAvoid storing descendant rows on every ancestor group.
Lines 23-35 document
Itemsas “all rows that fall under this group (across nested subgroups). For multi-level grouping that duplicates the same row references once per ancestor, so grouped datasets get noticeably heavier as depth increases. KeepingItemsonly on leaves and storingCount`/aggregates on parent groups would avoid that amplification.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cs` around lines 23 - 35, The BitDataGridGroup<TItem>.Items property is currently holding all descendant rows on every ancestor group, which duplicates row references across nested levels. Update the grouping model so only leaf groups retain row lists, while parent groups rely on Count, Aggregates, and SubGroups for summary data; adjust any code that reads or populates Items in BitDataGridGroup<TItem> accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor`:
- Around line 428-453: The typed filter handling in BitDataGrid is converting
empty input values and the Boolean “All” option into a real null-equality
filter, which causes cleared filters to match only null rows instead of removing
the filter. Update the typed filter path in BitDataGrid.razor around
SetTypedFilterAsync and the raw == "" handling so blank number/date/boolean
values clear the filter state or produce no descriptor, rather than creating an
Equals null condition. Make sure the resulting descriptor logic stays compatible
with BitDataGridDataProcessor.Matches.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor`:
- Around line 6-10: The boolean editor in BitDataGridCellEditor currently uses a
plain checkbox, which forces nullable boolean cells to behave like two-state
values and lose null. Update the BitDataGridCellEditor.razor rendering for
BitDataGridColumnDataType.Boolean to use a tri-state/null-capable editor and
wire it to the existing GetBool and Set handling so bool? values can be
displayed and cleared back to null instead of collapsing into false.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs`:
- Around line 61-103: Treat cleared empty-string edits as null in
BitDataGridPropertyAccessor when converting values for nullable targets. Update
the conversion path that currently special-cases only null so that an empty
string is normalized to null before the PropertyType/UnderlyingType checks,
while still rejecting clears for non-nullable value types. Keep the fix
localized in the accessor logic around the existing null-handling and target
conversion branches.
---
Duplicate comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cs`:
- Around line 610-617: Reset the infinite-loading state in ResetInfiniteAsync
should also clear or recompute the footer aggregate state, because
_footerAggregates is left stale after _infiniteItems and _view are reset. Update
the ResetInfiniteAsync flow in BitDataGrid to invalidate the current footer
totals alongside _infiniteItems, _infiniteHasMore, _infiniteLoading, _view, and
_pageItems so ShowFooter does not display outdated aggregates before the next
load.
- Around line 358-362: Throw an error when re-keying in BitDataGrid rather than
returning silently from the collision check in the column-ID update path. In the
code that handles the rename/rekey logic for the column registry, if
_columnsById.TryGetValue finds a different live column for the new Id, raise an
exception instead of leaving the renamed column partially updated. Keep the fix
localized to the re-keying logic in BitDataGrid and preserve the existing
duplicate-ID behavior used by AddColumn.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cs`:
- Around line 3-6: Keep BitDataGridPaginationState available as an obsolete
compatibility shim instead of replacing it outright with
BitQuickGridPaginationState; add or retain BitDataGridPaginationState as a
public type that forwards to the new implementation so existing callers continue
to compile, and mark it obsolete with guidance to use
BitQuickGridPaginationState while keeping the new class as the primary
implementation.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scss`:
- Around line 7-8: The imports in extra-components.scss still include the .scss
extension and violate scss/load-partial-extension; update the two `@import`
statements to use partial-style paths without the extension. Keep the existing
targets BitQuickGrid.scss and BitQuickGridPaginator.scss referenced via their
current relative locations, but remove the trailing file extension so stylelint
passes.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cs`:
- Line 625: The QuickGrid sample still passes ItemKey as a quoted string, so
update the BitQuickGrid markup in the demo samples to use Razor expression
syntax for the ItemKey delegate instead of a string literal. Fix both affected
examples in the BitQuickGrid sample content so the ItemKey attribute is bound as
an expression, matching what BitQuickGrid expects and using the existing
productsDataGrid/productsItemsProvider sample setup.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scss`:
- Line 12: The four `::deep` selectors in `BitQuickGridDemo.razor.scss` are
being flagged by `selector-pseudo-element-no-unknown`; suppress this false
positive either by disabling that rule locally for this SCSS file or by updating
the shared stylelint configuration to allow `::deep` for Blazor, and apply the
same handling to every `::deep` block in this component.
---
Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cs`:
- Around line 23-35: The BitDataGridGroup<TItem>.Items property is currently
holding all descendant rows on every ancestor group, which duplicates row
references across nested levels. Update the grouping model so only leaf groups
retain row lists, while parent groups rely on Count, Aggregates, and SubGroups
for summary data; adjust any code that reads or populates Items in
BitDataGridGroup<TItem> accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a08e4c53-2d18-407c-8205-50607a894744
📒 Files selected for processing (87)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (7)
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 6
♻️ Duplicate comments (4)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs (2)
61-65: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winDon't rewrite empty-string edits on
stringcolumns tonull.Line 64 normalizes every
""input before checking the target type, so a text cell bound tostringcan never persist an actual empty string.Minimal fix
- if (value is string es && es.Length == 0) + if (value is string es && es.Length == 0 && PropertyType != typeof(string)) value = null;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs` around lines 61 - 65, The empty-string normalization in BitDataGridPropertyAccessor is too broad and turns legitimate string edits into null. Update the value handling in the accessor logic so the empty-string-to-null conversion only applies when the target property is nullable/non-string, and preserves "" for string-typed columns. Use the existing value coercion path in BitDataGridPropertyAccessor to branch on the property type before normalizing.
21-25: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftConstrain
TItemor changeSetValueto update the stored row by reference.Line 37 takes
TItemby value, and Line 44 invokes anAction<TItem, object?>, so any value-type row is edited on a copy. This helper is public and unconstrained, so struct-backed rows can still lose inline edits.#!/bin/bash set -euo pipefail # Check whether the grid/accessor surface constrains TItem to reference types. rg -nP --type=cs 'where\s+TItem\s*:\s*class|BitDataGridPropertyAccessor<|SetValue\s*\(' \ src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid -C2 # Inspect the edit pipeline around the accessor usage. sed -n '1,220p' src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs sed -n '960,1105p' src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.csAlso applies to: 37-45
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs` around lines 21 - 25, The BitDataGridPropertyAccessor<TItem> edit path is still operating on a copied row when TItem is a value type, so inline edits can be lost. Fix this by either constraining BitDataGridPropertyAccessor<TItem> and the related grid edit surface to reference types, or by changing SetValue and the stored setter delegate so updates are applied back to the original row storage by reference. Check the BitDataGridPropertyAccessor constructor, SetValue, and the BitDataGrid edit pipeline that invokes the accessor to keep the row mutation semantics consistent.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cs (1)
9-10: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winMake
Typerequired in this model.Leaving
Typeunset still falls back to enum0, so an aggregate result can be created without declaring which aggregation produced it.Minimal fix
- public BitDataGridAggregateType Type { get; init; } + public required BitDataGridAggregateType Type { get; init; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cs` around lines 9 - 10, Make BitDataGridAggregateResult.Type required so aggregate results cannot be created without explicitly declaring the aggregation kind. Update the BitDataGridAggregateResult model to require Type at initialization (using the model’s existing init-only property pattern) and ensure any construction sites for BitDataGridAggregateResult provide a concrete BitDataGridAggregateType value.src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cs (1)
8-8: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winFix the return-type cref.
Line 8 still references
ValueTask{TResult}, butTResultis undeclared here, so the XML doc doesn't match the delegate signature. Point the cref at the concreteValueTask<BitQuickGridItemsProviderResult<TGridItem>>return type instead.Proposed fix
-/// <returns>A <see cref="ValueTask{TResult}"/> whose result is a <see cref="BitQuickGridItemsProviderResult{TGridItem}"/> that gives the data to be displayed.</returns> +/// <returns>A <see cref="ValueTask{BitQuickGridItemsProviderResult{TGridItem}}"/> that gives the data to be displayed.</returns>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cs` at line 8, The XML documentation on BitQuickGridItemsProviderResult/BitQuickGridItemsProvider delegate still uses an undeclared generic cref for ValueTask{TResult}; update the return-type reference in the doc comment to the concrete ValueTask<BitQuickGridItemsProviderResult<TGridItem>> signature so it matches the delegate’s actual return type and resolves correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor`:
- Around line 511-516: The DateTimeOffset date filter in BitDataGrid’s
date-handling path should not use the ambient offset returned by
DateTimeOffset.TryParse. Update the logic in the DateTimeOffset branch to derive
the range from a fixed offset or from DateOnly and then construct the [start,
nextDay) bounds explicitly. Keep the change localized to the parsing/filtering
flow around the underlying type check and SetDateRangeFilterAsync so filtering
behaves consistently across environments.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss`:
- Around line 455-469: The boolean editor in BitDataGrid is still inheriting the
text-input chrome from the .bit-dtg-editor / .bit-dtg-filter-input rules,
because BitDataGridCellEditor uses both bit-dtg-editor and bit-dtg-editor-check
for checkboxes. Update the .bit-dtg-editor-check styling so it fully resets
checkbox-specific appearance instead of only changing width, and ensure the
checkbox render path in BitDataGridCellEditor keeps the boolean editor visually
native while preserving the text-input styles for non-boolean editors.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cs`:
- Around line 9-10: The BitDataGridFilterDescriptor.Operator property is still
silently defaulting omitted values to Contains, which defeats the new
Unspecified sentinel behavior. Remove the initializer from Operator so missing
values stay Unspecified/invalid at the boundary, and keep the DTO/model flow
aligned with BitDataGridFilterOperator in BitDataGridFilterDescriptor.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cs`:
- Line 30: The public rename from BitDataGridColumnsCollectedNotifier<TGridItem>
to BitQuickGridColumnsCollectedNotifier<TGridItem> breaks downstream references,
so keep backward compatibility by adding an [Obsolete] forwarding shim with the
old type name. Update the notifier surface around
BitQuickGridColumnsCollectedNotifier<TGridItem> to remain the preferred
implementation, and have BitDataGridColumnsCollectedNotifier<TGridItem> inherit
or delegate to it so existing consumers continue to compile.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scss`:
- Around line 1-8: Restore the missing demo-specific styles in
BitDataGridDemo.razor.scss by bringing back the DataGrid layout rules that were
removed, not just the .span-banner and .muted utility classes. Reintroduce the
selectors for sticky headers, responsive cell labels, search panel sizing, and
row-detail sizing so the BitDataGridDemo component still behaves correctly on
narrow screens and in overflow cases. Keep the existing utility classes intact
and ensure the restored rules are applied to the demo’s DataGrid layout
elements.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor`:
- Around line 81-90: The live virtualized grid in BitQuickGridDemo.razor is
missing the same ItemSize setting already present in example3RazorCode, causing
the demo to diverge and virtualization to use the default row height. Update the
BitQuickGrid instance in the Virtualize example to match the sample by setting
ItemSize to 32 so the live demo and copied code stay consistent and scrolling
behaves correctly.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs`:
- Around line 61-65: The empty-string normalization in
BitDataGridPropertyAccessor is too broad and turns legitimate string edits into
null. Update the value handling in the accessor logic so the
empty-string-to-null conversion only applies when the target property is
nullable/non-string, and preserves "" for string-typed columns. Use the existing
value coercion path in BitDataGridPropertyAccessor to branch on the property
type before normalizing.
- Around line 21-25: The BitDataGridPropertyAccessor<TItem> edit path is still
operating on a copied row when TItem is a value type, so inline edits can be
lost. Fix this by either constraining BitDataGridPropertyAccessor<TItem> and the
related grid edit surface to reference types, or by changing SetValue and the
stored setter delegate so updates are applied back to the original row storage
by reference. Check the BitDataGridPropertyAccessor constructor, SetValue, and
the BitDataGrid edit pipeline that invokes the accessor to keep the row mutation
semantics consistent.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cs`:
- Around line 9-10: Make BitDataGridAggregateResult.Type required so aggregate
results cannot be created without explicitly declaring the aggregation kind.
Update the BitDataGridAggregateResult model to require Type at initialization
(using the model’s existing init-only property pattern) and ensure any
construction sites for BitDataGridAggregateResult provide a concrete
BitDataGridAggregateType value.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cs`:
- Line 8: The XML documentation on
BitQuickGridItemsProviderResult/BitQuickGridItemsProvider delegate still uses an
undeclared generic cref for ValueTask{TResult}; update the return-type reference
in the doc comment to the concrete
ValueTask<BitQuickGridItemsProviderResult<TGridItem>> signature so it matches
the delegate’s actual return type and resolves correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 8c115b5a-f81c-4c9b-baa1-1b77a06e2d42
📒 Files selected for processing (87)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (7)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss`:
- Around line 188-209: The header text wrapper `.bit-dtg-htext` is missing the
flexbox shrink override, so long sortable labels can refuse to shrink and won’t
ellipsize correctly in narrow columns. Add the flex min-size fix to
`.bit-dtg-htext` so it can shrink inside the header cell, while keeping the
existing `button.bit-dtg-htext` reset styles unchanged.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor`:
- Around line 37-45: The datetime-local editor path is dropping sub-minute
precision because `GetDateTime`, `SetDateTime`, and `SetDateTimeOffset`
round-trip only the minute-level string. Update the `BitDataGridCellEditor`
logic so the existing seconds/ticks from the bound `DateTime`/`DateTimeOffset`
are preserved when the user changes only the date or minute, instead of
rebuilding a value that resets them to zero. Keep the `datetime-local` input
wiring the same, but adjust the parsing/merging in those helper methods to carry
forward the original sub-minute component.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor`:
- Around line 463-468: The EmptyTemplate in BitDataGridDemo should not mention
filters because this demo has no filter UI. Update the empty-state text inside
the BitStack/BitText block to remove the “adjusting your filters” hint and keep
the message focused on loading sample data; use the EmptyTemplate and BitText
elements in BitDataGridDemo.razor to locate it.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cs`:
- Around line 348-350: The OnReorder handler in BitDataGridDemo.razor.cs assumes
BitDataGridRowReorderEventArgs<Product>.FromIndex and ToIndex are always
present, which can produce invalid log text when either is null. Update
OnReorder to handle nullable indices with a safe fallback message or placeholder
before building reorderLog, while keeping the existing use of e.DraggedItem.Name
and the reorder event arguments.
- Around line 209-213: In LoadServerData, cancellation is only checked during
the delay, so a canceled request can still return stale rows after
filtering/sorting/paging completes. Add an explicit check against
request.CancellationToken right before building and returning the
BitDataGridReadResult<Product>, and use the same token in the query flow if
possible so canceled requests stop before server data is returned.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 5ed35822-d015-4514-a39f-f2b8d04967a5
📒 Files selected for processing (87)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (7)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cs (1)
7-48: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winKeep a compatibility shim for the old items-provider result types.
This rename changes a public
ItemsProvidercontract, so existing consumers returningBitDataGridItemsProviderResult<TGridItem>will stop compiling. Please keep obsolete forwarding shims for both the generic and helper types, or explicitly ship this as a documented breaking change.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cs` around lines 7 - 48, The public items-provider result rename in BitQuickGridItemsProviderResult changes the existing contract and breaks callers using BitDataGridItemsProviderResult. Add obsolete compatibility shims for the old generic result type and its helper/From factory, forwarding to BitQuickGridItemsProviderResult so existing consumers keep compiling, or otherwise treat this as an explicit breaking change. Use the BitQuickGridItemsProviderResult<TGridItem> struct and the static BitQuickGridItemsProviderResult helper as the primary location to preserve backward compatibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor`:
- Around line 173-191: The SetDateTimeOffset path currently falls back to
TimeZoneInfo.Local when Value is null, which can persist a browser-entered
datetime-local using the server’s timezone instead of the client’s. Update this
branch in SetDateTimeOffset to use the browser-provided timezone/offset for the
null-Value case, while still preserving the existing current-value offset and
sub-minute tick handling before calling Grid.SetEditValue.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razor`:
- Around line 11-15: The reorder handle’s keyboard path in BitDataGridRow.razor
should intercept ArrowUp/ArrowDown before the browser handles them. Update
HandleReorderKeyDown for the drag handle button so the ArrowUp/ArrowDown cases
call MoveRowAsync and prevent the default action on the event target, keeping
the shortcut scoped to that button and avoiding page/grid scrolling. Apply the
same change to the duplicate reorder handle markup referenced in the component.
---
Outside diff comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cs`:
- Around line 7-48: The public items-provider result rename in
BitQuickGridItemsProviderResult changes the existing contract and breaks callers
using BitDataGridItemsProviderResult. Add obsolete compatibility shims for the
old generic result type and its helper/From factory, forwarding to
BitQuickGridItemsProviderResult so existing consumers keep compiling, or
otherwise treat this as an explicit breaking change. Use the
BitQuickGridItemsProviderResult<TGridItem> struct and the static
BitQuickGridItemsProviderResult helper as the primary location to preserve
backward compatibility.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 320737b8-0db9-4232-95a6-b7c4b3af27a1
📒 Files selected for processing (87)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (7)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (2)
src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cs (1)
27-35: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winReturn the last supporting executor to preserve DI precedence.
GetServices<IAsyncQueryExecutor>()enumerates registrations in order, so returning on the firstIsSupported(queryable)match lets an earlier generic executor override a later, more specific one. That is the opposite of normal DI override behavior and can still hide the EF-specific executor this method is trying to find.Suggested fix
- foreach (var executor in services.GetServices<IAsyncQueryExecutor>()) + IAsyncQueryExecutor? matchedExecutor = null; + foreach (var executor in services.GetServices<IAsyncQueryExecutor>()) { if (executor.IsSupported(queryable)) { - return executor; + matchedExecutor = executor; } } + + if (matchedExecutor is not null) + { + return matchedExecutor; + }In Microsoft.Extensions.DependencyInjection, does GetServices<T>() enumerate services in registration order, and does resolving a single service return the last registration?🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cs` around lines 27 - 35, The selection logic in AsyncQueryExecutorSupplier should preserve DI override precedence instead of returning the first supported IAsyncQueryExecutor from GetServices<IAsyncQueryExecutor>(). Update the loop to keep scanning and return the last executor whose IsSupported(queryable) is true, using the existing AsyncQueryExecutorSupplier resolution path so later, more specific registrations can override earlier generic ones without changing the EF warning behavior.src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor (1)
173-191: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftDon't derive a new
DateTimeOffsetfrom the host timezone.When
Valueisnull, this fallback usesTimeZoneInfo.Local, which resolves on the Blazor host rather than the browser. In Server hosting, the samedatetime-localinput can therefore be persisted with the server's offset instead of the user's, changing the stored instant. Use a browser-supplied offset/time-zone for this path instead.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor` around lines 173 - 191, The SetDateTimeOffset path currently falls back to TimeZoneInfo.Local when Value is null, which derives the offset from the Blazor host instead of the browser. Update this logic so the offset used for the new DateTimeOffset comes from browser-provided client timezone/offset data rather than the server, and keep the existing DateTimeOffset original-offset preservation behavior when Value already has one. Make the change in BitDataGridCellEditor.razor around SetDateTimeOffset and ensure Grid.SetEditValue still receives a correctly offset-adjusted DateTimeOffset.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor`:
- Around line 511-520: The `DateTimeOffset` branch in `BitDataGrid` is filtering
against fixed UTC midnights, which can exclude values whose own offset still
places them on the selected calendar date. Update the date-filter handling
around `SetDateRangeFilterAsync` so the filter semantics match the displayed
date: either normalize `DateTimeOffset` values and bounds consistently to UTC
before comparison, or keep the `DateTimeOffset` path strictly date-only instead
of converting to a single UTC range. Apply the same fix to the duplicated
`DateTimeOffset` logic in both affected blocks so filtering behaves consistently
regardless of offset.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razor`:
- Line 16: The reorder key handling in BitDataGridRow.razor is mutating the
`@onkeydown:preventDefault` state too late via `HandleReorderKeyDown`, so the
browser default can still run on the first ArrowUp/ArrowDown press and the flag
may leak to the next event. Move the prevent-default decision out of
`HandleReorderKeyDown` and into a pre-dispatch path, such as a JS or key filter
handler, so the default action is determined before the event reaches the
callback.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs`:
- Around line 552-557: The ARIA row count calculation in BitQuickGrid currently
uses Pagination.ItemsPerPage even when the last page has fewer items, so
assistive tech can announce extra non-existent rows. Update the row-count logic
in BitQuickGrid.razor.cs where _ariaBodyRowCount is assigned to clamp the
paginated value to the remaining items on the current page instead of always
using the configured page size, while keeping the non-paginated and virtualized
behavior unchanged.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cs`:
- Around line 74-97: The Title auto-generation logic in
BitQuickGridPropertyColumn is still inferring user intent by comparing the
current Title value to the last generated one, which can overwrite an explicit
Title that happens to match. Update the column to track whether Title was
explicitly supplied from ParameterView (for example via a dedicated flag set
during parameter handling) and use that flag in the
Property.Body/MemberExpression path instead of value equality, so only truly
auto-generated titles are regenerated or cleared.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor`:
- Around line 173-191: The SetDateTimeOffset path currently falls back to
TimeZoneInfo.Local when Value is null, which derives the offset from the Blazor
host instead of the browser. Update this logic so the offset used for the new
DateTimeOffset comes from browser-provided client timezone/offset data rather
than the server, and keep the existing DateTimeOffset original-offset
preservation behavior when Value already has one. Make the change in
BitDataGridCellEditor.razor around SetDateTimeOffset and ensure
Grid.SetEditValue still receives a correctly offset-adjusted DateTimeOffset.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cs`:
- Around line 27-35: The selection logic in AsyncQueryExecutorSupplier should
preserve DI override precedence instead of returning the first supported
IAsyncQueryExecutor from GetServices<IAsyncQueryExecutor>(). Update the loop to
keep scanning and return the last executor whose IsSupported(queryable) is true,
using the existing AsyncQueryExecutorSupplier resolution path so later, more
specific registrations can override earlier generic ones without changing the EF
warning behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7582b459-994c-44dd-be95-2f49001dd217
📒 Files selected for processing (87)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (7)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razor`:
- Around line 11-16: Keyboard row reordering is still active during edit mode
because the drag handle remains focusable and HandleReorderKeyDown still reacts
to ArrowUp/ArrowDown even when Editing is true. Update BitDataGridRow’s reorder
handler path so the keydown logic is ignored or short-circuited while the row is
being edited, matching the existing draggable guard; apply the same fix to the
other drag-handle occurrence referenced in the component.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cs`:
- Around line 170-182: Skip generating a setter for nested property paths in
BitDataGridPropertyAccessor when the chain crosses a struct-valued property,
since Expression.Assign on a path like Address.City cannot write back through a
value-type parent. Update the setter creation logic around the
canWrite/nullGuard block so it only compiles setters for safe reference-type
chains or direct properties, and leave these nested struct paths read-only
unless you implement a full get-modify-set rewrite.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cs`:
- Around line 35-44: The Title handling in BitQuickGridPropertyColumn currently
latches explicitness forever, so once a consumer removes Title later the
auto-generated header never comes back. Update SetParametersAsync to derive
explicitness from the current ParameterView each render instead of only setting
_titleWasExplicitlySet to true, and make the Title/Property update logic in
BitQuickGridPropertyColumn recompute whether to use the explicit Title or the
auto-generated one whenever parameters change.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cs`:
- Around line 678-681: The OData filter handling in the QuickGrid demo currently
treats whitespace-only input as a real search term, so update the filter check
near _odataSampleNameFilter to treat values made only of spaces as empty. Adjust
the logic that builds the "$filter" query in BitQuickGridDemo so it skips adding
contains(Name,...) unless the trimmed filter has content, while still escaping
apostrophes for valid input.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: cc87dfad-c8b0-47d2-b96f-cf64cab6bb81
📒 Files selected for processing (87)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (7)
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cs`:
- Line 805: The BitQuickGrid sample is passing Pagination as a string literal
instead of the BitQuickGridPaginationState instance, which makes the copied
example invalid. Update the BitQuickGrid usage to bind Pagination as an
expression so it references the existing pagination variable/state rather than
the text value, keeping the ItemsProvider and other parameters unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f6019e11-5162-41fd-8879-ff517f821c6b
📒 Files selected for processing (87)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (7)
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs
|
@coderabbitai re-review |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 13
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor`:
- Around line 374-466: RenderGroupList, RenderGroup, and RenderFilterEditor are
using invalid Razor render-fragment syntax with __builder =>, so they should be
rewritten as proper Razor templates using => @<...> or as explicit
RenderTreeBuilder code. Update the existing BitDataGrid.razor helpers (including
the RenderGroup and RenderFilterEditor methods) so the markup is emitted through
valid Razor source and compiles correctly.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss`:
- Around line 362-370: The focus styling in BitDataGrid.scss for
.bit-dtg-cell[tabindex]:focus and :focus-visible uses the same primary color as
selected cell backgrounds, so keyboard focus can become invisible. Update the
focus ring styling in this cell selector block to use a contrasting color or
alternate focus treatment when a cell is selected, and keep the focus indicator
clearly visible for selected rows and cells.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor`:
- Around line 10-65: The built-in editors in BitDataGridCellEditor.razor
currently have no accessible name, so screen readers can’t identify the column
being edited. Update each editor branch in the switch (select/input for Boolean,
Number, Date, DateTime, DateTimeOffset, Enum, and default text) to include an
aria-label based on the column title, using Column.DisplayTitle in the label
text. Keep the change localized to these editor controls so focusable elements
announce the correct field name.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cs`:
- Around line 149-167: `BitDataGridColumn<TItem>.OnParametersSet` currently
treats every `Grid.AddColumn(this)` call as a successful registration by setting
`_registeredId`, even when the grid rejects a duplicate id. Update the
registration flow so `_registeredId` is only assigned when `AddColumn` actually
adds the column, or retry `Grid.AddColumn(this)` when `_registeredId` is null
after a duplicate is skipped. Keep the re-registration logic in
`UpdateColumnRegistration` dependent on a real prior registration so skipped
duplicate columns can be added later when `Id`/`Field` becomes unique.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cs`:
- Around line 83-85: Update the grouping logic in BitDataGridDataProcessor so it
uses the same comparison semantics as the grid’s existing
BitDataGridValueComparer and Equals-based filtering path. The GroupBy call on
column.Accessor!.GetValue(item) is currently relying on default object equality,
so adjust the grouping key comparison to use the grid’s comparer for that
column, keeping grouping behavior consistent with sorting and filtering for
values like strings.
- Around line 311-321: CoerceToValueType currently uses a generic
Convert.ChangeType fallback, so it does not match the accessor’s conversion
behavior for filter operands like Guid, DateOnly, TimeOnly, and DateTimeOffset.
Update BitDataGridDataProcessor.CoerceToValueType to reuse the same coercion
logic as BitDataGridPropertyAccessor.TryConvertValue, including its
type-specific parsing paths, and keep the enum handling aligned so filter values
are converted to the property’s real type before comparison.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cs`:
- Around line 7-15: The BitDataGridReadResult constructor currently accepts
inconsistent read results where the current page size exceeds the reported total
count. Add a validation guard in BitDataGridReadResult(IReadOnlyList<TItem>
items, int totalCount) to reject cases where items.Count is greater than
totalCount, alongside the existing null and negative checks. Keep the failure at
this boundary so BitDataGrid.razor.cs never receives mismatched _pageItems and
_totalCount values from bad OnRead providers.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cs`:
- Around line 289-315: The refresh logic in OnParametersSetAsync currently
tracks only the data source and pagination state, so a change in view mode
between virtualized and non-virtualized is missed. Update the mustRefreshData
calculation to also detect when the Virtualize setting changes, and trigger
RefreshDataCoreAsync when that happens so BitQuickGrid does not keep using stale
_currentNonVirtualizedViewItems after a mode flip. Use the existing
OnParametersSetAsync flow and the
_lastRefreshedPaginationStateHash/_lastAssignedItemsOrItemsProvider tracking to
locate the refresh condition.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cs`:
- Line 7: The public row-template args type was renamed from
BitDataGridRowTemplateArgs<T> to BitQuickGridRowTemplateArgs<T>, which breaks
existing consumers immediately. Keep BitDataGridRowTemplateArgs<T> available as
an [Obsolete] forwarding/alias type that maps to BitQuickGridRowTemplateArgs<T>,
so older compiled code continues to work for one release. Update the QuickGrid
row-template contract carefully and preserve compatibility in the affected type
definition.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cs`:
- Around line 35-44: The Title parameter handling in
BitQuickGridPropertyColumn.SetParametersAsync needs to clear stale explicit
values when the parent stops passing Title. Update the parameter flow so that
when parameters no longer contain Title, the component resets the stored Title
before/around base.SetParametersAsync, and adjust the auto-title logic in the
property-column expression handling so only member-expression headers are
overwritten while method/cast expressions can also fall back to the generated
title. Use the existing _titleWasExplicitlySet flag and the
Title/SetParametersAsync path to locate the fix.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cs`:
- Around line 4-9: The renamed items-provider contracts introduce a breaking API
change for existing BitDataGrid consumers. Keep backward-compatible obsolete
forwarders for the old delegate and request/result type names by adding
[Obsolete] aliases/shims that delegate to the new BitQuickGrid* symbols, so
downstream apps can migrate without compile breaks. Make sure the existing
public contract around BitQuickGridItemsProvider and its request/result types
remains the new implementation target while the old BitDataGrid* names stay
available for compatibility.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs`:
- Around line 102-146: The embedded FileSystemDataCode snippet is out of sync
with the live FileSystemData.Build helper, so update the string in
BitDataGridDemo to match the current tree shape. Add the missing branches and
file entries from FileSystemData.Build, including Infrastructure,
BitDataGrid.Demo, assets, and the extra model file, and keep the Folder/File
local helpers and resulting hierarchy identical so example13CsharpCode reflects
the reproducible demo data.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cs`:
- Around line 741-744: The QuickGrid OData sample still treats whitespace-only
input as a valid filter and passes the untrimmed value into the $filter query,
which can generate a broken contains(Name,' ') expression. Update the
condition in the sample method that builds the OData query (the block using
_odataSampleNameFilter and query.Add) so it treats whitespace-only values as
empty, and ensure the emitted filter uses the trimmed value rather than the raw
string.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 986d1490-ac4d-41c1-9403-bdf7b62180dc
📒 Files selected for processing (87)
src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCell.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridRow.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridGroup.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridPropertyAccessor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridValueComparer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridAggregateType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridCellEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridColumnDataType.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridFilterOperator.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridGroupDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridPagerPosition.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridReadResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridRowReorderEventArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSelectionMode.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDescriptor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Models/BitDataGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGrid.tssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridJsRuntimeExtensions.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridSortDirection.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridAlign.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridColumnBase.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridSort.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridTemplateColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/IBitQuickGridSortBuilderColumn.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/AsyncQueryExecutorSupplier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridColumnsCollectedNotifier.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/BitQuickGridDefer.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscribable.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventCallbackSubscriber.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/EventHandlers.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/IAsyncQueryExecutor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Infrastructure/InternalGridContext.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderRequest.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProviderResult.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginationState.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razorsrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.razor.cssrc/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Pagination/BitQuickGridPaginator.scsssrc/BlazorUI/Bit.BlazorUI.Extras/Styles/extra-components.scsssrc/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/AppJsonContext.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecall.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/FoodRecallQueryResult.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Meta.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Openfda.cssrc/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/QuickGridDemo/Results.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.params.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/Product.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SampleData.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/SupplierModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/CountryModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/MedalsModel.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Shared/MainLayout.razor.NavItems.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/compilerconfig.json
💤 Files with no reviewable changes (7)
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridPropertyColumn.cs
- src/BlazorUI/Demo/Bit.BlazorUI.Demo.Shared/Dtos/DataGridDemo/Openfda.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/ItemsProvider/BitDataGridItemsProvider.cs
- src/BlazorUI/Bit.BlazorUI/Utils/BitDirection.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/IBitDataGridSortBuilderColumn.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Columns/BitDataGridColumnBase.razor.cs
- src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridJsRuntimeExtensions.cs
| private RenderFragment RenderGroupList(IReadOnlyList<BitDataGridGroup<TItem>> groups) => __builder => | ||
| { | ||
| var initialRowIndex = 2; // aria-rowindex is 1-based, plus the first row is the header | ||
| var rowIndex = initialRowIndex; | ||
| foreach (var item in _currentNonVirtualizedViewItems) | ||
| foreach (var group in groups) | ||
| { | ||
| RenderRow(__builder, rowIndex++, item); | ||
| <text>@RenderGroup(group)</text> | ||
| } | ||
| }; | ||
|
|
||
| // When pagination is enabled, by default ensure we render the exact number of expected rows per page, | ||
| // even if there aren't enough data items. This avoids the layout jumping on the last page. | ||
| // Consider making this optional. | ||
| if (Pagination is not null) | ||
| private RenderFragment RenderGroup(BitDataGridGroup<TItem> group) => __builder => | ||
| { | ||
| var groupCol = _columnsById.GetValueOrDefault(group.ColumnId); | ||
| var collapsed = IsGroupCollapsed(group); | ||
| <div class="bit-dtg-group-row" role="row" style="--bit-dtg-group-level:@group.Level;"> | ||
| <div class="bit-dtg-group-cell" role="gridcell" style="padding-inline-start:@(8 + group.Level * 20)px;"> | ||
| <button type="button" class="bit-dtg-icon-btn" | ||
| aria-label="@($"{(collapsed ? "Expand" : "Collapse")} group {groupCol?.DisplayTitle}: {group.KeyText}")" | ||
| aria-expanded="@(collapsed ? "false" : "true")" | ||
| @onclick="() => ToggleGroup(group)"> | ||
| @(collapsed ? "▸" : "▾") | ||
| </button> | ||
| <strong>@(groupCol?.DisplayTitle): @group.KeyText</strong> | ||
| <span class="bit-dtg-group-count">(@group.Count)</span> | ||
| @foreach (var agg in group.Aggregates) | ||
| { | ||
| <span class="bit-dtg-group-agg">@(_columnsById.GetValueOrDefault(agg.ColumnId)?.DisplayTitle): @AggregateLabel(agg)</span> | ||
| } | ||
| </div> | ||
| </div> | ||
| @if (!collapsed) | ||
| { | ||
| while (rowIndex++ < initialRowIndex + Pagination.ItemsPerPage) | ||
| if (group.HasSubGroups) | ||
| { | ||
| <tr></tr> | ||
| @RenderGroupList(group.SubGroups) | ||
| } | ||
| else | ||
| { | ||
| foreach (var item in group.Items) | ||
| { | ||
| <BitDataGridRow TItem="TItem" Grid="this" Item="item" @key="GetKey(item)" /> | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| private void RenderRow(RenderTreeBuilder __builder, int rowIndex, TGridItem item) | ||
| // Renders a column filter editor whose input kind, operator and value type match the column's | ||
| // data type, so Number/Date/Boolean/Enum columns no longer filter as plain "contains" text. | ||
| private RenderFragment RenderFilterEditor(BitDataGridColumn<TItem> column) => __builder => | ||
| { | ||
| if (RowTemplate is null) | ||
| var current = GetFilter(column)?.Value; | ||
| var type = column.EffectiveDataType; | ||
| // Every filter control needs an accessible name so screen readers can identify which column | ||
| // it targets (placeholders and bare selects are not exposed as accessible names). | ||
| var filterLabel = $"Filter by {column.DisplayTitle}"; | ||
|
|
||
| if (type is BitDataGridColumnDataType.Number) | ||
| { | ||
| RenderOriginalRow(__builder, rowIndex, item); | ||
| <input class="bit-dtg-filter-input" type="number" placeholder="=" aria-label="@filterLabel" | ||
| value="@FormatFilterNumber(current)" | ||
| @onchange="e => SetTypedFilterAsync(column, (string?)e.Value)" /> | ||
| } | ||
| else if (type is BitDataGridColumnDataType.Date or BitDataGridColumnDataType.DateTime or BitDataGridColumnDataType.DateTimeOffset) | ||
| { | ||
| <input class="bit-dtg-filter-input" type="date" aria-label="@filterLabel" | ||
| value="@FormatFilterDate(current)" | ||
| @onchange="e => SetTypedFilterAsync(column, (string?)e.Value)" /> | ||
| } | ||
| else if (type is BitDataGridColumnDataType.Boolean) | ||
| { | ||
| <select class="bit-dtg-filter-input" aria-label="@filterLabel" value="@(current?.ToString()?.ToLowerInvariant())" | ||
| @onchange="e => SetTypedFilterAsync(column, (string?)e.Value)"> | ||
| <option value="">All</option> | ||
| <option value="true">True</option> | ||
| <option value="false">False</option> | ||
| </select> | ||
| } | ||
| else if (type is BitDataGridColumnDataType.Enum) | ||
| { | ||
| <select class="bit-dtg-filter-input" aria-label="@filterLabel" value="@(current?.ToString())" | ||
| @onchange="e => SetTypedFilterAsync(column, (string?)e.Value)"> | ||
| <option value="">All</option> | ||
| @foreach (var name in EnumNames(column)) | ||
| { | ||
| <option value="@name">@name</option> | ||
| } | ||
| </select> | ||
| } | ||
| else | ||
| { | ||
| var args = new BitDataGridRowTemplateArgs<TGridItem> | ||
| { | ||
| RowIndex = rowIndex, | ||
| RowItem = item, | ||
| OriginalRow = (builder) => RenderOriginalRow(builder, rowIndex, item) | ||
| }; | ||
| __builder.AddContent(0, RowTemplate(args)); | ||
| <input class="bit-dtg-filter-input" placeholder="Filter…" aria-label="@filterLabel" | ||
| value="@(current?.ToString())" | ||
| @onchange="e => SetFilterAsync(column, BitDataGridFilterOperator.Contains, (string?)e.Value)" /> | ||
| } | ||
| } | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify the affected render fragments are no longer authored as builder lambdas with inline Razor markup.
rg -n "Render(GroupList|Group|FilterEditor).*=> __builder =>" src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razorRepository: bitfoundation/bitplatform
Length of output: 462
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== File outline =="
ast-grep outline src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor --view expanded || true
echo
echo "== Nearby lines around the render fragments =="
sed -n '350,470p' src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor
echo
echo "== Other RenderFragment patterns in the repo =="
rg -n "=> @<|=> __builder =>|RenderFragment" src/BlazorUI -g '*.razor' -g '*.cs' | sed -n '1,220p'Repository: bitfoundation/bitplatform
Length of output: 43731
🌐 Web query:
Blazor Razor file RenderFragment builder lambda inline markup supported syntax __builder => {
💡 Result:
Yes, using a lambda with builder to define a RenderFragment is a supported syntax in Blazor, though it is considered a low-level, advanced approach [1][2]. In this syntax, the lambda parameter must be named exactly builder (of type RenderTreeBuilder) [3][2]. This name is a reserved identifier used by the Razor compiler's internal code generation process [3][4]. When you use this syntax, the body of the lambda is treated as a Razor code block, allowing you to write markup and C# logic directly [2]. ### Usage and Syntax The builder lambda approach is typically used when you need manual control over render tree construction within a C# method [1][5]. csharp private RenderFragment MyFragment => builder => { <div> <p>Inline markup is supported here.</p> `@if` (true) { <span>Conditional rendering works too.</span> } </div> }; ### Preferred Alternatives While the builder lambda syntax works, it is generally recommended to use the modern, simplified templated Razor syntax for readability [3][4]. The Razor compiler automatically handles the underlying RenderTreeBuilder logic when you use the @<...> notation [6][3]. For example, the following is functionally equivalent to the manual builder approach but is more idiomatic: csharp // Modern, idiomatic approach private RenderFragment MyFragment => @<div> <p>Inline markup is supported here.</p> </div>; ### Key Considerations 1. Mandatory Naming: If you choose to use the builder lambda syntax, the parameter must be named builder [2][7]. Changing it to any other name (e.g., builder) will result in a compilation error because the compiler specifically looks for that identifier to inject the rendering instructions [3][7]. 2. Code Block Behavior: Within the builder lambda, the content is treated as a Razor code block [2]. This means plain text must be explicitly prefixed with @: if it is not otherwise wrapped in an HTML element [2]. 3. Advanced Scenarios: If you require absolute control—such as conditional element creation, manual sequence number management, or complex logic that cannot be expressed easily in standard Razor—the manual builder approach remains the standard way to perform low-level render tree manipulation [1][5].
Citations:
- 1: https://learn.microsoft.com/en-us/aspnet/core/blazor/advanced-scenarios?view=aspnetcore-10.0
- 2: Better syntax for methods the return RenderFragment dotnet/razor#9959
- 3: https://stackoverflow.com/questions/70096198/blazor-return-renderfragment-builder-does-not-exist-in-the-current-context
- 4: Is using __builder in the examples a good idea? dotnet/AspNetCore.Docs#25822
- 5: https://learn.microsoft.com/en-us/aspnet/core/blazor/advanced-scenarios?view=aspnetcore-9.0
- 6: https://stackoverflow.com/questions/77477141/do-i-need-builder-in-a-renderfragment-definition
- 7: https://stackoverflow.com/questions/57839622/how-do-i-write-blazor-html-code-inside-the-code-block
🌐 Web query:
Blazor .razor file RenderFragment lambda parameter name __builder supported syntax
💡 Result:
In Blazor, the parameter name builder is required when you manually define a RenderFragment using a C# lambda expression that contains Razor markup [1][2][3]. This is because builder is the fixed name of the RenderTreeBuilder instance expected by the Razor compiler to emit rendering instructions [1][4][3]. However, relying on this builder syntax is generally considered an implementation detail or a hack [5]. Modern Blazor (since.NET 6+) provides a more elegant and recommended syntax for defining reusable RenderFragments that avoids the need to manually manage builder [1][6][7]. Recommended syntax using Razor templates: Instead of manually creating a lambda with builder, you can use the @ prefix followed by the markup. The Razor compiler will intelligently handle the transformation behind the scenes [1][6]: private RenderFragment MyFragment => @
Hello world!
; private RenderFragment MyTypedFragment => (name) => @Hello @name!
builder: 1. Required in manual lambdas: If you explicitly write a lambda that returns a RenderFragment and includes markup, the parameter must be named builder [2][4]. If you name it anything else, the compiler will be unable to inject the necessary rendering instructions, resulting in a "does not exist in the current context" error [1][3]. 2. Compiler implementation detail: The name builder is not part of a stable public API for manual consumption. It is specifically what the compiler looks for during the transpilation of.razor files [4][5]. 3. Risk of scope issues: Manually passing or accessing builder is error-prone, especially in nested components where the compiler may use different builder names (e.g., builder2, builder3) [5][8]. Using the native Razor template syntax avoids these scope-related risks [5]. For most use cases, you should prefer the template-based approach (@<...>) over the manual builder lambda approach [7][4].
Citations:
- 1: https://stackoverflow.com/questions/70096198/blazor-return-renderfragment-builder-does-not-exist-in-the-current-context
- 2: Better syntax for methods the return RenderFragment dotnet/razor#9959
- 3: https://stackoverflow.com/questions/62239194/what-is-causing-builder-does-not-exist-in-current-context-error-from-compiler
- 4: Is using __builder in the examples a good idea? dotnet/AspNetCore.Docs#25822
- 5: How to use BuildRenderTree() as a RenderFragment? dotnet/razor#10499
- 6: https://stackoverflow.com/questions/77477141/do-i-need-builder-in-a-renderfragment-definition
- 7: Update render fragment example dotnet/AspNetCore.Docs#30118
- 8: Clean syntax for Razor-emitting methods (avoiding __builder, _builder2, …) dotnet/aspnetcore#37907
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Exact occurrences in the target file =="
rg -n "__builder =>|=> @<|builder =>|RenderFragment" src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor
echo
echo "== Compare against known supported syntax in repo =="
rg -n "private RenderFragment .*=> @<|private RenderFragment<.*> .*=> @<|RenderFragment<.*>.*=> \(.*\) => @<|RenderFragment .*=> builder =>|RenderFragment .*=> __builder =>" src/BlazorUI -g '*.razor' -g '*.cs' | sed -n '1,220p'
echo
echo "== Search for compile-like use of __builder in .razor files =="
rg -n "__builder" src/BlazorUI -g '*.razor' -g '*.cs' | sed -n '1,200p'Repository: bitfoundation/bitplatform
Length of output: 3989
Use Razor template syntax for these render fragments. RenderGroupList, RenderGroup, and RenderFilterEditor should be rewritten as => @<...> templates or explicit RenderTreeBuilder code; the current __builder => form is not valid Razor source here and will break compilation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.razor`
around lines 374 - 466, RenderGroupList, RenderGroup, and RenderFilterEditor are
using invalid Razor render-fragment syntax with __builder =>, so they should be
rewritten as proper Razor templates using => @<...> or as explicit
RenderTreeBuilder code. Update the existing BitDataGrid.razor helpers (including
the RenderGroup and RenderFilterEditor methods) so the markup is emitted through
valid Razor source and compiles correctly.
| .bit-dtg-cell[tabindex]:focus { | ||
| outline: 2px solid var(--bit-clr-pri); | ||
| outline-offset: -2px; | ||
| z-index: 1; | ||
| } | ||
|
|
||
| .bit-dtg-cell[tabindex]:focus-visible { | ||
| outline: 2px solid var(--bit-clr-pri); | ||
| outline-offset: -2px; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Keep the focus ring visible on selected cells.
Selected cells use var(--bit-clr-pri) as their background, and the focus outline uses the same color, so keyboard focus can disappear on selected rows.
Proposed fix
.bit-dtg-cell[tabindex]:focus-visible {
outline: 2px solid var(--bit-clr-pri);
outline-offset: -2px;
z-index: 1;
}
+
+.bit-dtg-row.bit-dtg-selected .bit-dtg-cell[tabindex]:focus,
+.bit-dtg-row.bit-dtg-selected .bit-dtg-cell[tabindex]:focus-visible {
+ outline-color: var(--bit-clr-pri-text);
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .bit-dtg-cell[tabindex]:focus { | |
| outline: 2px solid var(--bit-clr-pri); | |
| outline-offset: -2px; | |
| z-index: 1; | |
| } | |
| .bit-dtg-cell[tabindex]:focus-visible { | |
| outline: 2px solid var(--bit-clr-pri); | |
| outline-offset: -2px; | |
| .bit-dtg-cell[tabindex]:focus { | |
| outline: 2px solid var(--bit-clr-pri); | |
| outline-offset: -2px; | |
| z-index: 1; | |
| } | |
| .bit-dtg-cell[tabindex]:focus-visible { | |
| outline: 2px solid var(--bit-clr-pri); | |
| outline-offset: -2px; | |
| } | |
| .bit-dtg-row.bit-dtg-selected .bit-dtg-cell[tabindex]:focus, | |
| .bit-dtg-row.bit-dtg-selected .bit-dtg-cell[tabindex]:focus-visible { | |
| outline-color: var(--bit-clr-pri-text); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGrid.scss` around
lines 362 - 370, The focus styling in BitDataGrid.scss for
.bit-dtg-cell[tabindex]:focus and :focus-visible uses the same primary color as
selected cell backgrounds, so keyboard focus can become invisible. Update the
focus ring styling in this cell selector block to use a contrasting color or
alternate focus treatment when a cell is selected, and keep the focus indicator
clearly visible for selected rows and cells.
| <select class="bit-dtg-editor bit-dtg-editor-tristate" value="@(GetBoolString())" | ||
| @onchange="e => SetNullable(e.Value)"> | ||
| <option value="">@string.Empty</option> | ||
| <option value="true">True</option> | ||
| <option value="false">False</option> | ||
| </select> | ||
| break; | ||
|
|
||
| case BitDataGridColumnDataType.Boolean: | ||
| <input type="checkbox" class="bit-dtg-editor bit-dtg-editor-check" | ||
| checked="@(GetBool())" | ||
| @onchange="e => Set(e.Value)" /> | ||
| break; | ||
|
|
||
| case BitDataGridColumnDataType.Number: | ||
| <input type="number" class="bit-dtg-editor" step="any" | ||
| value="@(GetNumberString())" | ||
| @oninput="e => SetNullable(e.Value)" /> | ||
| break; | ||
|
|
||
| case BitDataGridColumnDataType.Date: | ||
| <input type="date" class="bit-dtg-editor" | ||
| value="@(GetDate())" | ||
| @onchange="e => SetNullable(e.Value)" /> | ||
| break; | ||
|
|
||
| case BitDataGridColumnDataType.DateTime: | ||
| <input type="datetime-local" class="bit-dtg-editor" | ||
| value="@(GetDateTime())" | ||
| @onchange="e => SetDateTime(e.Value)" /> | ||
| break; | ||
|
|
||
| case BitDataGridColumnDataType.DateTimeOffset: | ||
| <input type="datetime-local" class="bit-dtg-editor" | ||
| value="@(GetDateTime())" | ||
| @onchange="e => SetDateTimeOffset(e.Value)" /> | ||
| break; | ||
|
|
||
| case BitDataGridColumnDataType.Enum when Column.Accessor is not null && Column.Accessor.UnderlyingType.IsEnum: | ||
| <select class="bit-dtg-editor" value="@(GetString())" | ||
| @onchange="e => Set(string.IsNullOrEmpty(e.Value as string) ? null : e.Value)"> | ||
| @if (IsNullableEnum || Value is null) | ||
| { | ||
| <option value="">@string.Empty</option> | ||
| } | ||
| @foreach (var name in Enum.GetNames(Column.Accessor.UnderlyingType)) | ||
| { | ||
| <option value="@name">@name</option> | ||
| } | ||
| </select> | ||
| break; | ||
|
|
||
| default: | ||
| <input type="text" class="bit-dtg-editor" | ||
| value="@(GetString())" | ||
| @oninput="e => Set(e.Value)" /> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Give inline editor controls accessible names.
These inputs/selects focus directly but don’t expose the column name. Add an aria-label such as Edit @Column.DisplayTitle`` to each built-in editor control.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridCellEditor.razor`
around lines 10 - 65, The built-in editors in BitDataGridCellEditor.razor
currently have no accessible name, so screen readers can’t identify the column
being edited. Update each editor branch in the switch (select/input for Boolean,
Number, Date, DateTime, DateTimeOffset, Enum, and default text) to include an
aria-label based on the column title, using Column.DisplayTitle in the label
text. Keep the change localized to these editor controls so focusable elements
announce the correct field name.
| Grid.AddColumn(this); | ||
| _registeredId = Id; | ||
| SnapshotSemanticParameters(); | ||
| } | ||
|
|
||
| protected override void OnParametersSet() | ||
| { | ||
| if (HasField) | ||
| Accessor = BitDataGridPropertyAccessor<TItem>.For(Field!); | ||
| else | ||
| Accessor = null; | ||
|
|
||
| // ColumnId/Field are mutable parameters, so the resolved Id may have changed since the column | ||
| // was registered. Re-register under the new id (migrating any active descriptors) so grid | ||
| // lookups by id keep finding this column. | ||
| if (_registeredId is not null && _registeredId != Id) | ||
| { | ||
| Grid?.UpdateColumnRegistration(this, _registeredId); | ||
| _registeredId = Id; |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Don’t mark skipped duplicate columns as registered.
Grid.AddColumn(this) can return without adding the column when the ID is already taken, but Line 150 still sets _registeredId. If that skipped column later changes to a unique ColumnId/Field, UpdateColumnRegistration ignores it because it is not in _columns, so it never appears in the grid. Make registration success explicit, or retry AddColumn when _registeredId is null.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/BitDataGridColumn.cs`
around lines 149 - 167, `BitDataGridColumn<TItem>.OnParametersSet` currently
treats every `Grid.AddColumn(this)` call as a successful registration by setting
`_registeredId`, even when the grid rejects a duplicate id. Update the
registration flow so `_registeredId` is only assigned when `AddColumn` actually
adds the column, or retry `Grid.AddColumn(this)` when `_registeredId` is null
after a duplicate is skipped. Keep the re-registration logic in
`UpdateColumnRegistration` dependent on a real prior registration so skipped
duplicate columns can be added later when `Id`/`Field` becomes unique.
| var grouped = source | ||
| .GroupBy(item => column.Accessor!.GetValue(item)) | ||
| .Select(g => |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Align grouping equality with the grid’s comparison rules.
GroupBy is still using the default EqualityComparer<object?>, so string keys like "US" and "us" split into separate groups even though BitDataGridValueComparer and the Equals filter path treat them as equal. That makes grouping disagree with sorting/filtering on the same column.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/DataGrid/Infrastructure/BitDataGridDataProcessor.cs`
around lines 83 - 85, Update the grouping logic in BitDataGridDataProcessor so
it uses the same comparison semantics as the grid’s existing
BitDataGridValueComparer and Equals-based filtering path. The GroupBy call on
column.Accessor!.GetValue(item) is currently relying on default object equality,
so adjust the grouping key comparison to use the grid’s comparer for that
column, keeping grouping behavior consistent with sorting and filtering for
values like strings.
| /// </summary> | ||
| /// <typeparam name="T">The type of data represented by each row in the grid.</typeparam> | ||
| public class BitDataGridRowTemplateArgs<T> | ||
| public class BitQuickGridRowTemplateArgs<T> |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Preserve the old row-template args type for one release.
Line 7 moves the public RowTemplate contract to BitQuickGridRowTemplateArgs<T>, so existing consumers compiled against BitDataGridRowTemplateArgs<T> will break immediately. Please keep an [Obsolete] forwarding type, or ship this with explicit breaking-change notes and migration guidance.
Suggested compatibility patch
public class BitQuickGridRowTemplateArgs<T>
{
/// <summary>
/// A render fragment that produces the original row markup (the default <c><tr></c> with all column cells).
@@
public T RowItem { get; set; } = default!;
}
+
+[Obsolete("Use BitQuickGridRowTemplateArgs<T> instead.")]
+public class BitDataGridRowTemplateArgs<T> : BitQuickGridRowTemplateArgs<T>
+{
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public class BitQuickGridRowTemplateArgs<T> | |
| [Obsolete("Use BitQuickGridRowTemplateArgs<T> instead.")] | |
| public class BitDataGridRowTemplateArgs<T> : BitQuickGridRowTemplateArgs<T> | |
| { | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/BitQuickGridRowTemplateArgs.cs`
at line 7, The public row-template args type was renamed from
BitDataGridRowTemplateArgs<T> to BitQuickGridRowTemplateArgs<T>, which breaks
existing consumers immediately. Keep BitDataGridRowTemplateArgs<T> available as
an [Obsolete] forwarding/alias type that maps to BitQuickGridRowTemplateArgs<T>,
so older compiled code continues to work for one release. Update the QuickGrid
row-template contract carefully and preserve compatibility in the affected type
definition.
| public override Task SetParametersAsync(ParameterView parameters) | ||
| { | ||
| // Track whether Title was supplied explicitly by the consumer in *this* render's ParameterView | ||
| // rather than inferring intent from value equality (which can't tell an auto-derived header apart | ||
| // from an explicit one matching the member name). Recompute it every render instead of latching: | ||
| // if a consumer later removes Title, explicitness must drop back to false so the auto-generated | ||
| // header can return. | ||
| _titleWasExplicitlySet = parameters.TryGetValue<string?>(nameof(Title), out _); | ||
|
|
||
| return base.SetParametersAsync(parameters); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Clear the old explicit Title when the parameter is removed.
If a parent supplies Title once and later omits it, base.SetParametersAsync leaves the previous value in place. Member-expression properties overwrite it at Line 99, but method/cast expressions keep the stale header forever because Lines 102-106 only clear auto-generated titles.
💡 Suggested fix
public override Task SetParametersAsync(ParameterView parameters)
{
- _titleWasExplicitlySet = parameters.TryGetValue<string?>(nameof(Title), out _);
+ var titleWasSupplied = parameters.TryGetValue<string?>(nameof(Title), out _);
+ if (!titleWasSupplied && !_titleIsAutoGenerated)
+ {
+ Title = null;
+ }
+ _titleWasExplicitlySet = titleWasSupplied;
return base.SetParametersAsync(parameters);
}Also applies to: 88-106
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/Columns/BitQuickGridPropertyColumn.cs`
around lines 35 - 44, The Title parameter handling in
BitQuickGridPropertyColumn.SetParametersAsync needs to clear stale explicit
values when the parent stops passing Title. Update the parameter flow so that
when parameters no longer contain Title, the component resets the stored Title
before/around base.SetParametersAsync, and adjust the auto-title logic in the
property-column expression handling so only member-expression headers are
overwritten while method/cast expressions can also fall back to the generated
title. Use the existing _titleWasExplicitlySet flag and the
Title/SetParametersAsync path to locate the fix.
| /// A callback that provides data for a <see cref="BitQuickGrid{TGridItem}"/>. | ||
| /// </summary> | ||
| /// <typeparam name="TGridItem">The type of data represented by each row in the grid.</typeparam> | ||
| /// <param name="request">Parameters describing the data being requested.</param> | ||
| /// <returns>A <see cref="ValueTask{TResult}"/> (specifically <c>ValueTask<BitQuickGridItemsProviderResult<TGridItem>></c>) whose result is a <see cref="BitQuickGridItemsProviderResult{TGridItem}"/> that gives the data to be displayed.</returns> | ||
| public delegate ValueTask<BitQuickGridItemsProviderResult<TGridItem>> BitQuickGridItemsProvider<TGridItem>(BitQuickGridItemsProviderRequest<TGridItem> request); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Keep obsolete shims for the renamed items-provider contracts.
This public delegate rename, together with the renamed request/result types in this cohort, breaks every existing BitDataGrid* ItemsProvider signature in downstream apps. Please keep [Obsolete] forwarders for the old names so consumers can migrate without an immediate compile break.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Bit.BlazorUI.Extras/Components/QuickGrid/ItemsProvider/BitQuickGridItemsProvider.cs`
around lines 4 - 9, The renamed items-provider contracts introduce a breaking
API change for existing BitDataGrid consumers. Keep backward-compatible obsolete
forwarders for the old delegate and request/result type names by adding
[Obsolete] aliases/shims that delegate to the new BitQuickGrid* symbols, so
downstream apps can migrate without compile breaks. Make sure the existing
public contract around BitQuickGridItemsProvider and its request/result types
remains the new implementation target while the old BitDataGrid* names stay
available for compatibility.
| private const string FileSystemDataCode = @" | ||
|
|
||
| public class FoodRecallQueryResult | ||
| public class FileNode | ||
| { | ||
| [JsonPropertyName(""meta"")] | ||
| public Meta? Meta { get; set; } | ||
|
|
||
| [JsonPropertyName(""results"")] | ||
| public List<FoodRecall>? Results { get; set; } | ||
| public int Id { get; set; } | ||
| public string Name { get; set; } = """"; | ||
| public string Kind { get; set; } = ""Folder""; | ||
| public long Size { get; set; } | ||
| public DateTime Modified { get; set; } | ||
| public List<FileNode> Children { get; set; } = new(); | ||
| } | ||
|
|
||
| public class Meta | ||
| public static class FileSystemData | ||
| { | ||
| [JsonPropertyName(""disclaimer"")] | ||
| public string? Disclaimer { get; set; } | ||
| public static List<FileNode> Build() | ||
| { | ||
| var id = 0; | ||
| var baseDate = new DateTime(2025, 1, 1); | ||
|
|
||
| [JsonPropertyName(""terms"")] | ||
| public string? Terms { get; set; } | ||
| FileNode Folder(string name, params FileNode[] children) | ||
| { | ||
| var node = new FileNode { Id = ++id, Name = name, Kind = ""Folder"", Modified = baseDate.AddDays(id), Children = children.ToList() }; | ||
| node.Size = node.Children.Sum(c => c.Size); | ||
| return node; | ||
| } | ||
|
|
||
| [JsonPropertyName(""license"")] | ||
| public string? License { get; set; } | ||
| FileNode File(string name, long size) => new() { Id = ++id, Name = name, Kind = ""File"", Size = size, Modified = baseDate.AddDays(id) }; | ||
|
|
||
| [JsonPropertyName(""last_updated"")] | ||
| public string? LastUpdated { get; set; } | ||
| return new List<FileNode> | ||
| { | ||
| Folder(""src"", | ||
| Folder(""BitDataGrid"", | ||
| File(""BitDataGrid.razor"", 24_500), | ||
| File(""BitDataGrid.razor.cs"", 41_200), | ||
| Folder(""Models"", | ||
| File(""BitDataGridColumnAlign.cs"", 320), | ||
| File(""BitDataGridSortDescriptor.cs"", 540)))), | ||
| Folder(""docs"", | ||
| File(""README.md"", 6_400), | ||
| File(""CHANGELOG.md"", 2_100)), | ||
| File(""LICENSE"", 1_070), | ||
| File("".gitignore"", 410) | ||
| }; | ||
| } | ||
| }"; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Keep the tree-data snippet aligned with the live helper.
example13CsharpCode appends this embedded FileSystemDataCode, but it no longer matches src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/FileSystemData.cs: the snippet is missing the Infrastructure, BitDataGrid.Demo, and assets branches plus an extra model file. The demo page will show a tree users cannot reproduce from the published sample.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/DataGrid/BitDataGridDemo.razor.samples.cs`
around lines 102 - 146, The embedded FileSystemDataCode snippet is out of sync
with the live FileSystemData.Build helper, so update the string in
BitDataGridDemo to match the current tree shape. Add the missing branches and
file entries from FileSystemData.Build, including Infrastructure,
BitDataGrid.Demo, assets, and the extra model file, and keep the Folder/File
local helpers and resulting hierarchy identical so example13CsharpCode reflects
the reproducible demo data.
| if (string.IsNullOrEmpty(_odataSampleNameFilter) is false) | ||
| { | ||
| query.Add(""$filter"", $""contains(Name,'{_odataSampleNameFilter.Replace(""'"", ""''"")}')""); | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Treat whitespace-only OData filters as empty in the sample.
Line 741 still uses IsNullOrEmpty and forwards the untrimmed value, so copying this sample reintroduces the broken contains(Name,' ') query that the runtime demo already fixed.
Proposed fix
- if (string.IsNullOrEmpty(_odataSampleNameFilter) is false)
+ var nameFilter = _odataSampleNameFilter?.Trim();
+ if (string.IsNullOrWhiteSpace(nameFilter) is false)
{
- query.Add(""$filter"", $""contains(Name,'{_odataSampleNameFilter.Replace(""'"", ""''"")}')"");
+ var escapedFilter = nameFilter.Replace(""'"", ""''"");
+ query.Add(""$filter"", $""contains(Name,'{escapedFilter}')"");
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (string.IsNullOrEmpty(_odataSampleNameFilter) is false) | |
| { | |
| query.Add(""$filter"", $""contains(Name,'{_odataSampleNameFilter.Replace(""'"", ""''"")}')""); | |
| } | |
| var nameFilter = _odataSampleNameFilter?.Trim(); | |
| if (string.IsNullOrWhiteSpace(nameFilter) is false) | |
| { | |
| var escapedFilter = nameFilter.Replace(""'"", ""''""); | |
| query.Add(""$filter"", $""contains(Name,'{escapedFilter}')""); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Extras/QuickGrid/BitQuickGridDemo.razor.samples.cs`
around lines 741 - 744, The QuickGrid OData sample still treats whitespace-only
input as a valid filter and passes the untrimmed value into the $filter query,
which can generate a broken contains(Name,' ') expression. Update the
condition in the sample method that builds the OData query (the block using
_odataSampleNameFilter and query.Add) so it treats whitespace-only values as
empty, and ensure the emitted filter uses the trimmed value rather than the raw
string.
closes #12502
Summary by CodeRabbit