简体   繁体   中英

How to bind selected values from dropdownlists in a dynamically generated table? ASP.NET Core MVC

In my ASP.NET Core MVC project there is a table with two columns containing dropdownlists where the user is supposed to pick rates values and click save to update them for each row in the table. There are dozens of dynamically generated rows in total, which results in twice as many dropdownlists with values to track.

Again, the goal is to update each row with the values selected in the two dropdownlists in that row.

I was able to create the table and display the values. There is a loop that generates each row in the table. The issue I am having is not knowing how to pass all of the values from all of the dropdownlists back to the controller along with rownumbers so I can write the logic to update the values in the database. I can pass a single dropdown combination from the first row and I don't know how to do the same for all of them or indicate which row they are from. The fact that dropdownlists are in a loop makes this difficult.

This is the part of the view where I display the table:

      <tbody>
      @foreach (var item in Model.WorksheetRates)
      {
      var recordNumber = PagedContext.Page * PagedContext.PageSize + Model.WorksheetRates.IndexOf(item) + 1;
      <tr>
           <td>@recordNumber</td>
           <td>
               @item.Program
           </td>
           <td>
               @item.Area
           </td>
            <td>
                @Html.DropDownListFor(x => x.GARateID, gaRatesList, new { @style = "width:280px;" })
            </td>
             <td>
                 @Html.DropDownListFor(x => x.OverheadRateID, overheadRatesList, new { @style = "width:280px;" })
             </td>
         </tr>
      }
                        </tbody>

This is the model:

public class BudgetPrepViewModel
{
    public List<WorksheetRate> WorksheetRates { get; set; }

    public int GARateID { get; set; }
    public int OverheadRateID { get; set; }

    public IEnumerable<SelectListItem> GARateList { get; set; }
    public IEnumerable<SelectListItem> OverheadRateList { get; set; }
}

As you can see I added IEnumerable<SelectListItem> object because I thought they would need to be used and iterated in the controller. This is a guess, I don't know how to bind to them. And it's important I associate them with the correct row.

This is what I came up with in the controller for the header, the actual code inside is not relevant to the question:

[HttpPost, ActionName("SelectRates")]
public IActionResult SelectRates([Bind("GARateID, OverheadRateID")] BudgetPrepViewModel data)
{
        BPViewModel model = new BPViewModel
        {
            MonthNameList = MonthSelectList(),
            PrepStep = 8
        };

       return View("Index", model);
}

Any help would be appreciated. Please let me know if something is not clear, I did my best to describe this question. Thank you!

First of all, I'm assuming that WorksheetRate has GARateID and OverheadRateID as properties, since they are inside the same table row. Secondly, I've added a property Id to the WorksheetRate so that the selected options could be identified when the form is submitted. That said, now the classes are like this:

public class WorksheetRate
{
    public int Id { get; set; }
    public string Program { get; set; }
    public string Area { get; set; }
    public int GARateID { get; set; }
    public int OverheadRateID { get; set; }
}
public class BudgetPrepViewModel
{
    public List<WorksheetRate> WorksheetRates { get; set; }

    public IEnumerable<SelectListItem> GARateList { get; set; }
    public IEnumerable<SelectListItem> OverheadRateList { get; set; }
}

The key aspect here is that the name of the selects and inputs must follow a pattern so that ASP.NET bind it to the model. For this case, to bind values to the property GARateID from BudgetPrepViewModel.WorksheetRates the name of selects and inputs must be:

  • selects:
    • <select name="WorksheetRates[0].GARateID">
    • <select name="WorksheetRates[1].GARateID">
  • inputs
    • <input hidden name="WorksheetRates[0].Id" />
    • <input hidden name="WorksheetRates[1].Id" />

Therefore, the solution is:

@for (var i=0; i<Model.WorksheetRates.Count(); i++)
{
    <tr>
        <td>
            @Model.WorksheetRates[i].Id
            <input hidden asp-for="WorksheetRates[i].Id" /> 
        </td>
        <td>
            @Model.WorksheetRates[i].Program
        </td>
        <td>
            @Model.WorksheetRates[i].Area
        </td>
        <td>
            @Html.DropDownListFor(x => x.WorksheetRates[i].GARateID, Model.GARateList, new { @style = "width:280px;" })
        </td>
        <td>
            @Html.DropDownListFor(x => x.WorksheetRates[i].OverheadRateID, Model.OverheadRateList, new { @style = "width:280px;" })
        </td>
    </tr>
}

I have created arepository with the full working solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM