Skip to content

FluentAutoComplete: Allow the ability to trigger the search options via code. #3570

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
Expand Up @@ -6066,6 +6066,13 @@
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentAutocomplete`1.InputHandlerAsync(Microsoft.AspNetCore.Components.ChangeEventArgs)">
<summary />
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentAutocomplete`1.InvokeOptionsSearchAsync">
<summary>
Performs the search operation and displays the available values. The search takes into account any previously
entered text which has updated the <see cref="P:Microsoft.FluentUI.AspNetCore.Components.FluentAutocomplete`1.ValueText"/>.
</summary>
<returns></returns>
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.FluentAutocomplete`1.KeyDownHandlerAsync(Microsoft.FluentUI.AspNetCore.Components.FluentKeyCodeEventArgs)">
<summary />
</member>
Expand Down
41 changes: 25 additions & 16 deletions src/Core/Components/List/FluentAutocomplete.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,27 +296,37 @@ protected override async Task InputHandlerAsync(ChangeEventArgs e)
if (MaximumSelectedOptions > 0 && SelectedOptions?.Count() >= MaximumSelectedOptions)
{
IsReachedMaxItems = true;
RenderComponent();
await RenderComponentAsync();
return;
}

IsReachedMaxItems = false;
IsMultiSelectOpened = true;

var args = new OptionsSearchEventArgs<TOption>()
{
Items = Items ?? Array.Empty<TOption>(),
Text = ValueText,
};

if (ImmediateDelay > 0)
{
await _debounce.RunAsync(ImmediateDelay, () => InvokeAsync(() => OnOptionsSearch.InvokeAsync(args)));
await _debounce.RunAsync(ImmediateDelay, () => InvokeAsync(() => InvokeOptionsSearchAsync()));
}
else
{
await OnOptionsSearch.InvokeAsync(args);
await this.InvokeOptionsSearchAsync();
}
}

/// <summary>
/// Performs the search operation and displays the available values. The search takes into account any previously
/// entered text which has updated the <see cref="ValueText"/>.
/// </summary>
/// <returns></returns>
public async Task InvokeOptionsSearchAsync()
{
var args = new OptionsSearchEventArgs<TOption>()
{
Items = Items ?? Array.Empty<TOption>(),
Text = ValueText,
};

await OnOptionsSearch.InvokeAsync(args);

Items = args.Items?.Take(MaximumOptionsSearch);

Expand All @@ -329,14 +339,13 @@ protected override async Task InputHandlerAsync(ChangeEventArgs e)
await VirtualizationContainer.RefreshDataAsync();
}

RenderComponent();
await RenderComponentAsync();
}

// Activate the rendering
void RenderComponent()
{
_shouldRender = true;
StateHasChanged();
}
private async Task RenderComponentAsync()
{
_shouldRender = true;
await InvokeAsync(StateHasChanged);
}

private ValueTask<ItemsProviderResult<TOption>> LoadFilteredItemsAsync(ItemsProviderRequest request)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

<div class=" fluent-autocomplete-multiselect" style="width: 100%;" b-hg72r5b4ox="">
<fluent-text-field style="width: 100%; min-width: 100%;" placeholder="" id="xxx" value="" current-value="" appearance="outline" blazor:onchange="1" role="combobox" aria-expanded="true" aria-controls="myComponent-popup" aria-label="1-Denis Voituron (1 of 1)" blazor:onclick="2" blazor:oninput="3" blazor:elementreference="">
<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">
<title>Search</title>
<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>
</svg>
</fluent-text-field>
<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="">
<div b-xkrr7evqik=""></div>
</div>
<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="">
<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="">
<div id="xxx" role="listbox" style="width: 100%;" tabindex="0" b-hg72r5b4ox="">
<fluent-option id="xxx" value="1-Denis Voituron" blazor:onclick="9" aria-selected="true" selectable="" blazor:elementreference="">1-Denis Voituron</fluent-option>
</div>
</div>
</fluent-anchored-region>
</div>
34 changes: 30 additions & 4 deletions tests/Core/List/FluentAutocompleteTests.razor
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,36 @@
cut.Verify();
}

[Fact]
public async Task FluentAutocomplete_InvokeSearchOptions()
{
// Arrange
FluentAutocomplete<Customer> fluentAutoComplete = default!;

var externalSearchString = string.Empty;
var customers = Customers.Get();

async Task OnSearchValueChanged(OptionsSearchEventArgs<Customer> e)
{
e.Items = customers;
if (!string.IsNullOrWhiteSpace(externalSearchString))
e.Items = customers.Where(x => x.Name.Contains(externalSearchString));
}

var cut = Render(@<FluentAutocomplete Id="myComponent" @ref=fluentAutoComplete OnOptionsSearch="OnSearchValueChanged" TOption="Customer" />);

// Act
var input = cut.Find("fluent-text-field");
input.Click();

externalSearchString = "Denis";

await fluentAutoComplete.InvokeOptionsSearchAsync();

// Assert
cut.Verify();
}

[Theory()]
[InlineData("Escape")]
[InlineData("Backspace")]
Expand Down Expand Up @@ -446,8 +476,4 @@
.OrderBy(i => i.Name);
return Task.CompletedTask;
}




}