diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml index 9da128204b..8583f4421f 100644 --- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml +++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml @@ -5660,6 +5660,12 @@ Default is false. + + + Gets or sets whether the drop-down panel stays open after selecting an item, + until the number of selected items reaches the maximum (only using the mouse). + + @@ -5714,6 +5720,9 @@ + + + diff --git a/examples/Demo/Shared/Pages/List/Autocomplete/Examples/AutocompleteCustomized.razor b/examples/Demo/Shared/Pages/List/Autocomplete/Examples/AutocompleteCustomized.razor index dbf799e84e..9315d477f1 100644 --- a/examples/Demo/Shared/Pages/List/Autocomplete/Examples/AutocompleteCustomized.razor +++ b/examples/Demo/Shared/Pages/List/Autocomplete/Examples/AutocompleteCustomized.razor @@ -7,6 +7,7 @@ Placeholder="search" OnOptionsSearch="@OnSearch" MaximumSelectedOptions="3" + KeepOpen="true" OptionText="@(item => item.FirstName)" OptionStyle="min-height: 40px;" @bind-SelectedOptions="@SelectedItems"> diff --git a/src/Core/Components/List/FluentAutocomplete.razor.cs b/src/Core/Components/List/FluentAutocomplete.razor.cs index d1eb72148c..8e1c34f2de 100644 --- a/src/Core/Components/List/FluentAutocomplete.razor.cs +++ b/src/Core/Components/List/FluentAutocomplete.razor.cs @@ -224,6 +224,13 @@ public override bool Multiple [Parameter] public bool SelectValueOnTab { get; set; } = false; + /// + /// Gets or sets whether the drop-down panel stays open after selecting an item, + /// until the number of selected items reaches the maximum (only using the mouse). + /// + [Parameter] + public bool KeepOpen { get; set; } = false; + /// private string? ListStyleValue => new StyleBuilder() .AddStyle("width", Width, when: !string.IsNullOrEmpty(Width)) @@ -287,6 +294,7 @@ protected override async Task InputHandlerAsync(ChangeEventArgs e) if (MaximumSelectedOptions > 0 && SelectedOptions?.Count() >= MaximumSelectedOptions) { IsReachedMaxItems = true; + RenderComponent(); return; } @@ -319,8 +327,14 @@ protected override async Task InputHandlerAsync(ChangeEventArgs e) await VirtualizationContainer.RefreshDataAsync(); } - _shouldRender = true; - StateHasChanged(); + RenderComponent(); + + // Activate the rendering + void RenderComponent() + { + _shouldRender = true; + StateHasChanged(); + } } private ValueTask> LoadFilteredItemsAsync(ItemsProviderRequest request) @@ -534,9 +548,13 @@ protected override async Task OnSelectedItemChangedHandlerAsync(TOption? item) ValueText = string.Empty; await RaiseValueTextChangedAsync(ValueText); - IsMultiSelectOpened = false; await base.OnSelectedItemChangedHandlerAsync(item); await DisplayLastSelectedItemAsync(); + + if (MustBeClosed()) + { + IsMultiSelectOpened = false; + } } /// @@ -619,4 +637,25 @@ private async Task RaiseValueTextChangedAsync(string value) } } + + /// + private bool MustBeClosed() + { + if (KeepOpen == false) + { + return true; + } + + if (MaximumSelectedOptions is null || MaximumSelectedOptions <= 1) + { + return true; + } + + if (MaximumSelectedOptions > 0 && _selectedOptions.Count >= MaximumSelectedOptions) + { + return true; + } + + return false; + } } diff --git a/src/Core/Components/List/ListComponentBase.razor.cs b/src/Core/Components/List/ListComponentBase.razor.cs index eaea5bae0d..51caceb484 100644 --- a/src/Core/Components/List/ListComponentBase.razor.cs +++ b/src/Core/Components/List/ListComponentBase.razor.cs @@ -22,7 +22,7 @@ public abstract partial class ListComponentBase : FluentInputBase _selectedOptions = []; + protected List _selectedOptions = []; protected TOption? _currentSelectedOption; protected readonly RenderFragment _renderOptions;