Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,48 +34,6 @@
</Table>
</DemoBlock>

<DemoBlock Title="@Localizer["SearchTableTitle"]"
Introduction="@Localizer["SearchTableIntro"]"
Name="SearchTable">
<section ignore>
<ul class="ul-demo mb-3">
<li>@((MarkupString)Localizer["SearchTableLi1"].Value)</li>
<li>@((MarkupString)Localizer["SearchTableLi2"].Value)</li>
<li>@((MarkupString)Localizer["SearchTableLi3"].Value)</li>
</ul>
@((MarkupString)Localizer["AutoHeightIntro"].Value)
</section>
<div style="height: 600px;">
<Table TItem="Foo"
IsPagination="true" PageItemsSource="new int[] {10, 20}"
IsStriped="true" IsBordered="true" ShowMoreButton="true"
ShowToolbar="true" ShowSearch="true" ShowCardView="true" IsMultipleSelect="true" ShowExtendButtons="true"
AddModalTitle="@Localizer["AddModelTitle"]" EditModalTitle="@Localizer["EditModelTitle"]"
SearchModel="@SearchModel" SearchMode="SearchMode.Top" ShowEmpty="true"
OnQueryAsync="@OnSearchModelQueryAsync" OnResetSearchAsync="@OnResetSearchAsync"
OnAddAsync="@OnAddAsync" OnSaveAsync="@OnSaveAsync" OnDeleteAsync="@OnDeleteAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" />
<TableColumn @bind-Field="@context.Name" />
<TableColumn @bind-Field="@context.Address" />
<TableColumn @bind-Field="@context.Education" />
</TableColumns>
<SearchTemplate>
<GroupBox Title="@Localizer["SearchTableGroupBoxText"]">
<div class="row g-3 form-inline">
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.Name" PlaceHolder="@Localizer["NamePlaceholder"]" maxlength="50" ShowLabel="true" DisplayText="@FooLocalizer[nameof(context.Name)]" />
</div>
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.Address" PlaceHolder="@Localizer["AddressPlaceholder"]" maxlength="500" ShowLabel="true" DisplayText="@FooLocalizer[nameof(context.Address)]" />
</div>
</div>
</GroupBox>
</SearchTemplate>
</Table>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["AutoGenerateSearchTitle"]"
Introduction="@Localizer["AutoGenerateSearchIntro"]"
Name="AutoGenerateSearch">
Expand Down Expand Up @@ -124,6 +82,48 @@
</Table>
</DemoBlock>

