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:
Magehernan 2022-09-12 21:57:23 -03:00 committed by GitHub
parent c8496a3d9d
commit 7f9365d71f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 28 deletions

View File

@ -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"

View File

@ -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)
;
}

View File

@ -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())

View File

@ -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

View File

@ -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"};
}

View File

@ -0,0 +1,14 @@
---
order: 1
title:
zh-CN: 带搜索的多项选择
en-US: Multiple with search
---
## zh-CN
多项选择搜索使用。
## en-US
Multiple selection search usage.