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
List<int>
or a concatenated string of key values)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:
select multiple departments and get the list of selected (numerical) Id
- but then the display of those departments selected is also the concatenated list of numerical Id
; or
use that MultiSelectionTextFunc
and get the display of the departments selected properly, in human-readable form - but I lose the information of what (numerical) keys have been selected.
What can I do to achieve both?
Key
of the selected departments so I can store these into a database somehowYou 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);
}