CodeBeamOrg / CodeBeam.MudBlazor.Extensions

Useful third party extension components for MudBlazor, from the contributors.
https://mudextensions.codebeam.org/
MIT License
367 stars 62 forks source link

MudSelectExtended Select All Filtered #273

Closed PlayerModu closed 9 months ago

PlayerModu commented 9 months ago

Could the MudSelectedExtended component support the ability to Select All but only selecting "all" from the list that is filtered/currently in dropdown context?

I.e I have a list of 10 items, I've filtered those items by A, so there are 5 in the selectable dropdown. If I click "Select All", it select the 5 A items and not just the original full list?

A similar request was raised and completed for the MudComboxBox (https://github.com/CodeBeamOrg/CodeBeam.MudBlazor.Extensions/issues/262) but I'm having so many issues with the MudComboxBox at the moment, it's easier for for me to stick with the MudSelectedExtended component which works perfectly until the roadmap for the MudComboBox is more complete.

PlayerModu commented 9 months ago

@mckaragoz I believe I've identified the change needed to resolve this issue.

In the SelectAllItems method in the MudListExtended.razor.cs, it is only doing the expected filtering (items.Where(x => x.IsSelected).Select(y => y.Value).ToHashSet(_comparer)) on the items list when ItemCollection is null. Otherwise it is applying the ItemCollection list to SelectedValues, not the items list. So it wasn't applying the filtering that had already been done on the items at the start of this method.

I've changed this, and adding the filtering that was in the else block to the if block as well in the ternary seems to be behaving as expected now when I was testing the "Select All" component running the extension docs locally.

image

            var selectedItems = items.Where(x => x.IsSelected).Select(y => y.Value).ToHashSet(_comparer);
            if (ItemCollection != null)
            {
                SelectedValues = deselect == true ? Enumerable.Empty<T>() : selectedItems;
            }
            else
            {
                SelectedValues = selectedItems;
            }

Let me know your thoughts on this change. I can raise a PR if all good to can go ahead for this?

mckaragoz commented 9 months ago

Ofc you can prepare a PR, your idea sounds like the true behavior. We will also add a test to be sure that changes are working both with ItemCollection and RenderFragment approaches.

PlayerModu commented 9 months ago

@mckaragoz I'm struggling with getting the unit test running. I've looked at the other unit tests in this class but I can't see a clear one where it enters search text. Are you able to advise? This is the unit test method code I have so far in SelectExtendedTests.cs:

The idea is the full list contains FirstA, SecondA, ThirdA. So I wanted to search on i, to remove SecondA from the available list. And then selecting all would only select the filtered FirstA and ThirdA elements.

[Test]
public async Task MultiSelect_ValueSearched_SelectAllClicked_ShouldSelectAllFiltered()
{
    var comp = Context.RenderComponent<MultiSelectTest2>();

    // select element needed for the test
    var select = comp.FindComponent<MudSelectExtended<string>>();

    // Open the menu
    var menu = comp.Find("div.mud-popover");
    var input = comp.Find("div.mud-input-control");
    input.Click();
    menu.ClassList.Should().Contain("mud-popover-open");

    // Enter a search value
    var searchInput = comp.Find("div.mud-input-slot");
    searchInput.TextContent = "i";

    // Click on Select All
    comp.FindAll("div.mud-list-item-extended")[0].Click();

    // All searched items should be selected
    comp.WaitForAssertion(() => select.Instance.Text.Should().Be("FirstA^ThirdA"));
}

And it's failing with the message below, I think it's not finding and/or triggering the searchbox entry correctly? :

Bunit.Extensions.WaitForHelpers.WaitForFailedException : The assertion did not pass within the timeout period. Check count: 1. Component render count: 4. Total render count: 5.
  ----> NUnit.Framework.AssertionException : Expected select.Instance.Text to be "FirstA^ThirdA" with a length of 13, but "FirstA^SecondA^ThirdA" has a length of 21, differs near "Sec" (index 7).
mckaragoz commented 9 months ago

You can push the PR then i can look and play with the test