<DemoBlock Title="@Localizer["SearchTableTitle"]"
Introduction="@Localizer["SearchTableIntro"]"
Name="SearchTable">
<section ignore>
<ul class="ul-demo mb-3">
<li>@((MarkupString)Localizer["SearchTableLi1"].Value)</li>
<li>@((MarkupString)Localizer["SearchTableLi2"].Value)</li>
<li>@((MarkupString)Localizer["SearchTableLi3"].Value)</li>
</ul>
@((MarkupString)Localizer["AutoHeightIntro"].Value)
</section>
<div style="height: 600px;">
<Table TItem="Foo"
IsPagination="true" PageItemsSource="new int[] {10, 20}"
IsStriped="true" IsBordered="true" ShowMoreButton="true"
ShowToolbar="true" ShowSearch="true" ShowCardView="true" IsMultipleSelect="true" ShowExtendButtons="true"
AddModalTitle="@Localizer["AddModelTitle"]" EditModalTitle="@Localizer["EditModelTitle"]"
SearchModel="@SearchModel" SearchMode="SearchMode.Top" ShowEmpty="true"
OnQueryAsync="@OnSearchModelQueryAsync" OnResetSearchAsync="@OnResetSearchAsync"
OnAddAsync="@OnAddAsync" OnSaveAsync="@OnSaveAsync" OnDeleteAsync="@OnDeleteAsync">
<TableColumns>
<TableColumn @bind-Field="@context.DateTime" Width="180" />
<TableColumn @bind-Field="@context.Name" />
<TableColumn @bind-Field="@context.Address" />
<TableColumn @bind-Field="@context.Education" />
</TableColumns>
<SearchTemplate>
<GroupBox Title="@Localizer["SearchTableGroupBoxText"]">
<div class="row g-3 form-inline">
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.Name" PlaceHolder="@Localizer["NamePlaceholder"]" maxlength="50" ShowLabel="true" DisplayText="@FooLocalizer[nameof(context.Name)]" />
</div>
<div class="col-12 col-sm-6">
<BootstrapInput @bind-Value="@context.Address" PlaceHolder="@Localizer["AddressPlaceholder"]" maxlength="500" ShowLabel="true" DisplayText="@FooLocalizer[nameof(context.Address)]" />
</div>
</div>
</GroupBox>
</SearchTemplate>
</Table>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["CustomColSearchTitle"]"
Introduction="@Localizer["CustomColSearchIntro"]"
Name="CustomColSearch">
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -5066,7 +5066,7 @@
"NamePlaceholder": "Please enter your name within 50 characters",
"SearchFormDesc": "When <code>UseSearchForm</code> is enabled and <code>SearchItems</code> is not provided, it will default to using <code>TableColumn</code> with <code>Searchable=\"true\"</code>. You can customize the metadata through the <code>SearchFormItemMetadata</code> property in <code>TableColumn</code>",
"SearchFormIntro": "Enable the search form feature by setting <code>UseSearchForm=\"true\"</code>, and configure the search items within the form using <code>SearchItems</code>, suitable for scenarios with custom complex search conditions",
"SearchFormTips": "Enabling <code>UseSearchForm</code> will prevent <code>SearchTemplate</code>, <code>CustomerSearchModel</code>, and <code>CustomerSearchTemplate</code> from taking effect.",
"SearchFormTips": "Enabling <code>UseSearchForm</code> will prevent <code>SearchModel</code> <code>SearchTemplate</code>, <code>CustomerSearchModel</code>, and <code>CustomerSearchTemplate</code> from taking effect.",
"SearchFormTitle": "Search Form",
"SearchTableGroupBoxText": "Search Criteria",
"SearchTableIntro": "Set <code>ShowSearch</code> to display the query component, customize the search UI by setting the <code>SearchTemplate</code> template",
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -5065,8 +5065,8 @@
"EditModelTitle": "编辑测试数据窗口",
"NamePlaceholder": "请输入姓名,50字以内",
"SearchFormDesc": "使用 <code>UseSearchForm</code> 开启搜索表单时未提供 <code>SearchItems</code> 默认尝试使用设置 <code>Searchable=\"true\"</code> 的 <code>TableColumn</code> 进行构建,可以通过 <code>TableColumn</code> 中的 <code>SearchFormItemMetadata</code> 属性定制化元数据",
"SearchFormTips": "开启 <code>UseSearchForm</code> 后 <code>SearchTemplate</code> <code>CustomerSearchModel</code> <code>CustomerSearchTemplate</code> 均不生效",
"SearchFormIntro": "通过设置 <code>UseSearchForm=\"true\"</code> 开启搜索表单功能,通过 <code>SearchItems</code> 配置搜索表单内搜索项,适用于自定义复杂搜索条件的场景",
"SearchFormTips": "开启 <code>UseSearchForm</code> 后 <code>SearchModel</code> <code>SearchTemplate</code> <code>CustomerSearchModel</code> <code>CustomerSearchTemplate</code> 均不生效",
"SearchFormTitle": "搜索表单",
"SearchTableGroupBoxText": "搜索条件",
"SearchTableIntro": "设置 <code>ShowSearch</code> 显示查询组件,通过设置 <code>SearchTemplate</code> 模板自定义搜索 UI",
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/BootstrapBlazor.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>10.4.2-beta02</Version>
<Version>10.4.2</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
6 changes: 4 additions & 2 deletions src/BootstrapBlazor/Components/Dialog/SearchDialog.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

@if (UseSearchForm)
{
<SearchForm Items="SearchItems" RowType="RowType" ItemsPerRow="ItemsPerRow" LabelAlign="LabelAlign" ShowLabel="ShowLabel" ShowUnsetGroupItemsOnTop="ShowUnsetGroupItemsOnTop"
SearchFormLocalizerOptions="SearchFormLocalizerOptions" OnChanged="OnSearchFormFilterChanged">
<SearchForm Items="SearchItems" RowType="RowType" ItemsPerRow="ItemsPerRow"
LabelAlign="LabelAlign" ShowLabel="ShowLabel" ShowUnsetGroupItemsOnTop="ShowUnsetGroupItemsOnTop"
SearchFormLocalizerOptions="SearchFormLocalizerOptions"
OnChanged="OnSearchFormFilterChanged">
<Buttons>
@RenderButtons
</Buttons>
Expand Down
14 changes: 3 additions & 11 deletions src/BootstrapBlazor/Components/SearchForm/SearchForm.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,26 +145,18 @@ private RenderFragment AutoGenerateTemplate(ISearchItem item)
if (OnChanged != null)
{
var filter = Items.ToFilter();
await OnChanged.Invoke(filter);
await OnChanged(filter);
}
};

