Skip to content

Commit e8e25d5

Browse files
committed
fix initial query bug
1 parent dab1a55 commit e8e25d5

File tree

5 files changed

+91
-34
lines changed

5 files changed

+91
-34
lines changed

src/LoreSoft.Blazor.Controls/Data/DataComponentBase.cs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public abstract class DataComponentBase<TItem> : ComponentBase, IDisposable
2222
private IEnumerable<TItem>? _data;
2323
private bool _isLoading;
2424
private DataSort? _currentSort;
25+
private QueryGroup? _initialQuery;
2526

2627
/// <summary>
2728
/// Gets or sets the JavaScript runtime for interop calls.
@@ -157,12 +158,18 @@ public abstract class DataComponentBase<TItem> : ComponentBase, IDisposable
157158
[Parameter]
158159
public QueryGroup? Query { get; set; }
159160

161+
/// <summary>
162+
/// Event triggered when the data grid is initialized.
163+
/// </summary>
164+
[Parameter]
165+
public EventCallback<DataGrid<TItem>> Initialized { get; set; }
166+
160167
/// <summary>
161168
/// Gets the root query group for filtering and searching.
162169
/// This is the primary filter container that holds all active filters and query groups.
163170
/// It's automatically managed by the component's filter operations but can be accessed for advanced scenarios.
164171
/// </summary>
165-
public QueryGroup RootQuery { get; private set; } = new();
172+
public QueryGroup RootQuery { get; } = new();
166173

167174
/// <summary>
168175
/// Gets or sets a value indicating whether the component is currently loading data.
@@ -295,18 +302,22 @@ public async Task ClearFilters()
295302
/// This method allows programmatic application of filters without user interaction with the filter UI.
296303
/// </summary>
297304
/// <param name="rules">The collection of filter rules to apply. Each rule defines a specific filter condition.</param>
298-
/// <param name="replace">When true, existing filters are cleared before applying new rules.
299-
/// When false, new rules are added to existing filters.</param>
305+
/// <param name="replace">
306+
/// When true, existing filters are cleared before applying new rules.
307+
/// When false, new rules are added to existing filters.
308+
/// </param>
309+
/// <param name="refresh">Whether to refresh the data display after applying the filter.</param>
300310
/// <returns>A task representing the asynchronous filter application and data refresh operation.</returns>
301-
public async Task ApplyFilters(IEnumerable<QueryRule> rules, bool replace = false)
311+
public async Task ApplyFilters(IEnumerable<QueryRule> rules, bool replace = false, bool refresh = true)
302312
{
303313
if (replace)
304314
RootQuery.Filters.Clear();
305315

306316
if (rules != null)
307317
RootQuery.Filters.AddRange(rules);
308318

309-
await RefreshAsync(true);
319+
if (refresh)
320+
await RefreshAsync(true);
310321
}
311322

