Aspnetcore: Support binding to <select multiple>, getting/setting the selection as an array

Created on 10 May 2018  路  10Comments  路  Source: dotnet/aspnetcore

With the following code

 <select name="cars" multiple onchange="@SelectionChanged">
        <option value="volvo">Volvo</option>
        <option value="saab">Saab</option>
        <option value="opel">Opel</option>
        <option value="audi">Audi</option>
    </select>
 void SelectionChanged(UIChangeEventArgs e)
        {
            Console.WriteLine(e.Value);
        }

Holding down the ctrl key, if you select 'volvo' first and then any other value, e.value is always 'volvo'. It basically returns the top selected item in the list.

affected-most area-blazor enhancement severity-major

Most helpful comment

@pjmagee There is a workaround. I used a javascript interop call to get the list of selected items from the list. To set the initial selections, you can set the <select value=@selections> where selections is a List<string>.

   <select ref="sel" multiple="multiple" onchange=@SelectionChanged value=@selections>
         @foreach (string s in MyStringList)
         {
            <option value="@s">@s</option>
         }
     </select>

@functions {

[Parameter]
private List<string> FilteredStringList { get; set; } = new List<string>();
private List<string> selections = new List<string>();  

public async Task<List<string>> GetAllSelections()
{
    return (await JSRuntime.Current.InvokeAsync<List<string>>("getSelectedValues", sel)).ToList();
}

 private async Task SelectionChanged(UIChangeEventArgs evt)
 {
    List<string> localSelections = await GetAllSelections();
    // do something with localSelections.  or wait for some other
    //  event like a button and call GetAllSelections() to get the list later.
  }
}

in the html page include the getSelectedValues function. The function below works, but
I know there are faster ways of getting the list.

  window.getSelectedValues = function(sel) {
    var results = [];
    var i;
    for (i = 0; i < sel.options.length; i++) {
        if (sel.options[i].selected) {
            results[results.length] = sel.options[i].value;
        }
    }
    return results;
};

All 10 comments

I have checked #805 and it looks that in simple binding scenario it doesn't work either. The question is: what data type should we use to bind to "select multiple" and what should be returned in e.Value? Array of strings or simple string (multiple values with separators)?

Great point to raise. We don't have any specific API in place for this scenario.

I guess a reasonable design would be binding to a string[], but that's not yet implemented.

We can add it to the backlog.

Just to be clear, Blazor doesn't currently support selects that are defined as multi select? If it doesn't, is there a simple way around it?

@pjmagee There is a workaround. I used a javascript interop call to get the list of selected items from the list. To set the initial selections, you can set the <select value=@selections> where selections is a List<string>.

   <select ref="sel" multiple="multiple" onchange=@SelectionChanged value=@selections>
         @foreach (string s in MyStringList)
         {
            <option value="@s">@s</option>
         }
     </select>

@functions {

[Parameter]
private List<string> FilteredStringList { get; set; } = new List<string>();
private List<string> selections = new List<string>();  

public async Task<List<string>> GetAllSelections()
{
    return (await JSRuntime.Current.InvokeAsync<List<string>>("getSelectedValues", sel)).ToList();
}

 private async Task SelectionChanged(UIChangeEventArgs evt)
 {
    List<string> localSelections = await GetAllSelections();
    // do something with localSelections.  or wait for some other
    //  event like a button and call GetAllSelections() to get the list later.
  }
}

in the html page include the getSelectedValues function. The function below works, but
I know there are faster ways of getting the list.

  window.getSelectedValues = function(sel) {
    var results = [];
    var i;
    for (i = 0; i < sel.options.length; i++) {
        if (sel.options[i].selected) {
            results[results.length] = sel.options[i].value;
        }
    }
    return results;
};

Great point to raise. We don't have any specific API in place for this scenario.

I guess a reasonable design would be binding to a string[], but that's not yet implemented.

We can add it to the backlog.

Hi Steve. I cannot find any new information on this, could you confirm if this is still in the backlog or if it has been implemented? Thanks.

It is still in the backlog. Currently we're focused on shipping Blazor WebAssembly, during which we're not making any changes to the core Blazor components programming model. The next phase during which we'll do programming model enhancements is for .NET 5, which we'll be working on between May and November.

Still not working ?
Well, I'm trying to use it and its not working as intended...

Any Updates?

I can't seem to find it on the project board (https://github.com/dotnet/aspnetcore/projects/12).

is it still planned for the .NET5 release?

No, sorry, this was never planned for .NET 5 (I only said that was the earliest it could be done). We packed in absolutely as much as we could, but this didn鈥檛 make the cut. I know that will seem disappointing if this one was particularly important to you.

For now if you need this you鈥檇 need to implement it manually. Sorry!

It鈥檚 on the backlog that we鈥檒l review for .NET 6.

Was this page helpful?
0 / 5 - 0 ratings