return item.CreateSearchItemComponentByMetadata();
return item.Metadata.RenderContent() ?? item.CreateSearchItemComponentByMetadata();
}

private SearchFormLocalizerOptions? _options;

private SearchFormLocalizerOptions GetSearchOptions()
{
_options ??= SearchFormLocalizerOptions ?? new SearchFormLocalizerOptions()
{
SelectAllText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.SelectAllText)],
BooleanAllText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.BooleanAllText)],
BooleanTrueText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.BooleanTrueText)],
BooleanFalseText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.BooleanFalseText)],
NumberStartValueLabelText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.NumberStartValueLabelText)],
NumberEndValueLabelText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.NumberEndValueLabelText)]
};
_options ??= SearchFormLocalizerOptions ?? SearchFormLocalizer.GetSearchFormLocalizerOptions();

return _options.Value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace BootstrapBlazor.Components;
/// <para lang="zh">时间区间搜索元数据类</para>
/// <para lang="en">DateTime range search meta data class</para>
/// </summary>
public class DateTimeRangeSearchMetadata : SearchMetadataBase
public class DateTimeRangeSearchMetadata : SearchFormItemMetadataBase
{
/// <summary>
/// <para lang="zh">获得/设置 搜索值</para>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace BootstrapBlazor.Components;
/// <para lang="zh">时间搜索元数据类</para>
/// <para lang="en">DateTime search meta data class</para>
/// </summary>
public class DateTimeSearchMetadata : SearchMetadataBase
public class DateTimeSearchMetadata : SearchFormItemMetadataBase
{
/// <summary>
/// <para lang="zh">获得/设置 搜索值</para>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,11 @@ public interface ISearchFormItemMetadata
/// <para lang="en">Reset method</para>
/// </summary>
void Reset();

/// <summary>
/// <para lang="zh">渲染自定义内容方法</para>
/// <para lang="en">Render custom content method</para>
/// </summary>
/// <returns></returns>
RenderFragment? RenderContent();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace BootstrapBlazor.Components;
public class MultipleSelectSearchMetadata : SelectSearchMetadata
{
/// <summary>
/// <inheritdoc cref="SearchMetadataBase.GetFilter(string)"/>
/// <inheritdoc cref="SearchFormItemMetadataBase.GetFilter(string)"/>
/// </summary>
public override FilterKeyValueAction? GetFilter(string fieldName)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace BootstrapBlazor.Components;
/// <para lang="zh">数字类型搜索元数据类</para>
/// <para lang="en">Number type search metadata class</para>
/// </summary>
public class NumberSearchMetadata : SearchMetadataBase
public class NumberSearchMetadata : SearchFormItemMetadataBase
{
/// <summary>
/// <para lang="zh">获得/设置 搜索开始值</para>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace BootstrapBlazor.Components;
/// <para lang="zh">搜索元数据基类</para>
/// <para lang="en">Search meta data base class</para>
/// </summary>
public abstract class SearchMetadataBase : ISearchFormItemMetadata
public abstract class SearchFormItemMetadataBase : ISearchFormItemMetadata
{
/// <summary>
/// <para lang="zh">获得/设置 占位符文本</para>
Expand Down Expand Up @@ -72,7 +72,13 @@ public abstract class SearchMetadataBase : ISearchFormItemMetadata
}

/// <summary>
/// <inheritdoc/>
/// <inheritdoc cref="ISearchFormItemMetadata.Reset"/>
/// </summary>
public abstract void Reset();

/// <summary>
/// <inheritdoc cref="ISearchFormItemMetadata.RenderContent"/>
/// </summary>
/// <returns></returns>
public virtual RenderFragment? RenderContent() => null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace BootstrapBlazor.Components;
/// <para lang="zh">字符串搜索元数据类</para>
/// <para lang="en">String search meta data class</para>
/// </summary>
public class StringSearchMetadata : SearchMetadataBase
public class StringSearchMetadata : SearchFormItemMetadataBase
{
/// <summary>
/// <para lang="zh">获得/设置 搜索值</para>
Expand Down
4 changes: 3 additions & 1 deletion src/BootstrapBlazor/Components/Table/Table.razor
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,9 @@
<BodyTemplate>
@if (UseSearchForm)
{
<SearchForm Items="SearchFormItems"
<SearchForm Items="SearchFormItems" RowType="SearchDialogRowType" ItemsPerRow="SearchDialogItemsPerRow"
LabelAlign="SearchDialogLabelAlign" ShowLabel="true" ShowUnsetGroupItemsOnTop="ShowUnsetGroupItemsOnTop"
SearchFormLocalizerOptions="SearchFormLocalizerOptions"
OnChanged="OnSearchFormFilterChanged">
</SearchForm>
}
Expand Down
10 changes: 1 addition & 9 deletions src/BootstrapBlazor/Components/Table/Table.razor.Search.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,7 @@ private List<ISearchItem> GetSearchFormItems()

if (SearchFormLocalizerOptions is null)
{
SearchFormLocalizerOptions = new SearchFormLocalizerOptions()
{
SelectAllText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.SelectAllText)],
BooleanAllText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.BooleanAllText)],
BooleanTrueText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.BooleanTrueText)],
BooleanFalseText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.BooleanFalseText)],
NumberStartValueLabelText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.NumberStartValueLabelText)],
NumberEndValueLabelText = SearchFormLocalizer[nameof(Components.SearchFormLocalizerOptions.NumberEndValueLabelText)]
};
SearchFormLocalizerOptions = SearchFormLocalizer.GetSearchFormLocalizerOptions();
}
return GetSearchColumns().Select(i => i.ParseSearchItem(SearchFormLocalizerOptions.Value)).ToList();
}
Expand Down
4 changes: 2 additions & 2 deletions src/BootstrapBlazor/Extensions/ISearchItemExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ public ISearchFormItemMetadata BuildSearchMetadata(SearchFormLocalizerOptions op
}

