blazormulti-select.net-8.0mudblazormudselect

How to handle multi-select correctly?


I'm struggling with a multi-select dropdown component in my .NET 8 Blazor server-side app. I'm using MudBlazor select component to support the multi-selection.

I'm loading a list of departments from our Dynamics instance, and I'm storing those into a List<SelectListItem>. Each entry has a Key (a numerical value, like 737004101), and a textual representation of the department ("Department A").

My goal is to

My trouble is: I can't seem to get this to work as I would like.

I'm rendering the departments like this - with this set up, the names of the departments are shown when the dropdown is opened (as expected and wanted):

<MudSelect T="string" @bind-Value="@CurrentValue" MultiSelection=true>
    @foreach (SelectListItem item in Departments)
    {
        <MudSelectItem T="string" Value="@item.Value">@item.Text</MudSelectItem>
    }
</MudSelect>

The list of departments is handled as a parameter on my component:

[Parameter]
public List<SelectListItem> Departments { get; set; } = new List<SelectListItem>();

and the CurrentValue comes from the InputBase<string> Blazor base component - it's a string field on the component.

If I have it just like this, I do see the list of departments with their names in the dropdown, I can select multiple entries - but after I'm done with the selection, the MudSelect component shows the concatenated list of the numerical values of those departments selected (e.g. "737004101, 737004104, 737004106").

I then discovered the MultiSelectionTextFunc property of MudSelect, and from reading the docs, I believed this to be the solution: a function used to define a custom display text for the component, when multiple items have been selected. So I created such a function in my component and wired it up to the MudSelect:

<MudSelect T="string" @bind-Value="@CurrentValue" MultiSelection=true MultiSelectionTextFunc="@GetMultiSelectionText">
    @foreach (SelectListItem item in Departments)
    {
        <MudSelectItem T="string" Value="@item.Value">@item.Text</MudSelectItem>
    }
</MudSelect>

private string GetMultiSelectionText(List<string> selectedValues)
{
    List<string> selectedTexts = new List<string>();

    foreach (string value in selectedValues)
    {
        SelectListItem? item = Departments.FirstOrDefault(x => x.Value == value);

        if (item != null)
        {
            selectedTexts.Add(item.Text);
        }
    }

    return string.Join("; ", selectedTexts);
}

I get the list of the selected (numerical) values, and I translate those into the department names, and then I show this (list of the human-readable names of the selected departments) in my component:

Dept. A; Dept. D; Dept. H

But while I now see the names of the departments in the dropdown list, and after choosing a few of them, I also see the readable names in the textbox of the dropdown component, now my CurrentValue is also being set to the list of names of the departments selected - I do not get the list of the selected numerical keys any more.

It seems that I can either:

What can I do to achieve both?


Solution

  • You can store your SelectedListItem objects as SelectedValues. This way you can retrieve the Key values and display the Text values by using ToStringFunc="x => x.Text". Additionally you can set Delimiter="; " to achieve the

    Dept. A; Dept. D; Dept. H
    

    look.

    So your Mudselect looks like this:

    <MudSelect 
     T="SelectedListItem" 
     @bind-SelectedValues="@_selectedValues" 
     MultiSelection="true" 
     ToStringFunc="x => x.Text"
     Delimiter="; "
    >
        @foreach (SelectListItem item in Departments)
        {
            <MudSelectItem T="SelectListItem" Value="@item">@item.Text</MudSelectItem>
        }
    </MudSelect>
    

    and you can retrieve then the keys as simple as

    private IEnumerable<int> GetSelectedKeys()
    {
        return _selectedValues.Select(x => x.Key);
    }
    

    MudSnippet