Skip to content

Commit 24fc677

Browse files
authored
fix(Select): add composition support (#4847)
* refactor: 复用搜索栏 * refactor: 更改搜索回调未客户端 * fix: 修复汉字导致搜索高频触发问题
1 parent f96b827 commit 24fc677

File tree

3 files changed

+50
-23
lines changed

3 files changed

+50
-23
lines changed

src/BootstrapBlazor/Components/Select/Select.razor

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@
3131
<span class="@ClearClassString" @onclick="OnClearValue"><i class="@ClearIcon"></i></span>
3232
}
3333
<div class="dropdown-menu">
34+
@if (ShowSearch)
35+
{
36+
<div class="@SearchClassString">
37+
<input type="text" class="search-text form-control" autocomplete="off" value="@SearchText" aria-label="Search">
38+
<i class="@SearchIconString"></i>
39+
</div>
40+
}
3441
@if (IsVirtualize)
3542
{
36-
@if (ShowSearch)
37-
{
38-
<div class="@SearchClassString">
39-
<input type="text" class="search-text form-control" autocomplete="off" value="@SearchText" @oninput="EventCallback.Factory.CreateBinder<string>(this, async v => await SearchTextChanged(v), SearchText)" aria-label="Search">
40-
<i class="@SearchIconString"></i>
41-
</div>
42-
}
4343
<div class="dropdown-virtual">
4444
@if (OnQueryAsync == null)
4545
{
@@ -53,13 +53,6 @@
5353
}
5454
else
5555
{
56-
@if (ShowSearch)
57-
{
58-
<div class="@SearchClassString">
59-
<input type="text" class="search-text form-control" autocomplete="off" value="@SearchText" @oninput="EventCallback.Factory.CreateBinder<string>(this, async v => await SearchTextChanged(v), SearchText)" aria-label="Search">
60-
<i class="@SearchIconString"></i>
61-
</div>
62-
}
6356
@foreach (var itemGroup in Rows.GroupBy(i => i.GroupName))
6457
{
6558
if (!string.IsNullOrEmpty(itemGroup.Key))

src/BootstrapBlazor/Components/Select/Select.razor.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,8 @@ private async ValueTask<ItemsProviderResult<SelectedItem>> LoadItems(ItemsProvid
354354

355355
private async Task SearchTextChanged(string val)
356356
{
357-
SearchText = val;
358357
_itemsCache = null;
359-
358+
SearchText = val;
360359
if (OnQueryAsync != null)
361360
{
362361
// 通过 ItemProvider 提供数据
@@ -399,7 +398,7 @@ private bool TryParseSelectItem(string value, [MaybeNullWhen(false)] out TValue
399398
/// <inheritdoc/>
400399
/// </summary>
401400
/// <returns></returns>
402-
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(ConfirmSelectedItem));
401+
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, new { ConfirmMethodCallback = nameof(ConfirmSelectedItem), SearchMethodCallback = nameof(TriggerOnSearch) });
403402

404403
/// <summary>
405404
/// 客户端回车回调方法
@@ -416,6 +415,18 @@ public async Task ConfirmSelectedItem(int index)
416415
}
417416
}
418417

418+
/// <summary>
419+
/// 客户端搜索栏回调方法
420+
/// </summary>
421+
/// <param name="searchText"></param>
422+
/// <returns></returns>
423+
[JSInvokable]
424+
public async Task TriggerOnSearch(string searchText)
425+
{
426+
await SearchTextChanged(searchText);
427+
StateHasChanged();
428+
}
429+
419430
/// <summary>
420431
/// 下拉框选项点击时调用此方法
421432
/// </summary>

src/BootstrapBlazor/Components/Select/Select.razor.js

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { getHeight, getInnerHeight, getTransitionDelayDurationFromElement } from "../../modules/utility.js"
1+
import { debounce, getHeight, getInnerHeight, getTransitionDelayDurationFromElement } from "../../modules/utility.js"
22
import Data from "../../modules/data.js"
33
import EventHandler from "../../modules/event-handler.js"
44
import Popover from "../../modules/base-popover.js"
55

6-
export function init(id, invoke, method) {
6+
export function init(id, invoke, options) {
77
const el = document.getElementById(id)
8-
8+
const { confirmMethodCallback, searchMethodCallback } = options;
99
if (el == null) {
1010
return
1111
}
@@ -64,7 +64,7 @@ export function init(id, invoke, method) {
6464
if (e.key === "Enter") {
6565
popover.toggleMenu.classList.remove('show')
6666
let index = indexOf(el, activeItem)
67-
invoke.invokeMethodAsync(method, index)
67+
invoke.invokeMethodAsync(confirmMethodCallback, index)
6868
}
6969
}
7070
}
@@ -77,7 +77,27 @@ export function init(id, invoke, method) {
7777
el,
7878
popover
7979
}
80-
Data.set(id, select)
80+
Data.set(id, select);
81+
82+
const onSearch = debounce(v => invoke.invokeMethodAsync(searchMethodCallback, v));
83+
let isComposing = false;
84+
85+
EventHandler.on(el, 'input', '.search-text', e => {
86+
if (isComposing) {
87+
return;
88+
}
89+
90+
onSearch(e.delegateTarget.value);
91+
});
92+
93+
EventHandler.on(el, 'compositionstart', '.search-text', e => {
94+
isComposing = true;
95+
});
96+
97+
EventHandler.on(el, 'compositionend', '.search-text', e => {
98+
isComposing = false;
99+
onSearch(e.delegateTarget.value);
100+
});
81101
}
82102

83103
export function show(id) {
@@ -108,7 +128,10 @@ export function dispose(id) {
108128

109129
if (select) {
110130
EventHandler.off(select.el, 'shown.bs.dropdown')
111-
EventHandler.off(select.el, 'keydown')
131+
EventHandler.off(select.el, 'keydown');
132+
EventHandler.off(select.el, 'input');
133+
EventHandler.off(select.el, 'compositionstart');
134+
EventHandler.off(select.el, 'compositionend')
112135
Popover.dispose(select.popover)
113136
}
114137
}

0 commit comments

Comments
 (0)