fluentui-blazor icon indicating copy to clipboard operation
fluentui-blazor copied to clipboard

fix: Custom text lost after selecting item in FluentCombobox

Open JamesNK opened this issue 2 months ago β€’ 12 comments

πŸ› Bug Report

πŸ’» Repro or Code Sample

I have a combobox. The combobox is:

  • Bound to a list of items
  • Has Immediate="true"
  • @bind-Value:after is used to manually filter items the combobox is bound to as the selected value changes

Unfortunately, this combination of behavior causes a bug after selecting an item. Entering custom text in the combobox stops working because the text value resets back to the selected item.

Recording of issue: Image

The combobox starts working again if the items its bound to doesn't change. I think there is a bug when the items collection is changed in the value change event. It causes a new changed event which resets the combobox back to the selected value.

Source code of a comboxbox with this issue: https://github.com/dotnet/aspire/blob/c97743e5f463312ebd2dde2ac454686cc4901a39/src/Aspire.Dashboard/Components/Dialogs/FilterDialog.razor#L39-L60

You can see this issue in any Aspire playground app, i.e. TestShop

πŸ€” Expected Behavior

Can enter text after selecting an item.

😯 Current Behavior

Text entered after selecting an item is lost.

πŸ’ Possible Solution

πŸ”¦ Context

🌍 Your Environment

  • OS & Device: [e.g. MacOS, iOS, Windows, Linux] on [iPhone 7, PC]
  • Browser [e.g. Microsoft Edge, Google Chrome, Apple Safari, Mozilla FireFox]
  • .NET and Fluent UI Blazor library Version [e.g. 8.0.2 and 4.4.1]

JamesNK avatar Nov 12 '25 09:11 JamesNK

it isn't particullary lost. It sets the text to your selection and appends your new text to it. Since there is no item available with this specific name nothing will be shown. Do you want to support multiple item selection or what are you trying to achieve?

I would suggest using the AutoComplete component for this scenario instead.

MarvinKlein1508 avatar Nov 12 '25 13:11 MarvinKlein1508

The combobox Value should be the value of text typed into it. That's how comboxes work.

You can see it working here https://www.fluentui-blazor.net/Combobox:

Image

I want that, but as you can see in the first recording, the typed in value is lost and it resets back to the last selected value.

As I mentioned in the original issue body, I've debugged that the value is correctly bound to the typed value in a change event, but it is reset back to the previous value in another change event. It seems related to changing the bound items in the first change event.

JamesNK avatar Nov 12 '25 23:11 JamesNK

I can indeed see the behavior you are reporting.

I think it is fixed when I add the ChangeOnEnterOnly="true" parameter to the dialog. Can you confirm? When this is added, I see in your ValueChanged code the correct value is being handled.

vnbaaij avatar Nov 18 '25 10:11 vnbaaij

I still see the problem.

Image

Image

And I think I found another issue with the same cause:

  1. I select "Middleware loaded"
  2. "Middleware loaded" is set in the value
  3. Comboxbox @bind-Value:after event runs and sets new options
  4. "Middleware loaded: DOTNET_MODIFIABLE_ASSEMBLIES=debug, __ASPNETCORE_BROWSER_TOOLS=true" is set in the value

Image

From the debugger POV:

Image

The problem doesn't happen if options aren't filtered in @bind-Value:after. It causes both bugs.

JamesNK avatar Nov 20 '25 03:11 JamesNK

When looking at our default combobox, I see the behavior that the full lust is shown once the value changes into something that is not in the list. See the screengrab below. This is how the Razor component and the underlying web component are supposed to work and is consistent with for example how the Fluent React combobox works.

Image

With the combobox in the filter this is not happening. There, because of the filtering, the list is trimmed to 0 elements if the value is not present in the list. Not only does this stop the combobox from working, it also causes the value to 'jump back' to the earlier selected list entry. By having the @bind-Value:after just returning the non-filtered list (also first 1000 elements), in my testing (see below) it all just works:

Image

I checked the _formModel.Value and that also then contains the value entered in the combobox text field. For completeness, I am not using the earlier suggested ChangeOnEnterOnly.

This is how I changed the ValueChanged method (only changed line is shown)

             // Limit to 1000 items to avoid the combo box have too many items and impacting UI perf.
            _filteredValues = newValues.Any() ? newValues.Take(1000).ToList() : _allValues.Take(1000).ToList();

Please confirm if you see the same when making this change.

vnbaaij avatar Nov 25 '25 20:11 vnbaaij

Using the solution for my previous comment, will present another issue...It is now possible for users to apply a filter that is not available in the list. Once that is done, navigating back to the filter dialog by selecting the filter (see image)

Image

will show the filter dialog with an empty combobox although, as can be seen in the image, the @_formModel.Value is correct

Image

I've identified what is causing that and creating a PR (#4353) to fix that:

Image

vnbaaij avatar Nov 25 '25 21:11 vnbaaij

I’m away for two weeks and don’t have a dev machine with me. I’ll have a look at what you found when I get back

JamesNK avatar Nov 27 '25 00:11 JamesNK

@JamesNK Hope you have a good time off!

vnbaaij avatar Nov 27 '25 11:11 vnbaaij

We need to filter the list because there could be hundreds of items in the combobox. If we don't filter, then users are forced to scroll through a potentially huge list of values to find what they want. Typing the value in the combobox lets them quickly filter from hundreds to a few, and then they can select it.

I looked at your link to Fluent UI React combox. On the page there is an example doing exactly what I'm doing here (value change raises an event, and in that event the comboxbox item list is filtered using the value). It doesn't have the Blazor Fluent UI bugs.

See the filtering example: https://storybooks.fluentui.dev/react/?path=/docs/components-combobox--docs#filtering

JamesNK avatar Dec 06 '25 05:12 JamesNK

The filter by itself works fine, doesn't it? With the change I proposed, there aren't any bugs present in using the bind after.

The only issue I see is that it doesn't empty the list if you filter beyond any of the possible options. As I mentioned, that is what you get with almost every other Combobox. Showing the original list is not bad, is it. After all, that is also what you get if you start filtering in the first place.

The example you mention is interesting. You could try in your code to return a single option if you filter beyond the list and see if that makes a difference with the case where an empty list was being returned.

I don't see us investing in changing the current behavior in the short term. We are quite busy with the v5 version.

vnbaaij avatar Dec 06 '25 08:12 vnbaaij

Opps, I didn't understand exactly what your change proposed. Showing all items if there are no matches fixes the initial bug in this issue, and it still provides a good experience.

Unfortunately, the second bug I mentioned still happens:

Image

Repo:

  1. Enter text that doesn't match any items
  2. Click on "Middleware loaded"
  3. "Middleware loaded" is set to the bound property. After event raised that filters the items with "Middleware loaded" (I debugged to double check that "Middleware loaded" is still an item in the items
  4. "Middleware loaded: DOTNET_MOD...." is set to the bound property. After event raised that filters the items with "Middleware loaded" <- bug

JamesNK avatar Dec 06 '25 11:12 JamesNK

Ok, I'll look into that second one

vnbaaij avatar Dec 06 '25 11:12 vnbaaij