mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-12-02 20:17:58 +08:00
fix(module TreeSelect): search not working on TreeSelect (#2686)
* Added the implementation like select to use tree search funcionality. Trying to change minimum posible to make it work. Add ignoreCase for search on tree and fix display of match to respect the original value. * Add a example of search.
This commit is contained in:
parent
c8496a3d9d
commit
7f9365d71f
@ -45,6 +45,10 @@
|
||||
ChildrenExpression="ChildrenExpression"
|
||||
DisabledExpression="DisabledExpression"
|
||||
DefaultExpandAll="TreeDefaultExpandAll"
|
||||
SearchExpression="SearchExpression"
|
||||
MatchedStyle="@MatchedStyle"
|
||||
MatchedClass="@MatchedClass"
|
||||
SearchValue="@_searchValue"
|
||||
>
|
||||
<Nodes>
|
||||
@if (IsTemplatedNodes)
|
||||
@ -66,8 +70,9 @@
|
||||
<CascadingValue Value="@LabelTemplate" Name="ParentLabelTemplate">
|
||||
<CascadingValue Value="@ShowSearchIcon" Name="ShowSearchIcon">
|
||||
<CascadingValue Value="@ShowArrowIcon" Name="ShowArrowIcon">
|
||||
<SelectContent Prefix="ant-select"
|
||||
<SelectContent Prefix="@ClassPrefix"
|
||||
RefBack="@context"
|
||||
@ref="_selectContent"
|
||||
TItemValue="string"
|
||||
TItem="TItem"
|
||||
SearchValue="@_searchValue"
|
||||
|
@ -40,6 +40,8 @@ namespace AntDesign
|
||||
|
||||
[Parameter] public Action OnMouseLeave { get; set; }
|
||||
|
||||
[Parameter] public Action OnBlur { get; set; }
|
||||
|
||||
[Parameter] public RenderFragment<TItem> LabelTemplate { get; set; }
|
||||
|
||||
[Parameter] public bool ShowSearchIcon { get; set; } = true;
|
||||
@ -53,9 +55,14 @@ namespace AntDesign
|
||||
[Parameter] public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter] public bool TreeDefaultExpandAll { get; set; }
|
||||
|
||||
[Parameter] public Func<TreeNode<TItem>, bool> SearchExpression { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string RootValue { get; set; } = "0";
|
||||
[Parameter] public string MatchedStyle { get; set; } = string.Empty;
|
||||
|
||||
[Parameter] public string MatchedClass {get; set; }
|
||||
|
||||
[Parameter] public string RootValue { get; set; } = "0";
|
||||
|
||||
[Parameter] public OneOf<bool, string> DropdownMatchSelectWidth { get; set; } = true;
|
||||
|
||||
@ -107,6 +114,8 @@ namespace AntDesign
|
||||
[Parameter]
|
||||
public Func<TreeNode<TItem>, bool> DisabledExpression { get; set; }
|
||||
|
||||
private const string ClassPrefix = "ant-select";
|
||||
|
||||
private bool IsMultiple => Multiple || TreeCheckable;
|
||||
|
||||
private bool IsTemplatedNodes => ChildContent != null;
|
||||
@ -246,6 +255,20 @@ namespace AntDesign
|
||||
|
||||
protected async void OnInputAsync(ChangeEventArgs e)
|
||||
{
|
||||
if (e == null) throw new ArgumentNullException(nameof(e));
|
||||
if (!IsSearchEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_dropDown.IsOverlayShow())
|
||||
{
|
||||
await _dropDown.Show();
|
||||
}
|
||||
|
||||
_prevSearchValue = _searchValue;
|
||||
_searchValue = e.Value?.ToString();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
protected async Task OnKeyUpAsync(KeyboardEventArgs e)
|
||||
@ -254,10 +277,26 @@ namespace AntDesign
|
||||
|
||||
protected async Task OnInputFocusAsync(FocusEventArgs _)
|
||||
{
|
||||
await SetInputFocusAsync();
|
||||
}
|
||||
|
||||
protected async Task OnInputBlurAsync(FocusEventArgs _)
|
||||
{
|
||||
await SetInputBlurAsync();
|
||||
}
|
||||
|
||||
protected async Task SetInputBlurAsync()
|
||||
{
|
||||
if (Focused)
|
||||
{
|
||||
Focused = false;
|
||||
|
||||
SetClassMap();
|
||||
|
||||
await JsInvokeAsync(JSInteropConstants.Blur, _inputRef);
|
||||
|
||||
OnBlur?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnOverlayVisibleChangeAsync(bool visible)
|
||||
@ -265,6 +304,12 @@ namespace AntDesign
|
||||
if (visible)
|
||||
{
|
||||
await SetDropdownStyleAsync();
|
||||
|
||||
await SetInputFocusAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
OnOverlayHide();
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,24 +409,23 @@ namespace AntDesign
|
||||
|
||||
protected override void SetClassMap()
|
||||
{
|
||||
var classPrefix = "ant-select";
|
||||
ClassMapper
|
||||
.Add(classPrefix)
|
||||
.Add("ant-tree-select")
|
||||
.If("ant-select-lg", () => Size == "large")
|
||||
.If("ant-select-sm", () => Size == "small")
|
||||
.If("ant-select-rtl", () => RTL)
|
||||
.If("ant-select-disabled", () => Disabled)
|
||||
.If("ant-select-single", () => SelectMode == SelectMode.Default)
|
||||
.If("ant-select-multiple", () => SelectMode != SelectMode.Default)
|
||||
.If("ant-select-show-arrow", () => !IsMultiple)
|
||||
.If("ant-select-show-search", () => !IsMultiple)
|
||||
.If("ant-select-allow-clear", () => AllowClear)
|
||||
.If("ant-select-open", () => Open)
|
||||
.If("ant-select-focused", () => Open || Focused)
|
||||
.If("ant-select-status-error", () => Status == "error")
|
||||
.If("ant-select-status-warning", () => Status == "warning")
|
||||
.If($"{classPrefix}-status-error", () => ValidationMessages.Length > 0)
|
||||
.Add($"{ClassPrefix}")
|
||||
.If($"{ClassPrefix}-open", () => _dropDown?.IsOverlayShow() ?? false)
|
||||
.If($"{ClassPrefix}-focused", () => Focused)
|
||||
.If($"{ClassPrefix}-single", () => SelectMode == SelectMode.Default)
|
||||
.If($"{ClassPrefix}-multiple", () => SelectMode != SelectMode.Default)
|
||||
.If($"{ClassPrefix}-sm", () => Size == AntSizeLDSType.Small)
|
||||
.If($"{ClassPrefix}-lg", () => Size == AntSizeLDSType.Large)
|
||||
.If($"{ClassPrefix}-show-arrow", () => ShowArrowIcon)
|
||||
.If($"{ClassPrefix}-show-search", () => IsSearchEnabled)
|
||||
.If($"{ClassPrefix}-loading", () => Loading)
|
||||
.If($"{ClassPrefix}-disabled", () => Disabled)
|
||||
.If($"{ClassPrefix}-rtl", () => RTL)
|
||||
.If($"{ClassPrefix}-status-error", () => ValidationMessages.Length > 0)
|
||||
.If($"{ClassPrefix}-status-warning", () => Status == "warning")
|
||||
.If($"{ClassPrefix}-allow-clear", () => AllowClear)
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -409,8 +409,11 @@ namespace AntDesign
|
||||
get => _searchValue;
|
||||
set
|
||||
{
|
||||
_searchValue = value;
|
||||
SearchNodes();
|
||||
if (value != _searchValue)
|
||||
{
|
||||
_searchValue = value;
|
||||
SearchNodes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,7 +440,7 @@ namespace AntDesign
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(_searchValue))
|
||||
{
|
||||
searchDatas = allList.Where(x => x.Title.Contains(_searchValue)).ToList();
|
||||
searchDatas = allList.Where(x => x.Title.Contains(_searchValue, StringComparison.InvariantCultureIgnoreCase)).ToList();
|
||||
}
|
||||
|
||||
if (searchDatas != null && searchDatas.Any())
|
||||
|
@ -41,10 +41,13 @@
|
||||
}
|
||||
else if (SelfNode.Matched && !string.IsNullOrWhiteSpace(TreeComponent.SearchValue))
|
||||
{
|
||||
var value = $"<span class=\"{TreeComponent.MatchedClass}\" style=\"{TreeComponent.MatchedStyle}\">{TreeComponent.SearchValue}</span>";
|
||||
|
||||
int index = SelfNode.Title.IndexOf(TreeComponent.SearchValue, StringComparison.InvariantCultureIgnoreCase);
|
||||
var start = SelfNode.Title.Substring(0, index);
|
||||
var match = SelfNode.Title.Substring(index, TreeComponent.SearchValue.Length);
|
||||
var end = SelfNode.Title.Substring(index + TreeComponent.SearchValue.Length);
|
||||
var value = $"{start}<span class=\"{TreeComponent.MatchedClass}\" style=\"{TreeComponent.MatchedStyle}\">{match}</span>{end}";
|
||||
<span>
|
||||
@((MarkupString)SelfNode.Title.Replace(TreeComponent.SearchValue, value))
|
||||
@((MarkupString)value)
|
||||
</span>
|
||||
}
|
||||
else
|
||||
@ -98,10 +101,13 @@ else
|
||||
<span class="ant-tree-title">
|
||||
@if (SelfNode.Matched && !string.IsNullOrWhiteSpace(TreeComponent.SearchValue))
|
||||
{
|
||||
var value = $"<span class=\"{TreeComponent.MatchedClass}\" style=\"{TreeComponent.MatchedStyle}\">{TreeComponent.SearchValue}</span>";
|
||||
var regex = new Regex(TreeComponent.SearchValue);
|
||||
int index = SelfNode.Title.IndexOf(TreeComponent.SearchValue, StringComparison.InvariantCultureIgnoreCase);
|
||||
var start = SelfNode.Title.Substring(0, index);
|
||||
var match = SelfNode.Title.Substring(index, TreeComponent.SearchValue.Length);
|
||||
var end = SelfNode.Title.Substring(index + TreeComponent.SearchValue.Length);
|
||||
var value = $"{start}<span class=\"{TreeComponent.MatchedClass}\" style=\"{TreeComponent.MatchedStyle}\">{match}</span>{end}";
|
||||
<span>
|
||||
@((MarkupString)regex.Replace(SelfNode.Title,value,1))
|
||||
@((MarkupString)value)
|
||||
</span>
|
||||
}
|
||||
else
|
||||
|
@ -0,0 +1,28 @@
|
||||
<TreeSelect TItem="string"
|
||||
Style="width:100%;"
|
||||
@bind-Values="values"
|
||||
DropdownStyle="max-height:400px;overflow:auto;"
|
||||
Placeholder="Please select"
|
||||
AllowClear
|
||||
Multiple
|
||||
TreeDefaultExpandAll
|
||||
EnableSearch
|
||||
MatchedStyle="font-weight: bold">
|
||||
<TreeNode TItem="string" Key="parent 1" Title="parent 1">
|
||||
<TreeNode TItem="string" Key="parent 1-0" Title="parent 1-0">
|
||||
<TreeNode TItem="string" Key="leaf1" Title="my leaf" />
|
||||
<TreeNode TItem="string" Key="leaf2" Title="your leaf" />
|
||||
</TreeNode>
|
||||
<TreeNode TItem="string" Key="parent 1-1" Title="parent 1-1">
|
||||
<TreeNode TItem="string" Key="leaf3" Title="Leaf3"/>
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</TreeSelect>
|
||||
|
||||
@JsonSerializer.Serialize(values);
|
||||
|
||||
@code {
|
||||
|
||||
private IEnumerable<string> values=new[]{"leaf1","leaf2"};
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 带搜索的多项选择
|
||||
en-US: Multiple with search
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
多项选择搜索使用。
|
||||
|
||||
## en-US
|
||||
|
||||
Multiple selection search usage.
|
Loading…
Reference in New Issue
Block a user