mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-12-02 20:17:58 +08:00
5fd4aa9a7d
* feat: add auto-complete component * Select 组件 1. 组件支持双向绑定 2. 优化效率 3. 修复多选模式点击时下拉面板折叠问题 Co-authored-by: ElderJames <shunjiey@hotmail.com>
204 lines
9.6 KiB
C#
204 lines
9.6 KiB
C#
@namespace AntDesign
|
|
@inherits AntInputComponentBase<string>
|
|
|
|
<CascadingValue Value=this>
|
|
<div class="@ClassMapper.Class" style="@Style" id="@Id" title="@Title" tabindex="-1" @onclick="OnSelectOpenClick" @ref="Ref">
|
|
@switch (SelectMode)
|
|
{
|
|
case SelectMode.Default:
|
|
{
|
|
var selectedOption = SelectedOptions.FirstOrDefault();
|
|
<div class="@ClassPrefix-selector">
|
|
<span class="@ClassPrefix-selection-search">
|
|
<input @ref="_inputRef"
|
|
@oninput="OnInput" @onblur="OnInputBlur"
|
|
id="@Id"
|
|
value="@_searchValue"
|
|
role="combobox"
|
|
readonly="@(!_isSelectOpened)"
|
|
class="@ClassPrefix-selection-search-input"
|
|
style="@(_isSelectOpened ? "" : "opacity:0")"
|
|
autocomplete="off"
|
|
aria-owns="@(Id)_list"
|
|
aria-expanded="@_isSelectOpened"
|
|
aria-autocomplete="list"
|
|
aria-controls="@(Id)_list" />
|
|
</span>
|
|
@if (ShowPlaceholder)
|
|
{
|
|
<span class="ant-select-selection-placeholder">@Placeholder</span>
|
|
}
|
|
else if (string.IsNullOrEmpty(_searchValue) && selectedOption != null)
|
|
{
|
|
var showValue = GetShowValue(selectedOption);
|
|
@if (showValue.IsT0)
|
|
{
|
|
<span class="ant-select-selection-item">@showValue.AsT0 </span>
|
|
}
|
|
else
|
|
{
|
|
<span class="ant-select-selection-item">@showValue.AsT1 </span>
|
|
}
|
|
}
|
|
</div>
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
<div class="@ClassPrefix-selector">
|
|
@foreach (var option in SelectedOptions)
|
|
{
|
|
if (TagRender != null)
|
|
{
|
|
<span>@TagRender(GetProperties(option))</span>
|
|
}
|
|
else
|
|
{
|
|
var showValue = GetShowValue(option);
|
|
<span class="@ClassPrefix-selection-item">
|
|
<span class="@ClassPrefix-selection-item-content">
|
|
@if (showValue.IsT0)
|
|
{
|
|
@showValue.AsT0
|
|
}
|
|
else
|
|
{
|
|
@showValue.AsT1
|
|
}
|
|
</span>
|
|
|
|
<span unselectable="on" aria-hidden="true" style="user-select: none;" class="@ClassPrefix-selection-item-remove"
|
|
@onclick="()=>OnRemoveSelected(option)" @onclick:stopPropagation="true">
|
|
<Icon Type="close"></Icon>
|
|
</span>
|
|
</span>
|
|
}
|
|
}
|
|
<span class="@ClassPrefix-selection-search" style="width:@_inputWidth">
|
|
<input @ref="_inputRef"
|
|
@oninput="OnInput" @onblur="OnInputBlur"
|
|
@bind-value="@_searchValue"
|
|
id="@Id"
|
|
role="combobox"
|
|
readonly="@(!_isSelectOpened)"
|
|
class="@ClassPrefix-selection-search-input"
|
|
style="@(_isSelectOpened?"":"opacity:0")"
|
|
autocomplete="off"
|
|
aria-owns="@(Id)_list"
|
|
aria-expanded="@_isSelectOpened"
|
|
aria-autocomplete="list"
|
|
aria-controls="@(Id)_list" />
|
|
<span class="@ClassPrefix-selection-search-mirror" aria-hidden="true"> </span>
|
|
</span>
|
|
@if (ShowPlaceholder)
|
|
{
|
|
<span class="ant-select-selection-placeholder">@Placeholder</span>
|
|
}
|
|
</div>
|
|
break;
|
|
}
|
|
}
|
|
|
|
@if (ShowArrow && SelectMode == SelectMode.Default)
|
|
{
|
|
if (SuffixIcon != null)
|
|
{
|
|
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;">
|
|
@SuffixIcon
|
|
</span>
|
|
}
|
|
else if (Loading)
|
|
{
|
|
<span class="ant-select-arrow ant-select-arrow-loading" unselectable="on" aria-hidden="true" style="user-select: none;">
|
|
<Icon Type="loading"></Icon>
|
|
</span>
|
|
}
|
|
else
|
|
{
|
|
<span class="ant-select-arrow" unselectable="on" aria-hidden="true" style="user-select: none;">
|
|
@if (ShowSearch && _isSelectOpened)
|
|
{
|
|
<Icon Type="search"></Icon>
|
|
}
|
|
else
|
|
{
|
|
<Icon Type="down"></Icon>
|
|
}
|
|
</span>
|
|
@if (AllowClear && HasValue)
|
|
{
|
|
<span class="ant-select-clear" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="OnClearClick">
|
|
<Icon Type="close-circle"></Icon>
|
|
</span>
|
|
}
|
|
}
|
|
}
|
|
</div>
|
|
<div style="position: absolute; top: 0px; left: 0px; width: 100%;" @ref="_dropdownRef">
|
|
<div>
|
|
<div class="@(ClassPrefix)-dropdown @_dropdownClassMapper.Class" style="@_dropdownStyle" tabindex="-1"
|
|
@onblur="OnSelectHideClick" @onmouseenter="OnSelectMouseEnter" @onmouseleave="OnSelectMouseLeave">
|
|
<div>
|
|
@if (IsEmptyOnSearch())
|
|
{
|
|
<div role="listbox" id="@(Id)_list" class="@ClassPrefix-item-empty">
|
|
@if (NotFoundContent != null)
|
|
{
|
|
@NotFoundContent
|
|
}
|
|
else
|
|
{
|
|
<Empty Image="Empty.PRESENTED_IMAGE_SIMPLE" Small="true" />
|
|
}
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div role="listbox" id="@(Id)_list" style="height: 0px; width: 0px; overflow: hidden;">
|
|
@for (var i = 0; SelectOptions.Count > i; ++i)
|
|
{
|
|
var selectOption = SelectOptions[i];
|
|
<div id="@(Id)_list_@(i)" role="option" aria-label="@selectOption.Value" aria-selected="@GetAriaSelected(selectOption)">@selectOption.Value</div>
|
|
}
|
|
</div>
|
|
<div class="" style="max-height:256px; overflow-y:auto;">
|
|
<div>
|
|
<div class="" style="display: flex; flex-direction: column;">
|
|
@if (IsCreatedTagOption())
|
|
{
|
|
<SelectOption Value="@_searchValue" IsSearch="true">@_searchValue </SelectOption>
|
|
}
|
|
|
|
@ChildContent
|
|
|
|
@if (Options != null && Options.Any())
|
|
{
|
|
foreach (var option in Options)
|
|
{
|
|
<SelectOption Value="@option.Key">@option.Label</SelectOption>
|
|
}
|
|
}
|
|
|
|
@if (IsTagMode)
|
|
{
|
|
var tagOptions = new SortedSet<string>(_tagSelectOptions.Select(option => option.Value).Union(_tokenSelectOptions));
|
|
@foreach (var tag in tagOptions)
|
|
{
|
|
<SelectOption Value="@tag" IsTag="true">@tag </SelectOption>
|
|
}
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
if (DropdownRender != null)
|
|
{
|
|
@DropdownRender(default, default);
|
|
}
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CascadingValue>
|