diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index bee27a533e7..dc8572088a4 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@  - 9.4.8 + 9.4.9-beta01 diff --git a/src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor b/src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor index 04416dc2b20..7286758dfe9 100644 --- a/src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor +++ b/src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor @@ -16,7 +16,12 @@ placeholder="@PlaceHolder" disabled="@Disabled" @ref="FocusElement"/> - ; +} diff --git a/src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor.cs b/src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor.cs index 1d9f4e5e50d..a1e7a8b0921 100644 --- a/src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor.cs +++ b/src/BootstrapBlazor/Components/AutoComplete/AutoComplete.razor.cs @@ -89,6 +89,9 @@ public partial class AutoComplete private List? _filterItems; + [NotNull] + private AutoCompleteItems? _dropdown = default; + /// /// /// @@ -114,12 +117,21 @@ protected override void OnParametersSet() Items ??= []; } + private bool _render = true; + + /// + /// + /// + /// + protected override bool ShouldRender() => _render; + /// /// Callback method when a candidate item is clicked /// private async Task OnClickItem(string val) { CurrentValue = val; + if (OnSelectedItemChanged != null) { await OnSelectedItemChanged(val); @@ -135,9 +147,6 @@ private async Task OnClickItem(string val) [JSInvokable] public override async Task TriggerFilter(string val) { - // Store the current input value to prevent it from being overwritten - var currentInputValue = val; - if (OnCustomFilter != null) { var items = await OnCustomFilter(val); @@ -161,14 +170,7 @@ public override async Task TriggerFilter(string val) _filterItems = [.. _filterItems.Take(DisplayCount.Value)]; } - // Use currentInputValue here instead of potentially stale val - CurrentValue = currentInputValue; - - // Only trigger StateHasChanged if no binding is present - if (!ValueChanged.HasDelegate) - { - StateHasChanged(); - } + await TriggerChange(val); } /// @@ -178,16 +180,22 @@ public override async Task TriggerFilter(string val) [JSInvokable] public override Task TriggerChange(string val) { - // Only update CurrentValue if the value has actually changed - // This prevents overwriting the user's input - if (CurrentValue != val) + _render = false; + CurrentValue = val; + if (!ValueChanged.HasDelegate) { - CurrentValue = val; - if (!ValueChanged.HasDelegate) - { - StateHasChanged(); - } + StateHasChanged(); } + _render = true; + _dropdown.RenderContent(); return Task.CompletedTask; } + + private RenderFragment RenderItems => builder => + { + builder.OpenComponent(0); + builder.AddAttribute(10, "ChildContent", RenderDropdown); + builder.AddComponentReferenceCapture(20, dropdown => _dropdown = (AutoCompleteItems)dropdown); + builder.CloseComponent(); + }; } diff --git a/src/BootstrapBlazor/Components/AutoComplete/AutoCompleteItems.cs b/src/BootstrapBlazor/Components/AutoComplete/AutoCompleteItems.cs new file mode 100644 index 00000000000..d2839dc4ce4 --- /dev/null +++ b/src/BootstrapBlazor/Components/AutoComplete/AutoCompleteItems.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +using Microsoft.AspNetCore.Components.Rendering; + +namespace BootstrapBlazor.Components; + +/// +/// AutoCompleteItems component +/// +class AutoCompleteItems : IComponent +{ + /// + /// Gets or sets the child content + /// + [Parameter, NotNull] + public RenderFragment? ChildContent { get; set; } + + private RenderHandle _renderHandle; + + /// + /// + /// + /// + public void Attach(RenderHandle renderHandle) + { + _renderHandle = renderHandle; + } + + /// + /// + /// + /// + /// + public Task SetParametersAsync(ParameterView parameters) + { + parameters.SetParameterProperties(this); + + RenderContent(); + return Task.CompletedTask; + } + /// + /// Render method + /// + public void RenderContent() + { + _renderHandle.Render(BuildRenderTree); + } + + /// + /// + /// + /// + private void BuildRenderTree(RenderTreeBuilder builder) + { + builder.AddContent(0, ChildContent); + } +}