-
-
- @foreach (var item in GetItems())
- {
-
-
-
- }
+@if (IsHeaderRow)
+{
+
+}
+else
+{
+
+ @if (ShowSearch)
+ {
+
+ }
+
+
+
+ @foreach (var item in GetItems())
+ {
+
+
+
+ }
+
+ @if (_source == null)
+ {
+
+ @if (LoadingTemplate != null)
+ {
+ @LoadingTemplate
+ }
+ else
+ {
+
+ }
+
+ }
- @if (_source == null)
- {
-
- @if (LoadingTemplate != null)
- {
- @LoadingTemplate
- }
- else
- {
-
- }
-
- }
-
+}
diff --git a/src/BootstrapBlazor/Components/Filters/MultiFilter.razor.cs b/src/BootstrapBlazor/Components/Filters/MultiFilter.razor.cs
index 9b0af82c035..6062bc8ed4a 100644
--- a/src/BootstrapBlazor/Components/Filters/MultiFilter.razor.cs
+++ b/src/BootstrapBlazor/Components/Filters/MultiFilter.razor.cs
@@ -6,7 +6,7 @@
namespace BootstrapBlazor.Components;
///
-/// 表格过滤菜单组件
+/// 多选过滤器组件
///
public partial class MultiFilter
{
@@ -53,23 +53,14 @@ public partial class MultiFilter
public StringComparison StringComparison { get; set; } = StringComparison.OrdinalIgnoreCase;
private string? _searchText;
-
private List
? _source;
-
private List? _items;
///
- ///
+ /// Gets or sets the filter candidate items. It is recommended to use static data to avoid performance loss.
///
- protected override void OnInitialized()
- {
- base.OnInitialized();
-
- if (TableFilter != null)
- {
- TableFilter.ShowMoreButton = false;
- }
- }
+ [Parameter]
+ public IEnumerable? Items { get; set; }
///
///
@@ -89,7 +80,7 @@ protected override void OnParametersSet()
if (Items != null)
{
var selectedItems = _source?.Where(x => x.Active).ToList();
- _source = Items.ToList();
+ _source = [.. Items];
ResetActiveItems(_source, selectedItems);
}
}
@@ -117,45 +108,13 @@ protected override async Task InvokeInitAsync()
{
if (OnGetItemsAsync != null)
{
- await InvokeVoidAsync("init", Id, new { Invoker = Interop, Callback = nameof(TriggerGetItemsCallback), AlwaysTrigger = AlwaysTriggerGetItems });
- }
- }
-
- ///
- /// 重置过滤条件方法
- ///
- public override void Reset()
- {
- _searchText = string.Empty;
- if (_source != null)
- {
- foreach (var item in _source)
- {
- item.Active = false;
- }
- }
- _items = null;
- StateHasChanged();
- }
-
- ///
- /// 生成过滤条件方法
- ///
- ///
- public override FilterKeyValueAction GetFilterConditions()
- {
- var filter = new FilterKeyValueAction() { Filters = [], FilterLogic = FilterLogic.Or };
-
- foreach (var item in GetItems().Where(i => i.Active))
- {
- filter.Filters.Add(new FilterKeyValueAction()
+ await InvokeVoidAsync("init", Id, new
{
- FieldKey = FieldKey,
- FieldValue = item.Value,
- FilterAction = FilterAction.Equal
+ Invoker = Interop,
+ Callback = nameof(TriggerGetItemsCallback),
+ AlwaysTrigger = AlwaysTriggerGetItems
});
}
- return filter;
}
///
@@ -244,4 +203,63 @@ private Task OnSearchValueChanged(string? val)
}
private List GetItems() => _items ?? _source ?? [];
+
+ ///
+ /// 重置过滤条件方法
+ ///
+ public override void Reset()
+ {
+ _searchText = null;
+ if (_source != null)
+ {
+ foreach (var item in _source)
+ {
+ item.Active = false;
+ }
+ }
+ _items = null;
+ StateHasChanged();
+ }
+
+ ///
+ /// 生成过滤条件方法
+ ///
+ ///
+ public override FilterKeyValueAction GetFilterConditions()
+ {
+ var filter = new FilterKeyValueAction { FilterLogic = FilterLogic.Or };
+ foreach (var item in GetItems().Where(i => i.Active))
+ {
+ filter.Filters.Add(new FilterKeyValueAction
+ {
+ FieldKey = FieldKey,
+ FieldValue = item.Value,
+ FilterAction = FilterAction.Equal
+ });
+ }
+ return filter;
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override async Task SetFilterConditionsAsync(FilterKeyValueAction filter)
+ {
+ var items = GetItems();
+ if (items.Count > 0)
+ {
+ foreach (var f in filter.Filters)
+ {
+ var val = f.FieldValue?.ToString();
+ var item = items.Find(i => i.Value == val);
+ if (item != null)
+ {
+ item.Active = true;
+ }
+ }
+ }
+ await base.SetFilterConditionsAsync(filter);
+ }
}
diff --git a/src/BootstrapBlazor/Components/Filters/MultipleFilterBase.cs b/src/BootstrapBlazor/Components/Filters/MultipleFilterBase.cs
new file mode 100644
index 00000000000..637a798c327
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Filters/MultipleFilterBase.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License
+// See the LICENSE file in the project root for more information.
+// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
+
+namespace BootstrapBlazor.Components;
+
+///
+/// 多条件过滤器基类
+///
+public abstract class MultipleFilterBase : FilterBase
+{
+ ///
+ /// 获得/设置 条件数量
+ ///
+ [Parameter]
+ public int Count { get; set; }
+
+ ///
+ /// 获得/设置 多个条件逻辑关系符号
+ ///
+ protected FilterLogic Logic { get; set; }
+}
diff --git a/src/BootstrapBlazor/Components/Filters/NumberFilter.razor b/src/BootstrapBlazor/Components/Filters/NumberFilter.razor
index cab746c65a2..4ca28e1a2a4 100644
--- a/src/BootstrapBlazor/Components/Filters/NumberFilter.razor
+++ b/src/BootstrapBlazor/Components/Filters/NumberFilter.razor
@@ -1,47 +1,24 @@
@namespace BootstrapBlazor.Components
@typeparam TType
-@inherits FilterBase
+@inherits MultipleFilterBase
@if (IsHeaderRow)
{
- @if (typeof(TType).IsNumber())
- {
-
- }
- else
- {
-
- }
-
+
+
}
else
{
-
-
- @if (typeof(TType).IsNumber())
- {
-
- }
- else
- {
-
- }
-
+
+
@if (Count > 0)
{
-
-
-
- @if (typeof(TType).IsNumber())
- {
-
- }
- else
- {
-
- }
+
+
}
}
diff --git a/src/BootstrapBlazor/Components/Filters/NumberFilter.razor.cs b/src/BootstrapBlazor/Components/Filters/NumberFilter.razor.cs
index c74e30f69cf..f664d801d49 100644
--- a/src/BootstrapBlazor/Components/Filters/NumberFilter.razor.cs
+++ b/src/BootstrapBlazor/Components/Filters/NumberFilter.razor.cs
@@ -3,32 +3,28 @@
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-using Microsoft.Extensions.Localization;
-
namespace BootstrapBlazor.Components;
///
-/// 数字类型过滤条件
+/// NumberFilter 组件
///
public partial class NumberFilter
{
- private TType? Value1 { get; set; }
-
- private FilterAction Action1 { get; set; } = FilterAction.GreaterThanOrEqual;
-
- private TType? Value2 { get; set; }
+ private TType? _value1;
+ private FilterAction _action1 = FilterAction.GreaterThanOrEqual;
+ private TType? _value2;
+ private FilterAction _action2 = FilterAction.LessThanOrEqual;
+ private string? _step;
- private FilterAction Action2 { get; set; } = FilterAction.LessThanOrEqual;
-
- [Inject]
- [NotNull]
- private IStringLocalizer? Localizer { get; set; }
+ private string? FilterRowClassString => CssBuilder.Default("filter-row")
+ .AddClass("active", TableColumnFilter.HasFilter())
+ .Build();
///
- /// 获得/设置 步长 默认 0.01
+ /// Gets or sets the filter candidate items. It is recommended to use static data to avoid performance loss.
///
[Parameter]
- public string Step { get; set; } = "0.01";
+ public IEnumerable? Items { get; set; }
///
///
@@ -37,15 +33,16 @@ protected override void OnParametersSet()
{
base.OnParametersSet();
- Items ??= new SelectedItem[]
- {
- new("GreaterThanOrEqual", Localizer["GreaterThanOrEqual"].Value),
- new("LessThanOrEqual", Localizer["LessThanOrEqual"].Value),
- new("GreaterThan", Localizer["GreaterThan"].Value),
- new("LessThan", Localizer["LessThan"].Value),
- new("Equal", Localizer["Equal"].Value),
- new("NotEqual", Localizer["NotEqual"].Value)
- };
+ Items ??=
+ [
+ new SelectedItem("GreaterThanOrEqual", Localizer["GreaterThanOrEqual"].Value),
+ new SelectedItem("LessThanOrEqual", Localizer["LessThanOrEqual"].Value),
+ new SelectedItem("GreaterThan", Localizer["GreaterThan"].Value),
+ new SelectedItem("LessThan", Localizer["LessThan"].Value),
+ new SelectedItem("Equal", Localizer["Equal"].Value),
+ new SelectedItem("NotEqual", Localizer["NotEqual"].Value)
+ ];
+ _step = TableColumnFilter?.Column.Step;
}
///
@@ -53,10 +50,10 @@ protected override void OnParametersSet()
///
public override void Reset()
{
- Value1 = default;
- Value2 = default;
- Action1 = FilterAction.GreaterThanOrEqual;
- Action2 = FilterAction.LessThanOrEqual;
+ _value1 = default;
+ _value2 = default;
+ _action1 = FilterAction.GreaterThanOrEqual;
+ _action2 = FilterAction.LessThanOrEqual;
Count = 0;
Logic = FilterLogic.And;
StateHasChanged();
@@ -68,24 +65,24 @@ public override void Reset()
///
public override FilterKeyValueAction GetFilterConditions()
{
- var filter = new FilterKeyValueAction() { Filters = [] };
- if (Value1 != null)
+ var filter = new FilterKeyValueAction();
+ if (_value1 != null)
{
- filter.Filters.Add(new FilterKeyValueAction()
+ filter.Filters.Add(new FilterKeyValueAction
{
FieldKey = FieldKey,
- FieldValue = Value1,
- FilterAction = Action1
+ FieldValue = _value1,
+ FilterAction = _action1
});
}
- if (Count > 0 && Value2 != null)
+ if (Count > 0 && _value2 != null)
{
- filter.Filters.Add(new FilterKeyValueAction()
+ filter.Filters.Add(new FilterKeyValueAction
{
FieldKey = FieldKey,
- FieldValue = Value2,
- FilterAction = Action2,
+ FieldValue = _value2,
+ FilterAction = _action2,
});
filter.FilterLogic = Logic;
}
@@ -97,30 +94,30 @@ public override FilterKeyValueAction GetFilterConditions()
///
public override async Task SetFilterConditionsAsync(FilterKeyValueAction filter)
{
- var first = filter.Filters?.FirstOrDefault() ?? filter;
+ var first = filter.Filters.FirstOrDefault() ?? filter;
if (first.FieldValue is TType value)
{
- Value1 = value;
+ _value1 = value;
}
else
{
- Value1 = default;
+ _value1 = default;
}
- Action1 = first.FilterAction;
+ _action1 = first.FilterAction;
- if (filter.Filters != null && filter.Filters.Count == 2)
+ if (filter.Filters.Count > 1)
{
Count = 1;
FilterKeyValueAction second = filter.Filters[1];
if (second.FieldValue is TType value2)
{
- Value2 = value2;
+ _value2 = value2;
}
else
{
- Value2 = default;
+ _value2 = default;
}
- Action2 = second.FilterAction;
+ _action2 = second.FilterAction;
Logic = filter.FilterLogic;
}
await base.SetFilterConditionsAsync(filter);
diff --git a/src/BootstrapBlazor/Components/Filters/SearchFilterAction.cs b/src/BootstrapBlazor/Components/Filters/SearchFilterAction.cs
index 9cb238e7cfe..64a8e534b97 100644
--- a/src/BootstrapBlazor/Components/Filters/SearchFilterAction.cs
+++ b/src/BootstrapBlazor/Components/Filters/SearchFilterAction.cs
@@ -43,7 +43,7 @@ public void Reset()
///
public Task SetFilterConditionsAsync(FilterKeyValueAction filter)
{
- var first = filter.Filters?.FirstOrDefault() ?? filter;
+ var first = filter.Filters.FirstOrDefault() ?? filter;
if (first.FieldKey == Name)
{
Value = first.FieldValue;
diff --git a/src/BootstrapBlazor/Components/Filters/StringFilter.razor b/src/BootstrapBlazor/Components/Filters/StringFilter.razor
index 3084487b92c..9252ea1bb8b 100644
--- a/src/BootstrapBlazor/Components/Filters/StringFilter.razor
+++ b/src/BootstrapBlazor/Components/Filters/StringFilter.razor
@@ -1,25 +1,21 @@
@namespace BootstrapBlazor.Components
-@inherits FilterBase
+@inherits MultipleFilterBase
@if (IsHeaderRow)
{
-
-
+
+
}
else
{
-
-
-
-
+
+
@if (Count > 0)
{
-
-
-
-
+
+
}
}
diff --git a/src/BootstrapBlazor/Components/Filters/StringFilter.razor.cs b/src/BootstrapBlazor/Components/Filters/StringFilter.razor.cs
index 8e07b5c6b77..6d39ccfff5f 100644
--- a/src/BootstrapBlazor/Components/Filters/StringFilter.razor.cs
+++ b/src/BootstrapBlazor/Components/Filters/StringFilter.razor.cs
@@ -3,31 +3,37 @@
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-using Microsoft.Extensions.Localization;
-
namespace BootstrapBlazor.Components;
///
-/// 字符串类型过滤条件
+/// StringFilter 组件
///
public partial class StringFilter
{
- private string Value1 { get; set; } = "";
-
- private FilterAction Action1 { get; set; } = FilterAction.Contains;
-
- private string Value2 { get; set; } = "";
+ ///
+ /// Gets or sets the filter candidate items. It is recommended to use static data to avoid performance loss.
+ ///
+ [Parameter]
+ public IEnumerable? Items { get; set; }
- private FilterAction Action2 { get; set; } = FilterAction.Equal;
+ private string? _value1;
+ private FilterAction _action1 = FilterAction.Contains;
+ private string? _value2;
+ private FilterAction _action2 = FilterAction.Contains;
- [Inject]
- [NotNull]
- private IStringLocalizer? Localizer { get; set; }
+ private string? FilterRowClassString => CssBuilder.Default("filter-row")
+ .AddClass("active", TableColumnFilter.HasFilter())
+ .Build();
///
///
///
- protected override FilterLogic Logic { get; set; } = FilterLogic.Or;
+ protected override void OnInitialized()
+ {
+ base.OnInitialized();
+
+ Logic = FilterLogic.Or;
+ }
///
///
@@ -36,13 +42,13 @@ protected override void OnParametersSet()
{
base.OnParametersSet();
- Items ??= new SelectedItem[]
- {
- new("Contains", Localizer["Contains"].Value),
- new("Equal", Localizer["Equal"].Value),
- new("NotEqual", Localizer["NotEqual"].Value),
- new("NotContains", Localizer["NotContains"].Value)
- };
+ Items ??=
+ [
+ new SelectedItem("Contains", Localizer["Contains"].Value),
+ new SelectedItem("Equal", Localizer["Equal"].Value),
+ new SelectedItem("NotEqual", Localizer["NotEqual"].Value),
+ new SelectedItem("NotContains", Localizer["NotContains"].Value)
+ ];
}
///
@@ -50,10 +56,10 @@ protected override void OnParametersSet()
///
public override void Reset()
{
- Value1 = "";
- Value2 = "";
- Action1 = FilterAction.Contains;
- Action2 = FilterAction.Contains;
+ _value1 = null;
+ _value2 = null;
+ _action1 = FilterAction.Contains;
+ _action2 = FilterAction.Contains;
Logic = FilterLogic.Or;
Count = 0;
StateHasChanged();
@@ -65,24 +71,24 @@ public override void Reset()
///
public override FilterKeyValueAction GetFilterConditions()
{
- var filter = new FilterKeyValueAction() { Filters = [] };
- if (!string.IsNullOrEmpty(Value1))
+ var filter = new FilterKeyValueAction();
+ if (!string.IsNullOrEmpty(_value1))
{
- filter.Filters.Add(new FilterKeyValueAction()
+ filter.Filters.Add(new FilterKeyValueAction
{
FieldKey = FieldKey,
- FieldValue = Value1,
- FilterAction = Action1
+ FieldValue = _value1,
+ FilterAction = _action1
});
}
- if (Count > 0 && !string.IsNullOrEmpty(Value2))
+ if (Count > 0 && !string.IsNullOrEmpty(_value2))
{
- filter.Filters.Add(new FilterKeyValueAction()
+ filter.Filters.Add(new FilterKeyValueAction
{
FieldKey = FieldKey,
- FieldValue = Value2,
- FilterAction = Action2,
+ FieldValue = _value2,
+ FilterAction = _action2,
});
filter.FilterLogic = Logic;
}
@@ -94,30 +100,30 @@ public override FilterKeyValueAction GetFilterConditions()
///
public override async Task SetFilterConditionsAsync(FilterKeyValueAction filter)
{
- FilterKeyValueAction first = filter.Filters?.FirstOrDefault() ?? filter;
+ FilterKeyValueAction first = filter.Filters.FirstOrDefault() ?? filter;
if (first.FieldValue is string value)
{
- Value1 = value;
+ _value1 = value;
}
else
{
- Value1 = "";
+ _value1 = null;
}
- Action1 = first.FilterAction;
+ _action1 = first.FilterAction;
- if (filter.Filters != null && filter.Filters.Count == 2)
+ if (filter.Filters.Count > 1)
{
Count = 1;
FilterKeyValueAction second = filter.Filters[1];
if (second.FieldValue is string value2)
{
- Value2 = value2;
+ _value2 = value2;
}
else
{
- Value2 = "";
+ _value2 = null;
}
- Action2 = second.FilterAction;
+ _action2 = second.FilterAction;
Logic = second.FilterLogic;
}
await base.SetFilterConditionsAsync(filter);
diff --git a/src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor b/src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor
new file mode 100644
index 00000000000..35e63ed3615
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor
@@ -0,0 +1,75 @@
+@namespace BootstrapBlazor.Components
+@inherits BootstrapModuleComponentBase
+@attribute [BootstrapModuleAutoLoader("Filters/TableColumnFilter.razor.js")]
+
+@if (IsHeaderRow)
+{
+ @RenderFilter(Column)
+}
+else
+{
+
+
+
+ @RenderFilter(Column)
+
+}
+
+@code {
+ RenderFragment RenderFilter => Column =>
+ @
+ @if (Column.FilterTemplate != null)
+ {
+ @Column.FilterTemplate
+ }
+ else
+ {
+ @if (Column.PropertyType.IsEnum())
+ {
+
+ }
+ else if (Column.IsLookup())
+ {
+
+ }
+ else
+ {
+ var fieldType = Nullable.GetUnderlyingType(Column.PropertyType) ?? Column.PropertyType;
+ switch (fieldType.Name)
+ {
+ case nameof(String):
+
+ break;
+ case nameof(Boolean):
+
+ break;
+ case nameof(DateTime):
+
+ break;
+ case nameof(Int16):
+
+ break;
+ case nameof(Int32):
+
+ break;
+ case nameof(Int64):
+
+ break;
+ case nameof(Single):
+
+ break;
+ case nameof(Double):
+
+ break;
+ case nameof(Decimal):
+
+ break;
+ default:
+ @NotSupportedMessage
+ break;
+ }
+ }
+ }
+ ;
+}
diff --git a/src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor.cs b/src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor.cs
new file mode 100644
index 00000000000..d0d6238c524
--- /dev/null
+++ b/src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor.cs
@@ -0,0 +1,144 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License
+// See the LICENSE file in the project root for more information.
+// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
+
+using Microsoft.Extensions.Localization;
+
+namespace BootstrapBlazor.Components;
+
+///
+/// TableFilter component
+///
+public partial class TableColumnFilter : IFilter
+{
+ ///
+ /// 获得/设置 是否 active
+ ///
+ [Parameter]
+ public bool IsActive { get; set; }
+
+ ///
+ /// 获得/设置 过滤图标
+ ///
+ [Parameter]
+ public string? Icon { get; set; }
+
+ ///
+ /// 获得/设置 不支持过滤类型提示信息 默认 null 读取资源文件内容
+ ///
+ [Parameter]
+ public string? NotSupportedMessage { get; set; }
+
+ ///
+ /// 获得 相关联 ITableColumn 实例
+ ///
+ [Parameter]
+ [NotNull]
+ public ITableColumn? Column { get; set; }
+
+ ///
+ /// 获得/设置 是否为 HeaderRow 模式 默认 false
+ ///
+ [Parameter]
+ public bool IsHeaderRow { get; set; }
+
+ ///
+ /// 获得/设置 ITable 实例
+ ///
+ [Parameter]
+ [NotNull]
+ public ITable? Table { get; set; }
+
+ [Inject]
+ [NotNull]
+ private IStringLocalizer? Localizer { get; set; }
+
+ ///
+ /// 获得 过滤小图标样式
+ ///
+ private string? FilterClassString => CssBuilder.Default(Icon)
+ .AddClass("active", IsActive)
+ .Build();
+
+ ///
+ /// 获得 样式
+ ///
+ private string? ClassString => CssBuilder.Default("filter-icon")
+ .AddClassFromAttributes(AdditionalAttributes)
+ .Build();
+
+ ///
+ /// 获得/设置 过滤条件 IFilterAction 接口
+ ///
+ [NotNull]
+ public IFilterAction? FilterAction { get; set; }
+
+ private string _fieldKey = "";
+
+ ///
+ ///
+ ///
+ protected override void OnInitialized()
+ {
+ base.OnInitialized();
+
+ Column.Filter = this;
+ _fieldKey = Column.GetFieldName();
+ }
+
+ ///
+ ///
+ ///
+ protected override void OnParametersSet()
+ {
+ base.OnParametersSet();
+
+ NotSupportedMessage ??= Localizer[nameof(NotSupportedMessage)];
+ }
+
+ ///
+ ///
+ ///
+ ///
+ protected override async Task InvokeInitAsync()
+ {
+ if (!IsHeaderRow)
+ {
+ await base.InvokeInitAsync();
+ }
+ }
+
+ ///
+ /// Reset filter method
+ ///
+ public async Task Reset()
+ {
+ FilterAction.Reset();
+ await OnFilterAsync();
+ }
+
+ ///
+ /// Filter method
+ ///
+ ///
+ public async Task OnFilterAsync()
+ {
+ if (Table.OnFilterAsync == null)
+ {
+ return;
+ }
+
+ var action = FilterAction.GetFilterConditions();
+ if (action.Filters.Count > 0)
+ {
+ Table.Filters[_fieldKey] = FilterAction;
+ }
+ else
+ {
+ Table.Filters.Remove(_fieldKey);
+ }
+
+ await Table.OnFilterAsync();
+ }
+}
diff --git a/src/BootstrapBlazor/Components/Filters/TableFilter.razor.js b/src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor.js
similarity index 100%
rename from src/BootstrapBlazor/Components/Filters/TableFilter.razor.js
rename to src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor.js
diff --git a/src/BootstrapBlazor/Components/Filters/TableFilter.razor.scss b/src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor.scss
similarity index 100%
rename from src/BootstrapBlazor/Components/Filters/TableFilter.razor.scss
rename to src/BootstrapBlazor/Components/Filters/TableColumnFilter.razor.scss
diff --git a/src/BootstrapBlazor/Components/Filters/TableFilter.razor b/src/BootstrapBlazor/Components/Filters/TableFilter.razor
deleted file mode 100644
index ec94e845dbf..00000000000
--- a/src/BootstrapBlazor/Components/Filters/TableFilter.razor
+++ /dev/null
@@ -1,91 +0,0 @@
-@namespace BootstrapBlazor.Components
-@inherits BootstrapModuleComponentBase
-@attribute [BootstrapModuleAutoLoader("Filters/TableFilter.razor.js")]
-
-@if (IsHeaderRow)
-{
- @RenderFilter(Column)
-}
-else
-{
-
-
-
-
-
-
- @RenderFilter(Column)
-
-
-
-
-}
-
-@code {
- RenderFragment RenderFilter => Column =>
- @
- @if (Column.FilterTemplate != null)
- {
- @Column.FilterTemplate
- }
- else if (Column.PropertyType.IsEnum())
- {
-
- }
- else if (Column.IsLookup())
- {
-
- }
- else
- {
- var fieldType = Nullable.GetUnderlyingType(Column.PropertyType) ?? Column.PropertyType;
- switch (fieldType.Name)
- {
- case nameof(Boolean):
-
- break;
- case nameof(DateTime):
-
- break;
- case nameof(Int16):
-
- break;
- case nameof(Int32):
-
- break;
- case nameof(Int64):
-
- break;
- case nameof(Single):
-
- break;
- case nameof(Double):
-
- break;
- case nameof(Decimal):
-
- break;
- case nameof(String):
-
- break;
- default:
- @NotSupportedMessage
- break;
- };
- }
- ;
-}
diff --git a/src/BootstrapBlazor/Components/Filters/TableFilter.razor.cs b/src/BootstrapBlazor/Components/Filters/TableFilter.razor.cs
deleted file mode 100644
index 66d99990879..00000000000
--- a/src/BootstrapBlazor/Components/Filters/TableFilter.razor.cs
+++ /dev/null
@@ -1,259 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using Microsoft.Extensions.Localization;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// TableFilter 基类
-///
-public partial class TableFilter : IFilter
-{
- ///
- /// 获得 过滤小图标样式
- ///
- private string? FilterClassString => CssBuilder.Default(Icon)
- .AddClass("active", IsActive)
- .Build();
-
- ///
- /// 获得 样式
- ///
- private string? ClassString => CssBuilder.Default("filter-icon")
- .AddClassFromAttributes(AdditionalAttributes)
- .Build();
-
- ///
- /// 获得/设置 是否 active
- ///
- [Parameter]
- public bool IsActive { get; set; }
-
- ///
- /// 获得/设置 过滤图标
- ///
- [Parameter]
- public string? Icon { get; set; }
-
- ///
- /// 获得/设置 增加过滤条件图标
- ///
- [Parameter]
- public string? PlusIcon { get; set; }
-
- ///
- /// 获得/设置 减少过滤条件图标
- ///
- [Parameter]
- public string? MinusIcon { get; set; }
-
- ///
- /// 获得/设置 不支持过滤类型提示信息 默认 null 读取资源文件内容
- ///
- [Parameter]
- public string? NotSupportedMessage { get; set; }
-
- ///
- /// 获得/设置 Header 显示文字
- ///
- private string? _title;
-
- ///
- /// 获得/设置 相关 Field 字段名称
- ///
- [NotNull]
- internal string? FieldKey { get; set; }
-
- ///
- /// 获得/设置 条件数量
- ///
- private int _count;
-
- ///
- /// 获得/设置 是否显示增加减少条件按钮
- ///
- public bool ShowMoreButton { get; set; } = true;
-
- ///
- /// 获得/设置 过滤条件 IFilterAction 接口
- ///
- [NotNull]
- public IFilterAction? FilterAction { get; set; }
-
- ///
- /// 获得 当前过滤条件是否激活
- ///
- internal bool HasFilter => (Table != null) && Table.Filters.ContainsKey(Column.GetFieldName());
-
- ///
- /// 获得 相关联 ITableColumn 实例
- ///
- [Parameter]
- [NotNull]
- [EditorRequired]
- public ITableColumn? Column { get; set; }
-
- ///
- /// 重置按钮文本
- ///
- [Parameter]
- [NotNull]
- public string? ClearButtonText { get; set; }
-
- ///
- /// 获得/设置 是否为 HeaderRow 模式 默认 false
- ///
- [Parameter]
- public bool IsHeaderRow { get; set; }
-
- ///
- /// 过滤按钮文本
- ///
- [Parameter]
- [NotNull]
- public string? FilterButtonText { get; set; }
-
- ///
- /// 获得/设置 ITable 实例
- ///
- [Parameter]
- public ITable? Table { get; set; }
-
- [Inject]
- [NotNull]
- private IStringLocalizer? Localizer { get; set; }
-
- [Inject]
- [NotNull]
- private IIconTheme? IconTheme { get; set; }
-
- ///
- /// 组件步长
- ///
- private string? _step;
-
- ///
- ///
- ///
- protected override void OnInitialized()
- {
- base.OnInitialized();
-
- _title = Column.GetDisplayName();
- FieldKey = Column.GetFieldName();
- Column.Filter = this;
- _step = Column.Step;
- }
-
- ///
- ///
- ///
- protected override void OnParametersSet()
- {
- base.OnParametersSet();
-
- FilterButtonText ??= Localizer[nameof(FilterButtonText)];
- ClearButtonText ??= Localizer[nameof(ClearButtonText)];
- NotSupportedMessage ??= Localizer[nameof(NotSupportedMessage)];
-
- PlusIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableFilterPlusIcon);
- MinusIcon ??= IconTheme.GetIconByKey(ComponentIcons.TableFilterMinusIcon);
-
- if (Table != null && Table.Filters.TryGetValue(Column.GetFieldName(), out var action))
- {
- var filter = action.GetFilterConditions();
- if (filter.Filters?.Count > 1)
- {
- _count = 1;
- }
- }
- }
-
- ///
- ///
- ///
- ///
- protected override async Task InvokeInitAsync()
- {
- if (!IsHeaderRow)
- {
- await base.InvokeInitAsync();
- }
- }
-
- ///
- /// 点击重置按钮时回调此方法
- ///
- ///
- private async Task OnClickReset()
- {
- _count = 0;
-
- if (Table != null)
- {
- Table.Filters.Remove(FieldKey);
- FilterAction.Reset();
- if (Table.OnFilterAsync != null)
- {
- await Table.OnFilterAsync();
- }
- }
- }
-
- ///
- /// 点击确认时回调此方法
- ///
- ///
- private Task OnClickConfirm() => OnFilterAsync();
-
- ///
- /// 过滤数据方法
- ///
- ///
- internal async Task OnFilterAsync()
- {
- if (Table != null)
- {
- var f = FilterAction.GetFilterConditions();
- if (f.Filters != null && f.Filters.Count > 0)
- {
- Table.Filters[FieldKey] = FilterAction;
- }
- else
- {
- Table.Filters.Remove(FieldKey);
- }
- if (Table.OnFilterAsync != null)
- {
- await Table.OnFilterAsync();
- }
- }
- }
-
- ///
- /// 点击增加按钮时回调此方法
- ///
- ///
- private void OnClickPlus()
- {
- if (_count == 0)
- {
- _count++;
- }
- }
-
- ///
- /// 点击减少按钮时回调此方法
- ///
- ///
- private void OnClickMinus()
- {
- if (_count == 1)
- {
- _count--;
- }
- }
-}
diff --git a/src/BootstrapBlazor/Components/QueryBuilder/GroupFilterKeyValueAction.cs b/src/BootstrapBlazor/Components/QueryBuilder/GroupFilterKeyValueAction.cs
new file mode 100644
index 00000000000..c2e2c49f1ec
--- /dev/null
+++ b/src/BootstrapBlazor/Components/QueryBuilder/GroupFilterKeyValueAction.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License
+// See the LICENSE file in the project root for more information.
+// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
+
+namespace BootstrapBlazor.Components;
+
+class GroupFilterKeyValueAction : FilterKeyValueAction
+{
+ public GroupFilterKeyValueAction()
+ {
+ FilterLogic = FilterLogic.Or;
+ }
+}
diff --git a/src/BootstrapBlazor/Components/QueryBuilder/QueryBuilder.razor b/src/BootstrapBlazor/Components/QueryBuilder/QueryBuilder.razor
index 1bb183833ce..eaaa8491fb8 100644
--- a/src/BootstrapBlazor/Components/QueryBuilder/QueryBuilder.razor
+++ b/src/BootstrapBlazor/Components/QueryBuilder/QueryBuilder.razor
@@ -6,7 +6,7 @@
@ChildContent?.Invoke(new TModel())
- @if (!Value.HasFilters() && ShowHeader)
+ @if (ShowHeader && Value.Filters.Count == 0)
{
@RenderHeader(null, Value)
}
@@ -17,6 +17,29 @@
@code {
+ RenderFragment RenderFilters(FilterKeyValueAction? parent, FilterKeyValueAction filter) =>
+ @
;
+
RenderFragment RenderFilter(FilterKeyValueAction parent, FilterKeyValueAction filter) =>
@
diff --git a/src/BootstrapBlazor/Components/QueryBuilder/QueryBuilder.razor.cs b/src/BootstrapBlazor/Components/QueryBuilder/QueryBuilder.razor.cs
index 6947a6065b6..a146fe68437 100644
--- a/src/BootstrapBlazor/Components/QueryBuilder/QueryBuilder.razor.cs
+++ b/src/BootstrapBlazor/Components/QueryBuilder/QueryBuilder.razor.cs
@@ -24,9 +24,7 @@ namespace BootstrapBlazor.Components;
///
[Parameter]
[NotNull]
-#if NET6_0_OR_GREATER
[EditorRequired]
-#endif
public FilterKeyValueAction? Value { get; set; }
///
@@ -131,7 +129,6 @@ protected override void OnParametersSet()
ItemText ??= Localizer[nameof(ItemText)];
Value ??= new();
- Value.Filters ??= [];
Value.FilterLogic = Logic;
Operations ??=
@@ -164,14 +161,14 @@ protected override void OnAfterRender(bool firstRender)
private async Task OnClickRemoveFilter(FilterKeyValueAction parent, FilterKeyValueAction filter)
{
- parent.Filters!.Remove(filter);
+ parent.Filters.Remove(filter);
await OnFilterChanged();
}
private async Task OnClickAddFilter(FilterKeyValueAction filter)
{
- filter.Filters!.Add(new());
+ filter.Filters.Add(new());
await OnFilterChanged();
}
@@ -197,65 +194,33 @@ private Task SetFilterLogic(FilterKeyValueAction? parent, FilterKeyValueAction f
private async Task OnAddFilterGroup(FilterKeyValueAction filter)
{
- filter.Filters!.Add(new FilterKeyValueAction() { Filters = [new()] });
+ filter.Filters.Add(new GroupFilterKeyValueAction());
await OnFilterChanged();
}
private async Task OnAddFilterItem(FilterKeyValueAction filter)
{
- filter.Filters!.Add(new FilterKeyValueAction() { });
+ filter.Filters.Add(new FilterKeyValueAction());
await OnFilterChanged();
}
private async Task OnClickRemove(FilterKeyValueAction? parent, FilterKeyValueAction filter)
{
- filter.Filters!.Clear();
- parent?.Filters!.Remove(filter);
+ filter.Filters.Clear();
+ parent?.Filters.Remove(filter);
await OnFilterChanged();
}
- private static Color GetColorByFilter(FilterKeyValueAction filter, FilterLogic logic) => filter.FilterLogic == logic ? Color.Primary : Color.Secondary;
+ private static Color GetColorByFilter(FilterKeyValueAction filter, FilterLogic logic) => filter.FilterLogic == logic
+ ? Color.Primary
+ : Color.Secondary;
private readonly List _fields = [];
- RenderFragment RenderFilters(FilterKeyValueAction? parent, FilterKeyValueAction filter) => builder =>
- {
- if (filter.Filters != null)
- {
- var index = 0;
- builder.OpenElement(index++, "ul");
- builder.AddAttribute(index++, "class", "qb-group");
- if (filter.HasFilters() && ShowHeader)
- {
- builder.OpenElement(index++, "li");
- builder.AddAttribute(index++, "class", "qb-item");
- builder.AddContent(index++, RenderHeader(parent, filter));
- builder.CloseElement();
- }
- foreach (var f in filter.Filters)
- {
- if (f.HasFilters())
- {
- RenderFilterItem(ref index, RenderFilters(filter, f));
- }
- else
- {
- RenderFilterItem(ref index, RenderFilter(filter, f));
- }
- }
- builder.CloseElement();
- }
+ private bool IsShowHeader(FilterKeyValueAction filter) => ShowHeader && IsGroup(filter);
- void RenderFilterItem(ref int sequence, RenderFragment fragment)
- {
- builder.OpenElement(sequence++, "li");
- builder.AddAttribute(sequence++, "class", "qb-item");
- builder.AddAttribute(sequence++, "data-bb-logic", Localizer[filter.FilterLogic.ToString()]);
- builder.AddContent(sequence++, fragment);
- builder.CloseElement();
- }
- };
+ private static bool IsGroup(FilterKeyValueAction filter) => filter is GroupFilterKeyValueAction || filter.Filters.Count > 0;
}
diff --git a/src/BootstrapBlazor/Components/QueryBuilder/QueryGroup.razor b/src/BootstrapBlazor/Components/QueryBuilder/QueryGroup.razor
new file mode 100644
index 00000000000..9af2bd3561e
--- /dev/null
+++ b/src/BootstrapBlazor/Components/QueryBuilder/QueryGroup.razor
@@ -0,0 +1,6 @@
+@namespace BootstrapBlazor.Components
+@inherits BootstrapComponentBase
+
+
+ @ChildContent
+
diff --git a/src/BootstrapBlazor/Components/QueryBuilder/QueryGroup.cs b/src/BootstrapBlazor/Components/QueryBuilder/QueryGroup.razor.cs
similarity index 67%
rename from src/BootstrapBlazor/Components/QueryBuilder/QueryGroup.cs
rename to src/BootstrapBlazor/Components/QueryBuilder/QueryGroup.razor.cs
index 68b0ee0b684..74cbf011e9d 100644
--- a/src/BootstrapBlazor/Components/QueryBuilder/QueryGroup.cs
+++ b/src/BootstrapBlazor/Components/QueryBuilder/QueryGroup.razor.cs
@@ -3,14 +3,12 @@
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-using Microsoft.AspNetCore.Components.Rendering;
-
namespace BootstrapBlazor.Components;
///
/// QueryGroup 组件
///
-public class QueryGroup : BootstrapComponentBase, IDisposable
+public partial class QueryGroup : IDisposable
{
///
/// 获得/设置 子组件
@@ -33,7 +31,7 @@ public class QueryGroup : BootstrapComponentBase, IDisposable
///
/// 过滤条件集合
///
- protected FilterKeyValueAction _filter = new() { Filters = [] };
+ protected FilterKeyValueAction _filter = new();
///
///
@@ -55,19 +53,6 @@ protected override void OnParametersSet()
_filter.FilterLogic = Logic;
}
- ///
- ///
- ///
- ///
- protected override void BuildRenderTree(RenderTreeBuilder builder)
- {
- builder.OpenComponent>>(10);
- builder.AddAttribute(20, nameof(CascadingValue>.IsFixed), true);
- builder.AddAttribute(30, nameof(CascadingValue>.Value), _filter.Filters);
- builder.AddAttribute(40, nameof(CascadingValue>.ChildContent), ChildContent);
- builder.CloseComponent();
- }
-
///
/// 释放资源
///
diff --git a/src/BootstrapBlazor/Components/Table/Table.razor b/src/BootstrapBlazor/Components/Table/Table.razor
index 79cec98698d..51d31552a62 100644
--- a/src/BootstrapBlazor/Components/Table/Table.razor
+++ b/src/BootstrapBlazor/Components/Table/Table.razor
@@ -586,7 +586,7 @@
}
@if (col.GetFilterable() && !ShowFilterHeader)
{
-
+
}
@if (col.GetSortable())
{
@@ -655,7 +655,7 @@
@if(col.GetFilterable())
{
-
+
}
diff --git a/src/BootstrapBlazor/Extensions/LambdaExtensions.cs b/src/BootstrapBlazor/Extensions/LambdaExtensions.cs
index 8a19cf6a38e..a77c62302f2 100644
--- a/src/BootstrapBlazor/Extensions/LambdaExtensions.cs
+++ b/src/BootstrapBlazor/Extensions/LambdaExtensions.cs
@@ -46,9 +46,9 @@ private class ComboExpressionVisitor(ParameterExpression parameter) : Expression
public static Expression> GetFilterLambda(this FilterKeyValueAction filter)
{
var express = new List>>();
- if (filter.Filters != null)
+ if (filter.Filters.Count > 0)
{
- express.AddRange(filter.Filters.Select(f => f.Filters != null
+ express.AddRange(filter.Filters.Select(f => f.Filters.Count > 0
? f.Filters.GetFilterLambda(f.FilterLogic)
: f.GetInnerFilterLambda()));
}
@@ -86,7 +86,7 @@ public static Expression> GetFilterLambda(this FilterKe
///
private static Expression> GetFilterLambda(this IEnumerable filters, FilterLogic logic)
{
- var express = filters.Select(filter => filter.Filters != null
+ var express = filters.Select(filter => filter.Filters.Count > 0
? filter.Filters.GetFilterLambda(filter.FilterLogic)
: filter.GetInnerFilterLambda())
.ToList();
diff --git a/src/BootstrapBlazor/Extensions/QueryPageOptionsExtensions.cs b/src/BootstrapBlazor/Extensions/QueryPageOptionsExtensions.cs
index 7e29e5cc117..cf3c52ce585 100644
--- a/src/BootstrapBlazor/Extensions/QueryPageOptionsExtensions.cs
+++ b/src/BootstrapBlazor/Extensions/QueryPageOptionsExtensions.cs
@@ -19,7 +19,7 @@ public static class QueryPageOptionsExtensions
///
public static FilterKeyValueAction ToFilter(this QueryPageOptions option)
{
- var filter = new FilterKeyValueAction() { Filters = [] };
+ var filter = new FilterKeyValueAction();
// 处理模糊搜索
if (option.Searches.Count != 0)
@@ -27,7 +27,7 @@ public static FilterKeyValueAction ToFilter(this QueryPageOptions option)
filter.Filters.Add(new FilterKeyValueAction()
{
FilterLogic = FilterLogic.Or,
- Filters = option.Searches.Select(i => i.GetFilterConditions()).ToList()
+ Filters = [.. option.Searches.Select(i => i.GetFilterConditions())]
});
}
@@ -71,5 +71,5 @@ public static FilterKeyValueAction ToFilter(this QueryPageOptions option)
///
///
///
- public static bool HasFilters(this FilterKeyValueAction filterKeyValueAction) => filterKeyValueAction.Filters != null && filterKeyValueAction.Filters.Count != 0;
+ public static bool HasFilters(this FilterKeyValueAction filterKeyValueAction) => filterKeyValueAction.Filters.Count != 0;
}
diff --git a/src/BootstrapBlazor/Extensions/TableColumnFilterExtensions.cs b/src/BootstrapBlazor/Extensions/TableColumnFilterExtensions.cs
new file mode 100644
index 00000000000..417b9c839ce
--- /dev/null
+++ b/src/BootstrapBlazor/Extensions/TableColumnFilterExtensions.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License
+// See the LICENSE file in the project root for more information.
+// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
+
+namespace BootstrapBlazor.Components;
+
+///
+/// TableFilter extensions methods
+///
+public static class TableColumnFilterExtensions
+{
+ ///
+ /// Whether has filter
+ ///
+ ///
+ ///
+ public static bool HasFilter(this TableColumnFilter? filter)
+ {
+ if (filter == null)
+ {
+ return false;
+ }
+ return filter.Table.Filters.ContainsKey(filter.Column.GetFieldName());
+ }
+
+ ///
+ /// Whether is header row
+ ///
+ ///
+ ///
+ public static bool IsHeaderRow(this TableColumnFilter? filter)
+ {
+ if (filter == null)
+ {
+ return false;
+ }
+ return filter.IsHeaderRow;
+ }
+
+ ///
+ /// Gets the field key for the filter.
+ ///
+ ///
+ ///
+ public static string GetFieldKey(this TableColumnFilter? filter)
+ {
+ if (filter == null)
+ {
+ return string.Empty;
+ }
+ return filter.Column.GetFieldName();
+ }
+
+ ///
+ /// Gets the filter title.
+ ///
+ ///
+ ///
+ public static string GetFilterTitle(this TableColumnFilter? filter)
+ {
+ if (filter == null)
+ {
+ return string.Empty;
+ }
+ return filter.Column.GetDisplayName();
+ }
+}
diff --git a/src/BootstrapBlazor/Locales/en.json b/src/BootstrapBlazor/Locales/en.json
index c2d030ddbe0..70420663e99 100644
--- a/src/BootstrapBlazor/Locales/en.json
+++ b/src/BootstrapBlazor/Locales/en.json
@@ -185,10 +185,6 @@
"ContextCloseAll": "Close All Tabs",
"ContextFullScreen": "Full screen"
},
- "BootstrapBlazor.Components.MultiFilter": {
- "MultiFilterSearchPlaceHolderText": "Please enter ...",
- "MultiFilterSelectAllText": "Select All"
- },
"BootstrapBlazor.Components.Table": {
"AddButtonText": "Add",
"EditButtonText": "Edit",
@@ -263,7 +259,7 @@
"CloseButtonText": "Close",
"SaveButtonText": "Save"
},
- "BootstrapBlazor.Components.TableFilter": {
+ "BootstrapBlazor.Components.TableColumnFilter": {
"ClearButtonText": "Clear",
"FilterButtonText": "Filter",
"BoolFilter.AllText": "All",
@@ -278,7 +274,9 @@
"Contains": "Contains",
"NotContains": "NotContains",
"EnumFilter.AllText": "All",
- "NotSupportedMessage": "Unsupported filter type, Please customize the filter use FilterTemplate"
+ "NotSupportedMessage": "Unsupported filter type, Please customize the filter use FilterTemplate",
+ "MultiFilterSearchPlaceHolderText": "Please enter ...",
+ "MultiFilterSelectAllText": "Select All"
},
"BootstrapBlazor.Components.FilterLogicItem": {
"And": "And",
diff --git a/src/BootstrapBlazor/Locales/zh.json b/src/BootstrapBlazor/Locales/zh.json
index 219dd19ade3..2997ab392b7 100644
--- a/src/BootstrapBlazor/Locales/zh.json
+++ b/src/BootstrapBlazor/Locales/zh.json
@@ -185,10 +185,6 @@
"ContextCloseAll": "关闭全部",
"ContextFullScreen": "全屏"
},
- "BootstrapBlazor.Components.MultiFilter": {
- "MultiFilterSearchPlaceHolderText": "请输入 ...",
- "MultiFilterSelectAllText": "全选"
- },
"BootstrapBlazor.Components.Table": {
"AddButtonText": "新建",
"EditButtonText": "编辑",
@@ -263,7 +259,7 @@
"CloseButtonText": "关闭",
"SaveButtonText": "保存"
},
- "BootstrapBlazor.Components.TableFilter": {
+ "BootstrapBlazor.Components.TableColumnFilter": {
"ClearButtonText": "重置",
"FilterButtonText": "确认",
"BoolFilter.AllText": "全部",
@@ -278,7 +274,9 @@
"Contains": "包含",
"NotContains": "不包含",
"EnumFilter.AllText": "全选",
- "NotSupportedMessage": "不支持的类型,请使用 FilterTemplate 自定义过滤组件"
+ "NotSupportedMessage": "不支持的类型,请使用 FilterTemplate 自定义过滤组件",
+ "MultiFilterSearchPlaceHolderText": "请输入 ...",
+ "MultiFilterSelectAllText": "全选"
},
"BootstrapBlazor.Components.FilterLogicItem": {
"And": "并且",
diff --git a/src/BootstrapBlazor/wwwroot/scss/components.scss b/src/BootstrapBlazor/wwwroot/scss/components.scss
index ceb8fb7c648..cb52a9e2678 100644
--- a/src/BootstrapBlazor/wwwroot/scss/components.scss
+++ b/src/BootstrapBlazor/wwwroot/scss/components.scss
@@ -43,7 +43,7 @@
@import "../../Components/FlipClock/FlipClock.razor.scss";
@import "../../Components/FileIcon/FileIcon.razor.scss";
@import "../../Components/Filters/MultiFilter.razor.scss";
-@import "../../Components/Filters/TableFilter.razor.scss";
+@import "../../Components/Filters/TableColumnFilter.razor.scss";
@import "../../Components/Footer/Footer.razor.scss";
@import "../../Components/FullScreen/FullScreenButton.razor.scss";
@import "../../Components/GoTop/GoTop.razor.scss";
diff --git a/test/UnitTest/Components/FilterLogicItemTest.cs b/test/UnitTest/Components/FilterLogicItemTest.cs
new file mode 100644
index 00000000000..8f5943bc5ab
--- /dev/null
+++ b/test/UnitTest/Components/FilterLogicItemTest.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License
+// See the LICENSE file in the project root for more information.
+// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
+
+namespace UnitTest.Components;
+
+public class FilterLogicItemTest : BootstrapBlazorTestBase
+{
+ [Fact]
+ public async Task FilterLogicItem_Ok()
+ {
+ var logic = FilterLogic.And;
+ var cut = Context.RenderComponent(pb =>
+ {
+ pb.Add(a => a.Logic, FilterLogic.And);
+ pb.Add(a => a.LogicChanged, EventCallback.Factory.Create(this, v =>
+ {
+ logic = v;
+ }));
+ });
+
+ var select = cut.FindComponent