312323
/// <summary>
@@ -315,8 +326,9 @@ public async Task ApplyFilters(IEnumerable<QueryRule> rules, bool replace = fals
315326
/// This allows for easy updates to existing filters without duplicating filter conditions.
316327
/// </summary>
317328
/// <param name="rule">The filter rule to apply. If null, no action is taken.</param>
329+
/// <param name="refresh">Whether to refresh the data display after applying the filter.</param>
318330
/// <returns>A task representing the asynchronous filter application and data refresh operation.</returns>
319-
public async Task ApplyFilter(QueryRule rule)
331+
public async Task ApplyFilter(QueryRule? rule, bool refresh = true)
320332
{
321333
if (rule == null)
322334
return;
@@ -325,7 +337,9 @@ public async Task ApplyFilter(QueryRule rule)
325337
RootQuery.Filters.RemoveAll(f => f.Id == rule.Id);
326338

327339
RootQuery.Filters.Add(rule);
328-
await RefreshAsync(true);
340+
341+
if (refresh)
342+
await RefreshAsync(true);
329343
}
330344

331345
/// <summary>
@@ -400,6 +414,12 @@ protected override void OnInitialized()
400414
/// <inheritdoc />
401415
protected override async Task OnParametersSetAsync()
402416
{
417+
if (_initialQuery != Query)
418+
{
419+
await ApplyFilter(Query, false);
420+
_initialQuery = Query;
421+
}
422+
403423
if (DataProvider != null)
404424
{
405425
if (Data != null || DataLoader != null)
@@ -439,6 +459,9 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
439459
if (!firstRender)
440460
return;
441461

462+
// notify initialized
463+
await Initialized.InvokeAsync((DataGrid<TItem>)this);
464+
442465
// re-render due to columns being added
443466
await RefreshAsync();
444467
}
@@ -626,7 +649,7 @@ protected virtual IQueryable<TItem> SortData(IQueryable<TItem> queryable, DataRe
626649
if (!Sortable || request.Sorts == null || request.Sorts.Length == 0)
627650
return queryable;
628651

629-
return queryable.Sort(request.Sorts);
652+
return queryable.Sort(request.Sorts);
630653
}
631654

632655
/// <summary>

src/LoreSoft.Blazor.Controls/Data/DataGrid.razor.cs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public partial class DataGrid<TItem> : DataComponentBase<TItem>
2323
private readonly HashSet<TItem> _expandedItems = [];
2424
private readonly HashSet<string> _expandedGroups = [];
2525

26-
private QueryGroup? _initialQuery;
2726
private BreakpointProvider? _breakpointProvider;
2827

2928
/// <summary>
@@ -345,24 +344,6 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
345344
await base.OnAfterRenderAsync(firstRender);
346345
}
347346

348-
/// <inheritdoc />
349-
protected override void OnParametersSet()
350-
{
351-
base.OnParametersSet();
352-
353-
// only update RootQuery if Query changed
354-
if (_initialQuery != Query)
355-
{
356-
_initialQuery = Query;
357-
// RootQuery is managed by the base class, we can only access it if it exists
358-
if (Query != null)
359-
{
360-
// The base class handles RootQuery initialization and management
361-
// We just track the initial query for change detection
362-
}
363-
}
364-
}
365-
366347
/// <inheritdoc />
367348
protected override void OnInitialized()
368349
{

src/LoreSoft.Blazor.Controls/Query/QueryFilter.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace LoreSoft.Blazor.Controls;
66
/// Represents a single filter condition for a query in a data-bound component.
77
/// Inherits from <see cref="QueryRule"/> and specifies the field, operator, and value for filtering.
88
/// </summary>
9-
public class QueryFilter : QueryRule
9+
public class QueryFilter : QueryRule, IEquatable<QueryFilter?>
1010
{
1111
/// <summary>
1212
/// Gets or sets the name of the field to filter on.
@@ -26,4 +26,25 @@ public class QueryFilter : QueryRule
2626
/// </summary>
2727
[JsonPropertyName("value")]
2828
public object? Value { get; set; }
29+
30+
/// <inheritdoc/>
31+
public override bool Equals(object? obj)
32+
{
33+
return Equals(obj as QueryFilter);
34+
}
35+
36+
/// <inheritdoc/>
37+
public bool Equals(QueryFilter? other)
38+
{
39+
return other is not null &&
40+
Field == other.Field &&
41+
Operator == other.Operator &&
42+
EqualityComparer<object?>.Default.Equals(Value, other.Value);
43+
}
44+
45+
/// <inheritdoc/>
46+
public override int GetHashCode()
47+
{
48+
return HashCode.Combine(Field, Operator, Value);
49+
}
2950
}

src/LoreSoft.Blazor.Controls/Query/QueryGroup.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace LoreSoft.Blazor.Controls;
77
/// A group can contain multiple filters and/or subgroups, combined using a logical operator (AND/OR).
88
/// Inherits from <see cref="QueryRule"/>.
99
/// </summary>
10-
public class QueryGroup : QueryRule
10+
public class QueryGroup : QueryRule, IEquatable<QueryGroup?>
1111
{
1212
/// <summary>
1313
/// Gets or sets the logical operator used to combine the filters in this group.
@@ -22,4 +22,29 @@ public class QueryGroup : QueryRule
2222
/// </summary>
2323
[JsonPropertyName("filters")]
2424
public List<QueryRule> Filters { get; set; } = [];
25+
26+
/// <inheritdoc/>
27+
public override bool Equals(object? obj)
28+
{
29+
return Equals(obj as QueryGroup);
30+
}
31+
32+
/// <inheritdoc/>
33+
public bool Equals(QueryGroup? other)
34+
{
35+
return other is not null &&
36+
Logic == other.Logic &&
37+
Filters.SequenceEqual(other.Filters);
38+
}
39+
40+
/// <inheritdoc/>
41+
public override int GetHashCode()
42+
{
43+
var hash = new HashCode();
44+
hash.Add(Logic);
45+
foreach (var filter in Filters)
46+
hash.Add(filter);
47+
48+
return hash.ToHashCode();
49+
}
2550
}

test/LoreSoft.Blazor.Controls.Tests/Snapshots/PublicApiTest.PublicApiHasNotChanged.verified.txt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ namespace LoreSoft.Blazor.Controls
259259
protected bool FilterOpen { get; }
260260
[Microsoft.AspNetCore.Components.Parameter]
261261
public bool Filterable { get; set; }
262+
[Microsoft.AspNetCore.Components.Parameter]
263+
public Microsoft.AspNetCore.Components.EventCallback<LoreSoft.Blazor.Controls.DataGrid<TItem>> Initialized { get; set; }
262264
public bool IsLoading { get; set; }
263265
[Microsoft.AspNetCore.Components.Inject]
264266
public required Microsoft.JSInterop.IJSRuntime JavaScript { get; set; }
@@ -277,9 +279,9 @@ namespace LoreSoft.Blazor.Controls
277279
public int VirtualOverscan { get; set; }
278280
[Microsoft.AspNetCore.Components.Parameter]
279281
public bool Virtualize { get; set; }
280-
public System.Threading.Tasks.Task ApplyFilter(LoreSoft.Blazor.Controls.QueryRule rule) { }
282+
public System.Threading.Tasks.Task ApplyFilter(LoreSoft.Blazor.Controls.QueryRule? rule, bool refresh = true) { }
281283
protected System.Threading.Tasks.Task ApplyFilters() { }
282-
public System.Threading.Tasks.Task ApplyFilters(System.Collections.Generic.IEnumerable<LoreSoft.Blazor.Controls.QueryRule> rules, bool replace = false) { }
284+
public System.Threading.Tasks.Task ApplyFilters(System.Collections.Generic.IEnumerable<LoreSoft.Blazor.Controls.QueryRule> rules, bool replace = false, bool refresh = true) { }
283285
public System.Threading.Tasks.Task ClearFilters() { }
284286
public void CloseFilter() { }
285287
public virtual LoreSoft.Blazor.Controls.DataRequest CreateDataRequest(System.Threading.CancellationToken cancellationToken = default) { }
@@ -392,7 +394,6 @@ namespace LoreSoft.Blazor.Controls
392394
protected bool IsRowSelected(TItem item) { }
393395
protected override System.Threading.Tasks.Task OnAfterRenderAsync(bool firstRender) { }
394396
protected override void OnInitialized() { }
395-
protected override void OnParametersSet() { }
396397
public System.Threading.Tasks.Task QuickSearch(string? searchText, bool clearFilter = false) { }
397398
public override System.Threading.Tasks.Task RefreshAsync(bool resetPager = false, bool forceReload = false) { }
398399
protected void SelectAll() { }
@@ -1108,7 +1109,7 @@ namespace LoreSoft.Blazor.Controls
11081109
protected override void OnParametersSet() { }
11091110
public void Refresh() { }
11101111
}
1111-
public class QueryFilter : LoreSoft.Blazor.Controls.QueryRule
1112+
public class QueryFilter : LoreSoft.Blazor.Controls.QueryRule, System.IEquatable<LoreSoft.Blazor.Controls.QueryFilter?>
11121113
{
11131114
public QueryFilter() { }
11141115
[System.Text.Json.Serialization.JsonPropertyName("field")]
@@ -1117,14 +1118,20 @@ namespace LoreSoft.Blazor.Controls
11171118
public string? Operator { get; set; }
11181119
[System.Text.Json.Serialization.JsonPropertyName("value")]
11191120
public object? Value { get; set; }
1121+
public bool Equals(LoreSoft.Blazor.Controls.QueryFilter? other) { }
1122+
public override bool Equals(object? obj) { }
1123+
public override int GetHashCode() { }
11201124
}
1121-
public class QueryGroup : LoreSoft.Blazor.Controls.QueryRule
1125+
public class QueryGroup : LoreSoft.Blazor.Controls.QueryRule, System.IEquatable<LoreSoft.Blazor.Controls.QueryGroup?>
11221126
{
11231127
public QueryGroup() { }
11241128
[System.Text.Json.Serialization.JsonPropertyName("filters")]
11251129
public System.Collections.Generic.List<LoreSoft.Blazor.Controls.QueryRule> Filters { get; set; }
11261130
[System.Text.Json.Serialization.JsonPropertyName("logic")]
11271131
public string? Logic { get; set; }
1132+
public bool Equals(LoreSoft.Blazor.Controls.QueryGroup? other) { }
1133+
public override bool Equals(object? obj) { }
1134+
public override int GetHashCode() { }
11281135
}
11291136
public static class QueryLogic
11301137
{

0 commit comments

Comments
 (0)