Skip to content
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

fix: SelectedOptionsChanged Event Invoke Twice in FluentAutocomplete #3111

Closed
nassers opened this issue Dec 30, 2024 · 4 comments · Fixed by #3119
Closed

fix: SelectedOptionsChanged Event Invoke Twice in FluentAutocomplete #3111

nassers opened this issue Dec 30, 2024 · 4 comments · Fixed by #3119
Labels
closed:done Work is finished

Comments

@nassers
Copy link

nassers commented Dec 30, 2024

🐛 Bug Report

In FluentAutocomplete component, SelectedOptionsChanged event invokes twice.

💻 Repro or Code Sample

@page "/autocomplete"

<FluentAutocomplete TOption="Country"
                    AutoComplete="off"
                    Autofocus="true"
                    Label="Select a country"
                    Width="250px"
                    Placeholder="Select countries"
                    OnOptionsSearch="@OnSearchAsync"
                    MaximumSelectedOptions="5"
                    OptionText="@(item => item.Name)"
                    SelectedOptions="@SelectedItems"
                    SelectedOptionsChanged="OnChange" />

@code
{
    IEnumerable<Country> SelectedItems = Array.Empty<Country>();

    class Country
    {
        public string Name { get; set; }
    }

    List<Country> Data = new List<Country>
    {
        new Country { Name = "Afghanistan" },
        new Country { Name = "Argentina" },
        new Country { Name = "Armenia" },
        new Country { Name = "Australia" },
        new Country { Name = "Austria" },
        new Country { Name = "Azerbaijan" },
        new Country { Name = "Bahamas" },
        new Country { Name = "Bahrain" },
        new Country { Name = "Bangladesh" },
        new Country { Name = "Belgium" },
        new Country { Name = "Canada" },
        new Country { Name = "China" },
    };

    private async Task OnSearchAsync(OptionsSearchEventArgs<Country> e)
    {
        e.Items = Data.Where(i => i.Name.StartsWith(e.Text, StringComparison.OrdinalIgnoreCase)).OrderBy(i => i.Name);
    }

    private async Task OnChange(IEnumerable<Country> items)
    {

        foreach (var item in items)
        {
            Console.WriteLine(item.Name);
        }

        SelectedItems = items;
    }
}

🤔 Expected Behavior

After selecting for example "Afghanistan", It must print Afghanistan once in browser's console.

😯 Current Behavior

But it prints "Afghanistan" twice.

🌍 Your Environment

  • OS & Device: Windows on PC
  • Browser: Google Chrome, FireFox
  • .NET 9.0
  • Fluent UI Version 4.11.0
@microsoft-github-policy-service microsoft-github-policy-service bot added the triage New issue. Needs to be looked at label Dec 30, 2024
@pk9r
Copy link
Contributor

pk9r commented Dec 30, 2024

