Skip to content

Commit 8d3f795

Browse files
authoredApr 19, 2025
Autocomplete - close the dropdown via code (#3715)
* Added a method to close the dropdown via code. * Added a demo page showing how to invoke the 'CloseDropdownAsync' method. * Added a unit test.
1 parent 53f33c9 commit 8d3f795

7 files changed

+134
-0
lines changed
 

‎examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml

+6
Original file line numberDiff line numberDiff line change
@@ -6063,6 +6063,12 @@
60636063
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentAutocomplete`1.ShouldRender">
60646064
<summary />
60656065
</member>
6066+
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentAutocomplete`1.CloseDropdownAsync">
6067+
<summary>
6068+
Closes the multiselect dropdown.
6069+
</summary>
6070+
<returns></returns>
6071+
</member>
60666072
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentAutocomplete`1.InputHandlerAsync(Microsoft.AspNetCore.Components.ChangeEventArgs)">
60676073
<summary />
60686074
</member>

‎examples/Demo/Shared/Pages/List/Autocomplete/AutocompletePage.razor

+8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626
</Description>
2727
</DemoSection>
2828

29+
<DemoSection Title="Close via code" Component="@typeof(AutocompleteCloseViaCode)">
30+
<Description>
31+
<p>
32+
This example demonstrates how to close the dropdown in code.
33+
</p>
34+
</Description>
35+
</DemoSection>
36+
2937
<h2 id="documentation">Documentation</h2>
3038

3139
<ApiDocumentation Component="typeof(FluentAutocomplete<>)" GenericLabel="TOption" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
@inject DataSource Data
2+
3+
@inject IDialogService DialogService
4+
5+
<FluentAutocomplete @ref=_autocomplete
6+
TOption="Country"
7+
AutoComplete="off"
8+
Autofocus="true"
9+
Label="Select a country"
10+
Width="250px"
11+
MaxAutoHeight="@(AutoHeight ? "200px" : null)"
12+
Placeholder="Select countries"
13+
OnOptionsSearch="@OnSearchAsync"
14+
OptionDisabled="@(e => e.Code == "au")"
15+
MaximumSelectedOptions="5"
16+
OptionText="@(item => item.Name)"
17+
@bind-SelectedOptions="@SelectedItems">
18+
<FooterContent>
19+
<FluentStack Orientation="Orientation.Horizontal"
20+
HorizontalAlignment="HorizontalAlignment.Right"
21+
Style="padding: 3px;">
22+
<FluentButton OnClick="OpenDialog">
23+
Show Dialog
24+
</FluentButton>
25+
</FluentStack>
26+
</FooterContent>
27+
</FluentAutocomplete>
28+
29+
<p>
30+
<b>Selected</b>: @(String.Join(" - ", SelectedItems.Select(i => i.Name)))
31+
</p>
32+
33+
@code
34+
{
35+
FluentAutocomplete<Country> _autocomplete = default!;
36+
bool AutoHeight = false;
37+
IEnumerable<Country> SelectedItems = Array.Empty<Country>();
38+
39+
private async Task OnSearchAsync(OptionsSearchEventArgs<Country> e)
40+
{
41+
var allCountries = await Data.GetCountriesAsync();
42+
e.Items = allCountries.Where(i => i.Name.StartsWith(e.Text, StringComparison.OrdinalIgnoreCase))
43+
.OrderBy(i => i.Name);
44+
}
45+
46+
private async Task OpenDialog()
47+
{
48+
await _autocomplete.CloseDropdownAsync();
49+
await DialogService.ShowInfoAsync("You pressed a button to open a dialog and close the dropdown.");
50+
}
51+
}

‎src/Core/Components/List/FluentAutocomplete.razor.cs

+10
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,16 @@ private string ComponentWidth
280280
/// <summary />
281281
protected override bool ShouldRender() => _shouldRender;
282282

283+
/// <summary>
284+
/// Closes the multiselect dropdown.
285+
/// </summary>
286+
/// <returns></returns>
287+
public async Task CloseDropdownAsync()
288+
{
289+
IsMultiSelectOpened = false;
290+
await InvokeAsync(StateHasChanged);
291+
}
292+
283293
/// <summary />
284294
protected override async Task InputHandlerAsync(ChangeEventArgs e)
285295
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
<div class=" fluent-autocomplete-multiselect" style="width: 100%;" b-hg72r5b4ox="">
3+
<fluent-text-field style="width: 100%; min-width: 100%;" id="xxx" value="" current-value="" appearance="outline" blazor:onchange="1" role="combobox" aria-expanded="true" aria-controls="myAutocomplete-popup" aria-label="3-Bill Gates (1 of 3)" blazor:onclick="2" blazor:oninput="3" blazor:elementreference="">
4+
<svg slot="end" style="width: 16px; fill: var(--accent-fill-rest); cursor: pointer;" focusable="true" tabindex="0" role="button" viewBox="0 0 16 16" blazor:onkeydown="4" blazor:onclick="5" blazor:onfocus="6">
5+
<title>Search</title>
6+
<path d="M9.1 10.17a4.5 4.5 0 1 1 1.06-1.06l3.62 3.61a.75.75 0 1 1-1.06 1.06l-3.61-3.61Zm.4-3.67a3 3 0 1 0-6 0 3 3 0 0 0 6 0Z"></path>
7+
</svg>
8+
</fluent-text-field>
9+
<div class="fluent-overlay" style="cursor: auto; position: fixed; display: flex; align-items: center; justify-content: center; z-index: 9900;" blazor:onclick="7" blazor:oncontextmenu="8" blazor:oncontextmenu:preventdefault="" b-xkrr7evqik="">
10+
<div b-xkrr7evqik=""></div>
11+
</div>
12+
<fluent-anchored-region anchor="xxx" horizontal-positioning-mode="dynamic" horizontal-default-position="right" horizontal-inset="" horizontal-threshold="0" horizontal-scaling="content" vertical-positioning-mode="dynamic" vertical-default-position="unset" vertical-threshold="0" vertical-scaling="content" auto-update-mode="auto" style="z-index: 9999;" b-2ov9fhztky="" blazor:elementreference="xxx">
13+
<div style="z-index: 9999; background-color: var(--neutral-layer-floating); box-shadow: var(--elevation-shadow-flyout); margin-top: 10px; border-radius: calc(var(--control-corner-radius) * 2px); background-color: var(--neutral-layer-floating);" b-2ov9fhztky="">
14+
<div id="xxx" role="listbox" style="width: 100%;" tabindex="0" b-hg72r5b4ox="">
15+
<fluent-option id="xxx" value="3-Bill Gates" blazor:onclick="9" aria-selected="true" selectable="" blazor:elementreference="xxx">3-Bill Gates</fluent-option>
16+
<fluent-option id="xxx" value="1-Denis Voituron" blazor:onclick="10" aria-selected="false" blazor:elementreference="xxx">1-Denis Voituron</fluent-option>
17+
<fluent-option id="xxx" value="2-Vincent Baaij" blazor:onclick="11" aria-selected="false" blazor:elementreference="xxx">2-Vincent Baaij</fluent-option>
18+
</div>
19+
</div>
20+
</fluent-anchored-region>
21+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
<div class=" fluent-autocomplete-multiselect" style="width: 100%;" b-hg72r5b4ox="">
3+
<fluent-text-field style="width: 100%; min-width: 100%;" id="xxx" value="" current-value="" appearance="outline" blazor:onchange="1" role="combobox" aria-expanded="false" aria-controls="" blazor:onclick="2" blazor:oninput="3" blazor:elementreference="">
4+
<svg slot="end" style="width: 16px; fill: var(--accent-fill-rest); cursor: pointer;" focusable="true" tabindex="0" role="button" viewBox="0 0 16 16" blazor:onkeydown="4" blazor:onclick="5" blazor:onfocus="6">
5+
<title>Search</title>
6+
<path d="M9.1 10.17a4.5 4.5 0 1 1 1.06-1.06l3.62 3.61a.75.75 0 1 1-1.06 1.06l-3.61-3.61Zm.4-3.67a3 3 0 1 0-6 0 3 3 0 0 0 6 0Z"></path>
7+
</svg>
8+
</fluent-text-field>
9+
</div>

‎tests/Core/List/FluentAutocompleteTests.razor

+29
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,35 @@
430430
cut.Verify();
431431
}
432432

433+
[Fact]
434+
public async Task FluentAutocomplete_CloseManually()
435+
{
436+
IEnumerable<Customer> SelectedItems = Array.Empty<Customer>();
437+
FluentAutocomplete<Customer> autocomplete = default!;
438+
439+
// Arrange
440+
var cut = Render<FluentAutocomplete<Customer>>(
441+
@<FluentAutocomplete Id="myAutocomplete" TOption="Customer"
442+
@ref=autocomplete
443+
SelectValueOnTab="true"
444+
@bind-SelectedOptions="@SelectedItems"
445+
OnOptionsSearch="@OnSearchAsync" />
446+
);
447+
448+
// Act: click to open -> KeyDow + Enter to select
449+
var input = cut.Find("fluent-text-field");
450+
input.Click();
451+
452+
// Verify that the dropdown is open
453+
cut.Verify(suffix: "DropdownOpened");
454+
455+
// Close the dropdown
456+
await autocomplete.CloseDropdownAsync();
457+
458+
// Verify that the dropdown is closed
459+
cut.Verify();
460+
}
461+
433462
// Send a key code
434463
private async Task PressKeyAsync(IRenderedComponent<FluentAutocomplete<Customer>> cut, KeyCode key, bool popoverOpened = false)
435464
{

0 commit comments

Comments
 (0)