1

I have a List view like this:

@model List<ABC.Models.InfoDetails>

I use a for loop to display the values in a table in order to be able to edit each row and use a submit button (at the bottom of the table) to post the data back to the controller.

@using (Html.BeginForm("UpdateUsers", "User")) {
<table ...

<tbody>
    @for (var i = 0; i < Model.Count(); i++) {
 ...
}

The values are posted back like this:

[0].Title

[1].Title

etc.

This is fine and I get the correct values in the controller.

The only problem I have is posting the selected value from a select2 dropdown element of each row.

<select class="js-select2 form-control" name="user" id="select2-user">

The name value ("user") is posted to the controller instead of the name [0].User

My Javascript:

var users = [
                { id: '0', text: 'Please choose...' },
                { id: '1', text: 'Paul' }
                ];

$("[name='user']").select2({
                placeholder: "Select a user",
                data: users
            });

Is there any way to put the value to the according index of each user property?

I hope you can help me.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
ratanmalko
  • 449
  • 4
  • 20
  • 1
    Generate the ` –  Jan 16 '18 at 08:20
  • Can you show me the syntax? This is not working: `@Html.DropDownListFor(modelItem => modelItem[i].User, null, new { htmlAttributes = new { @name = "@modelItem[i].User", @class = "js-select2 form-control"} })` "There is no ViewData item of type 'IEnumerable' that has the key '[0].User'" – ratanmalko Jan 16 '18 at 08:42
  • (1). NEVER attempt to change the `name` attribute when using `HtmlHelper` methods. (2). The error is explained [here](https://stackoverflow.com/questions/34366305/the-viewdata-item-that-has-the-key-xxx-is-of-type-system-int32-but-must-be-o) - you need to pass an collection of Users to the view (refer also [this answer](https://stackoverflow.com/questions/37407811/mvc5-razor-html-dropdownlistfor-set-selected-when-value-is-in-array/37411482#37411482) for more detail about using dropdownlists in a loop –  Jan 16 '18 at 08:46

2 Answers2

2

Always use the HtmlHelper methods to generate the correct html (including the name attribute) and bind to your model. I also recommend that you generate the collection for the options in the controller and pass it to the model, rather than generating them in the view. Ideally you would do this using a view model

public class InfoDetailsVM
{
    public IEnumerable<User> UserList { get; set; }
    public List<InfoDetails> Details { get; set; }
}

Note this assumes your have a User class containing properties int ID and string Name

and in the GET method

InfoDetailsVM model = new InfoDetailsVM
{
    Details = ... // your current query for the collection of InfoDetails
};
ConfigureViewModel(model);
return View(model);

Where ConfigureViewModel() is

private void ConfigureViewModel(InfoDetailsVM model)
{
    model.UserList = ... // your code to return a collection of Users
}

And in the view

@model InfoDetailsVM
....
@for(int i = 0; i < Model.Details.Count; i++)
{
    @Html.LabelFor(m => m.Details[i].User)
    @Html.DropDownListFor(m => m.Details[i].User, 
        new SelectList(Model.UserList, "ID", "Name", Model.Details[i].User,
        "Select a user", 
        new { @class = "js-select2 form-control" }
    )
    @Html.ValidationMessageFor(m => m.Details[i].User)
    ....
}

and the script will be just

$('.js-select2').select2();

Side notes:

  1. For more information on generating dropdownlists in a loop, refer MVC5 Razor html.dropdownlistfor set selected when value is in array
  2. The separate ConfigureViewModel() method allows you to call it in the POST method (without duplicating code), which you need to do if ModelState is invalid and you need to return the view.
1
@Html.DropDownListFor(items => Model[i].UserID,                                
 new SelectList(@Model.Users, "id", "text", @Model.Users[i].id),            
 new                                                                          
 {                                                                       
   @class = "select2-hidden-accessible",                              
   @aria_hidden = "true"                                                     
})

Try to render in razor syntax. And give class = "select2-hidden-accessible"

Yogesh Patel
  • 818
  • 2
  • 12
  • 26