I confirm this happens.
@nassers you should provide ready-to-run reproduction code, either a (zipped) project structure or a GitHub repository (
see, #1744)

@pk9r
Copy link
Contributor

pk9r commented Dec 30, 2024

I'll note here the stack trace of the two event triggers. It might be useful later, but for now I want to wait for maintainers of this repository to respond to this issue first.

	FluentUI.Demo.Shared.dll!FluentUI.Demo.Shared.Pages.Issue.OnChange
	[Lightweight Function]
	System.Private.CoreLib.dll!System.Reflection.MethodBaseInvoker.InvokeWithOneArg
	System.Private.CoreLib.dll!System.Delegate.DynamicInvokeImpl
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync<object>
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.EventCallback<System.Collections.Generic.IEnumerable<FluentUI.Demo.Shared.Pages.Issue.Country>>.InvokeAsync
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.ListComponentBase<FluentUI.Demo.Shared.Pages.Issue.Country>.RaiseChangedEventsAsync
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.ListComponentBase<FluentUI.Demo.Shared.Pages.Issue.Country>.OnSelectedItemChangedHandlerAsync
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.FluentAutocomplete<FluentUI.Demo.Shared.Pages.Issue.Country>.OnSelectedItemChangedHandlerAsync
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.ListComponentBase<FluentUI.Demo.Shared.Pages.Issue.Country>.OnSelectCallback.AnonymousMethod__0
	[Lightweight Function]
	System.Private.CoreLib.dll!System.Reflection.MethodBaseInvoker.InvokeWithOneArg
	System.Private.CoreLib.dll!System.Delegate.DynamicInvokeImpl
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync<object>
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.EventCallback<string>.InvokeAsync
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.FluentOption<FluentUI.Demo.Shared.Pages.Issue.Country>.OnClickHandlerAsync
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.DispatchEventAsync
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.DispatchEventAsync
	[Lightweight Function]
	System.Private.CoreLib.dll!System.Reflection.MethodBaseInvoker.InvokeWithFewArgs
	Microsoft.JSInterop.dll!Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously
	Microsoft.JSInterop.dll!Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet
	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.BeginInvokeDotNetFromJS.AnonymousMethod__1
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.InvokeAsync.__Execute|8_0
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.InvokeAsync
	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.BeginInvokeDotNetFromJS
	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.ComponentHub.BeginInvokeDotNetFromJS
	[Lightweight Function]
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.ExecuteMethod
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.<ExecuteMethod>d__27>
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.Invoke.__ExecuteInvocation|22_0
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.<<Invoke>g__ExecuteInvocation|22_0>d>
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.Invoke
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.<Invoke>d__22>
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.ChannelBasedSemaphore.RunTask<(Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage)>
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.SignalR.Internal.ChannelBasedSemaphore.<RunTask>d__7<(Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage)>>
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.ProcessInvocation
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<System.__Canon>.DispatchMessageAsync
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.HubConnectionHandler<Microsoft.AspNetCore.Components.Server.ComponentHub>.DispatchMessagesAsync
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>.AsyncStateMachineBox<Microsoft.AspNetCore.SignalR.HubConnectionHandler<Microsoft.AspNetCore.Components.Server.ComponentHub>.<DispatchMessagesAsync>d__21>.MoveNext
	System.Private.CoreLib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch
	System.Private.CoreLib.dll!System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart
	
	FluentUI.Demo.Shared.dll!FluentUI.Demo.Shared.Pages.Issue.OnChange
	[Lightweight Function]
	System.Private.CoreLib.dll!System.Reflection.MethodBaseInvoker.InvokeWithOneArg
	System.Private.CoreLib.dll!System.Delegate.DynamicInvokeImpl
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.EventCallbackWorkItem.InvokeAsync<object>
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.Microsoft.AspNetCore.Components.IHandleEvent.HandleEventAsync
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.EventCallback<System.Collections.Generic.IEnumerable<FluentUI.Demo.Shared.Pages.Issue.Country>>.InvokeAsync
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.ListComponentBase<FluentUI.Demo.Shared.Pages.Issue.Country>.RaiseChangedEventsAsync
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.ListComponentBase<FluentUI.Demo.Shared.Pages.Issue.Country>.InternalValue.set
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.ListComponentBase<FluentUI.Demo.Shared.Pages.Issue.Country>.OnParametersSet
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.ComponentBase.SetParametersAsync
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.FluentInputBase<string>.SetParametersAsync
	Microsoft.FluentUI.AspNetCore.Components.dll!Microsoft.FluentUI.AspNetCore.Components.ListComponentBase<FluentUI.Demo.Shared.Pages.Issue.Country>.SetParametersAsync
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.DispatchEventAsync
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.RenderTree.Renderer.DispatchEventAsync
	[Lightweight Function]
	System.Private.CoreLib.dll!System.Reflection.MethodBaseInvoker.InvokeWithFewArgs
	Microsoft.JSInterop.dll!Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously
	Microsoft.JSInterop.dll!Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet
	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.BeginInvokeDotNetFromJS.AnonymousMethod__1
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.InvokeAsync.__Execute|8_0
	Microsoft.AspNetCore.Components.dll!Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext.InvokeAsync
	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost.BeginInvokeDotNetFromJS
	Microsoft.AspNetCore.Components.Server.dll!Microsoft.AspNetCore.Components.Server.ComponentHub.BeginInvokeDotNetFromJS
	[Lightweight Function]
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.ExecuteMethod
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.<ExecuteMethod>d__27>
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.Invoke.__ExecuteInvocation|22_0
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.<<Invoke>g__ExecuteInvocation|22_0>d>
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.Invoke
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.<Invoke>d__22>
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.ChannelBasedSemaphore.RunTask<(Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage)>
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<Microsoft.AspNetCore.SignalR.Internal.ChannelBasedSemaphore.<RunTask>d__7<(Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>, Microsoft.AspNetCore.SignalR.Internal.HubMethodDescriptor, Microsoft.AspNetCore.SignalR.HubConnectionContext, Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage)>>
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<Microsoft.AspNetCore.Components.Server.ComponentHub>.ProcessInvocation
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher<System.__Canon>.DispatchMessageAsync
	Microsoft.AspNetCore.SignalR.Core.dll!Microsoft.AspNetCore.SignalR.HubConnectionHandler<Microsoft.AspNetCore.Components.Server.ComponentHub>.DispatchMessagesAsync
	[Resuming Async Method]
	System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop
	System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>.AsyncStateMachineBox<Microsoft.AspNetCore.SignalR.HubConnectionHandler<Microsoft.AspNetCore.Components.Server.ComponentHub>.<DispatchMessagesAsync>d__21>.MoveNext
	System.Private.CoreLib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch
	System.Private.CoreLib.dll!System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart

@nassers
Copy link
Author

nassers commented Dec 30, 2024

Here is ready-to-run reproduction code :
FluentAutocomplete.zip

@vnbaaij
Copy link
Collaborator

vnbaaij commented Jan 2, 2025

Will be fixed with PR #3119 and available in next release,

@vnbaaij vnbaaij added closed:done Work is finished and removed triage New issue. Needs to be looked at labels Jan 2, 2025
@vnbaaij vnbaaij closed this as completed Jan 2, 2025
vnbaaij added a commit that referenced this issue Jan 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed:done Work is finished
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants