asp.netblazormudblazor

MudSelect Display Text different behavior when property to bind values is empty vs not


I have a MudSelect with MultiSelection enbabled. I also have a MultiSelectionTextFunc since my SelectItems have a Value and a Text. I bind the Value to the property Values of my Model. Here is a code snippet:

https://try.mudblazor.com/snippet/mOwyaqmnmhvriTTJ

The above works fine, and displays the values as I intended.

The problem is when I already have some values in my Values property. Then, although it binds the correct Values, it displays only the first one:

https://try.mudblazor.com/snippet/QYcSkqmRwrdnRwmz


Solution

  • Not sure what the issue is but it works as long as you set the Value property, even if you don't use it.

    <MudSelect T="int"  Clearable="true" @bind-Value="localVal"
           MultiSelectedValues="@Vm.Values" SelectedValuesChanged="SelectedValuesChanged"
           SelectionTextFunc="@GetMultiSelectionText" MultiSelection="true" Label="Select">
        @foreach (var option in options)
        {
            <MudSelectItem T="int" Value="@option.Value">@option.Text</MudSelectItem>
        }
    </MudSelect>
    
    @code {
        int localVal;
        public MyVm Vm { get; set; }
        
        private List<Option> options = new List<Option> {new Option(1, "Option1"), new Option(2, "Option2"), new Option(3, "Options3")};
    
        protected override void OnInitialized()
        {
            Vm = new MyVm
            {
                Values = new List<int>{1, 2}
            };
    
            base.OnInitialized();
        }
    
        private string GetMultiSelectionText(List<string> selectedValues)
        {
            return string.Join(", ", options.Where(x => selectedValues.Contains(x.Value.ToString())).Select(x => x.Text).ToList());
        }
        
        private void SelectedValuesChanged(IEnumerable<int> selectedValues)
        {
            Vm.Values = selectedValues.ToList();
        }
    
        public class MyVm
        {
            public List<int> Values { get; set; }
        }
    
         public class Option
        {
            public int Value { get; init; }
            public string Text { get; init; }
    
            public Option(int value, string text)
            {
                Value = value;
                Text = text;
            }
        }
    }
    

    Demo 👉MudBlazor Snippet


    Or with @spyros_'s workaround mentioned in the comments below, where you create a local collection i.e. IEnumerable instead of creating it as an objects property. Then you assign both the local collection and the object's property collection in the SelectedValuesChanged handler method.

    
    <MudSelect T="string"  Clearable="true"  SelectedValues="@initialSelectedValues" MultiSelectionTextFunc="@GetMultiSelectionText" SelectedValuesChanged="SelectedValuesChanged"
               MultiSelection="true" Label="Select">
        @foreach (var option in options)
        {
            <MudSelectItem T="string" Value="@option.Text">@option.Text</MudSelectItem>
        }
    </MudSelect>
    
    
    @code {
       
        public MyVm Vm { get; set; }
        
        private List<Option> options = new List<Option> {new Option(1, "Option1"), new Option(2, "Option2"), new Option(3, "Options3")};
    
        private IEnumerable<string> initialSelectedValues;
    
        protected override void OnInitialized()
        {
            Vm = new MyVm
            {
                Values = new List<int>{1, 2}
            };
    
            initialSelectedValues = options.Where(x=>Vm.Values.Contains(x.Value)).Select(x => x.Text).ToList();
    
            base.OnInitialized();
        }
    
        private string GetMultiSelectionText(List<string> selectedValues)
        {
            return string.Join(", ", options.Where(x => selectedValues.Contains(x.Text)).Select(x => x.Text).ToList());
        }
        
        private void SelectedValuesChanged(IEnumerable<string> selectedValues)
        {
            Vm.Values = options.Where(x=>selectedValues.Contains(x.Text)).Select(x => x.Value).ToList();
            initialSelectedValues = selectedValues;
        }
    
        public class MyVm
        {
            public List<int> Values { get; set; }
        }
    
         public class Option
        {
            public int Value { get; init; }
            public string Text { get; init; }
    
            public Option(int value, string text)
            {
                Value = value;
                Text = text;
            }
        }
    
    }