/// <summary>
/// <para lang="zh">创建 搜索项的 RenderFragment 实例</para>
/// <para lang="en">Creates a RenderFragment instance for the search item</para>
/// <para lang="zh">通过 SearchItem 实例 Metadata 创建搜索项 UI 方法</para>
/// <para lang="en">Creates a search item UI method through the SearchItem instance Metadata</para>
/// </summary>
public RenderFragment CreateSearchItemComponentByMetadata() => builder =>
{
Expand Down
16 changes: 16 additions & 0 deletions src/BootstrapBlazor/Extensions/IStringLocalizerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,20 @@ public static bool TryGetLocalizerString(this IStringLocalizer localizer, string
}
return ret;
}

/// <summary>
/// <para lang="zh">通过资源文件获取 SearchFormLocalizerOptions 实例</para>
/// <para lang="en">Get the SearchFormLocalizerOptions instance from the resource file</para>
/// </summary>
/// <param name="localizer"></param>
/// <returns></returns>
public static SearchFormLocalizerOptions GetSearchFormLocalizerOptions(this IStringLocalizer<SearchFormLocalizerOptions> localizer) => new SearchFormLocalizerOptions()
{
SelectAllText = localizer[nameof(Components.SearchFormLocalizerOptions.SelectAllText)],
BooleanAllText = localizer[nameof(Components.SearchFormLocalizerOptions.BooleanAllText)],
BooleanTrueText = localizer[nameof(Components.SearchFormLocalizerOptions.BooleanTrueText)],
BooleanFalseText = localizer[nameof(Components.SearchFormLocalizerOptions.BooleanFalseText)],
NumberStartValueLabelText = localizer[nameof(Components.SearchFormLocalizerOptions.NumberStartValueLabelText)],
NumberEndValueLabelText = localizer[nameof(Components.SearchFormLocalizerOptions.NumberEndValueLabelText)]
};
}
36 changes: 36 additions & 0 deletions test/UnitTest/Components/SearchFormTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,40 @@ public void Reset_Ok()
// Metadata 为空时不报错
item.Reset();
}

[Fact]
public async Task CustomMetadata_Ok()
{
var filterKeyValueAction = new FilterKeyValueAction();
var cut = Context.Render<SearchForm>(pb =>
{
pb.Add(a => a.OnChanged, action =>
{
filterKeyValueAction = action;
return Task.CompletedTask;
});
pb.Add(a => a.Items, new List<ISearchItem>()
{
new SearchItem(nameof(Foo.Name), typeof(string), "Name")
{
Metadata = new CustomeMetadata() { Value = "foo-name-value" }
}
});
});

cut.Contains("value=\"foo-name-value\"");
}

class CustomeMetadata : StringSearchMetadata
{
public override RenderFragment? RenderContent() => builder =>
{
builder.OpenComponent<BootstrapInput<string>>(0);
builder.AddAttribute(10, nameof(BootstrapInput<>.Value), Value);
builder.AddAttribute(20, nameof(BootstrapInput<>.OnValueChanged), ValueChangedHandler);
builder.AddAttribute(30, nameof(BootstrapInput<>.ShowLabel), true);
builder.AddAttribute(60, nameof(BootstrapInput<>.SkipValidate), true);
builder.CloseComponent();
};
}
}
Loading