Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
Tracked by #27883
dlr1 opened this issue May 10, 2018 · 13 comments
Closed
Tracked by #27883
Assignees
Labels
affected-most This issue impacts most of the customers area-blazor Includes: Blazor, Razor Components Done This issue has been fixed enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-razor.language Priority:2 Work that is important, but not critical for the release severity-major This label is used by an internal tool User Story A single user-facing feature. Can be grouped under an epic.
Milestone

Comments

@dlr1
Copy link

dlr1 commented May 10, 2018

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.

@Andrzej-W
Copy link

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)?

@SteveSandersonMS
Copy link
Member

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.

@SteveSandersonMS SteveSandersonMS changed the title html select with "multiple" attribute won't return the correct item in onchange event Support binding to <select multiple>, getting/setting the selection as an array May 11, 2018
@aspnet-hello aspnet-hello transferred this issue from dotnet/blazor Dec 17, 2018
@aspnet-hello aspnet-hello added this to the Backlog milestone Dec 17, 2018
@aspnet-hello aspnet-hello added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates area-blazor Includes: Blazor, Razor Components labels Dec 17, 2018
@pjmagee
Copy link

pjmagee commented Feb 22, 2019

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?

@mikewodarczyk
Copy link

@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;
};

@mkArtakMSFT mkArtakMSFT removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels May 9, 2019
@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Aug 27, 2019
@mkArtakMSFT mkArtakMSFT modified the milestones: Backlog, 5.0.0-preview1 Aug 27, 2019
@MariusMyburg
Copy link

MariusMyburg commented Feb 28, 2020

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.

@SteveSandersonMS
Copy link
Member

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.

@acpt
Copy link

acpt commented May 27, 2020

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

@astevens8182
Copy link

Any Updates?

@MatsKarlsson
Copy link

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?

@SteveSandersonMS
Copy link
Member

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’t make the cut. I know that will seem disappointing if this one was particularly important to you.

For now if you need this you’d need to implement it manually. Sorry!

It’s on the backlog that we’ll review for .NET 6.

@SteveSandersonMS SteveSandersonMS added affected-few This issue impacts only small number of customers severity-major This label is used by an internal tool affected-most This issue impacts most of the customers labels Oct 6, 2020 — with ASP.NET Core Issue Ranking
@mkArtakMSFT mkArtakMSFT added this to the Next sprint planning milestone Jan 8, 2021
@ghost
Copy link

ghost commented Jan 8, 2021

Thanks for contacting us.
We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@mkArtakMSFT mkArtakMSFT added User Story A single user-facing feature. Can be grouped under an epic. Priority:2 Work that is important, but not critical for the release labels Jan 31, 2021
@Rubenisme
Copy link

Okay, so it would have been nice if this had been working already, but what @mikewodarczyk wrote doesn't work anymore. What works for me currently is:

@functions {

    private async Task OnChangeCallback(ChangeEventArgs eventArgs)
    {
        var selection = await GetAllSelections(_elementReference);
        Model.MyListProperty = selection;
    }

    private ElementReference _elementReference;

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

And then as HTML:

<select @ref="_elementReference" value="@Model.MyListProperty" multiple="multiple" @onchange="OnChangeCallback">
    @foreach (var option in SomeService.Options)
    {
        <option value="@option">@option</option>
    }
</select>

JS stays the same as mikewodarczyk wrote, but let's at least use Typescript ;)

function getSelectedValues(sel: HTMLSelectElement)
{
    const results = [];

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

@MackinnonBuck
Copy link
Member

Closing because this was done in #33950.

@ghost ghost locked as resolved and limited conversation to collaborators Aug 5, 2021
@danroth27 danroth27 modified the milestones: 6.0-rc1, 6.0-preview7 Aug 31, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affected-most This issue impacts most of the customers area-blazor Includes: Blazor, Razor Components Done This issue has been fixed enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-razor.language Priority:2 Work that is important, but not critical for the release severity-major This label is used by an internal tool User Story A single user-facing feature. Can be grouped under an epic.
Projects
None yet
Development

No branches or pull requests