Megabit / Blazorise

Blazorise is a component library built on top of Blazor with support for CSS frameworks like Bootstrap, Tailwind, Bulma, AntDesign, and Material.
https://blazorise.com/
Other
3.31k stars 533 forks source link

[Bug]: Autocomplete ReadData on demand clears selected values if not in data results #5769

Open nachoationet opened 1 month ago

nachoationet commented 1 month ago

Blazorise Version

1.6.x

What Blazorise provider are you running on?

Bootstrap5

Link to minimal reproduction or a simple code snippet

Hi, Im using the Autocomplete Component with the following methods

TItem="AutocompleteSubAccountDto" TValue="Guid" Data="@ViewModel.SubAccounts" ReadData="OnHandleSubaccounts" TextField="@(( item ) => item.Description)" ValueField="@(( item ) => item.Id)" SelectionMode="AutocompleteSelectionMode.Multiple" MultipleBadgeColor="Color.Light" Class="bg-light-secondary border-0" Debounce="true" DebounceInterval="500" @bind-SelectedValues="ViewModel.IdentificationsFilter.SubaccountIds"

Also I defined a custom dynamic data reading with a multiple selection mode, when I change the filter criteria while having selected values, the autocomplete clears all previously selected values and keeps only the current one. As I could make some tests, if I keep the old values in the Data enumerable, this behaviour does not occur, but it shows already selected values and if I select them again, they dissapear from the selected ones.

I would like to have the following behaviour if possible: Show in Data list only those results that i have not already selected, and keep the previously selected even if the query has changed.

Thanks in advance. Any help will be appreciated.

Steps to reproduce

What is expected?

I would expect the old values to be kept on selected, while also keeping the new ones

What is actually happening?

The old values get deleted, the new ones are kept

What browsers do you see the problem on?

Microsoft Edge

Any additional comments?

No response

nachoationet commented 3 weeks ago

@David-Moreira @stsrki Any news?

stsrki commented 3 weeks ago

Hello @nachoationet, we still haven't looked into this.

It's hard to find a problem without a fully reproducible code. Is there any chance that you could provide one?

David-Moreira commented 3 weeks ago

Hello @nachoationet If I understand correctly,

  1. you want to select values using the Autocomplete
  2. modify the data completely
  3. still expect the selected values to be there.

However it is currently a pre-requisite that the SelectedValues exist in the Data, this is because, ValueField and TextField need to resolve the values from actual existing items. I would say it would be a stretch to try and support this niche feature. The Autocomplete is already quite the complex component. @stsrki please let us know your thoughts.

If I could suggest an alternative, I would try to bind these values to a separate input and use the Autocomplete for selection purposes only.

nachoationet commented 3 weeks ago

Hello @nachoationet If I understand correctly,

  1. you want to select values using the Autocomplete
  2. modify the data completely
  3. still expect the selected values to be there.

However it is currently a pre-requisite that the SelectedValues exist in the Data, this is because, ValueField and TextField need to resolve the values from actual existing items. I would say it would be a stretch to try and support this niche feature. The Autocomplete is already quite the complex component. @stsrki please let us know your thoughts.

If I could suggest an alternative, I would try to bind these values to a separate input and use the Autocomplete for selection purposes only.

Yes precisely, as if I try to do the same while manually inserting the already selected values in the data enumerable, the values are shown in the dropdown as selectable items but selecting an item twice will remove it from the SelectedValues list.

I've seen the example you provide here but in my use case i can't load all the items once inside OnInitialized.

Is there any alternative to this? Adding the already selected values to the data enumerable (manually ofc) would be a good option but I don't want those values to show up in the dropdown

Edit: I'll try to provide code below for reference

stsrki commented 3 weeks ago

However it is currently a pre-requisite that the SelectedValues exist in the Data, this is because, ValueField and TextField need to resolve the values from actual existing items. I would say it would be a stretch to try and support this niche feature. The Autocomplete is already quite the complex component. @stsrki please let us know your thoughts.

Didn't we allow the FreeTyping that enables the creation of search values that don't exist in the Data? Is this a similar problem?

David-Moreira commented 3 weeks ago

Actually i didn't think about it. While the applicability of FreeTyping, wasn't the exact use case of @nachoationet it might just work. Would you give it a try @nachoationet ?

nachoationet commented 3 weeks ago

I've been playing around with the following scenario and it seems to work as expected, not sure why in another app with the same parameters it doesn't. Tried with versions 1.6.1 and 1.6.2, both are ok. I'm not sure if it's about Web / WebAssembly / Server App or rendermode, it works for Web App and InteractiveServerRenderMode(prerender: false).

Component

<Autocomplete 
    TItem="DayOfWeekItem"
    TValue="string"
    SelectionMode="AutocompleteSelectionMode.Multiple" 
    Data="DaysOfWeek.Data" 
    ReadData="ReadData" 
    TextField="item => item.Name" 
    ValueField="item => item.Value"
    Debounce="true"
    DebounceInterval="500"
    @bind-SelectedValues=SelectedItems>
    <NotFoundContent> Sorry... @context was not found! :( </NotFoundContent>
</Autocomplete>
Selected items: @string.Join(", ", SelectedItems)

@code {
    DayOfWeekData DaysOfWeek = new();

    List<string> SelectedItems = [];

    private async Task ReadData(AutocompleteReadDataEventArgs e)
    {
        if (!e.CancellationToken.IsCancellationRequested)
        {
            await DaysOfWeek.Load(e.SearchValue);
        }
    }
}

DayOfWeekData.cs

public class DayOfWeekData
{
    public List<DayOfWeekItem> Data { get; set; } = [];

    public async Task Load(string search)
    {
        var data = Enum.GetValues<DayOfWeek>()
            .Where(x => x.ToString().Contains(search.Trim(), StringComparison.CurrentCultureIgnoreCase))
            .Take(3)
            .Select(x => new DayOfWeekItem()
            {
                Name = x.ToString(),
                Value = ((int)x).ToString()
            })
            .ToList();

        await Task.Delay(millisecondsDelay: 2000);

        Data = data;
    }
}

public class DayOfWeekItem
{
    public string Name { get; set; }
    public string Value { get; set; }
}

Note: perhaps this state of the component has something to do with this bug

Image