MVC 4 Razor - Creating a Dynamic DropDownList

I am trying to create a view with two DropDownLists. The options available in the second DropDownList depend on what the user selected in the first. I pass this data to my view in the ViewBag as follows:

List<SelectListItem> firstBoxChoices = ViewBag.firstBoxChoices; Dictionary<string, List<SelectListItem>> secondBoxDict = ViewBag.secondBoxDict; 

The first object has a choice for the first DropDownList. When the user selects one of them, I need to get the appropriate list of options for the second DropDownList from my Dictionary. I just can't figure out how to achieve this. If I get a new selection of the first DropDownList in the Javascript onchange () function, there seems to be no way to use this value as a key for my C # dictionary.

Of course, I saw this functionality on the Internet, so I know that it is possible somehow. How can I achieve this?

Thanks!

+5
source share
2 answers

There are several ways to do this without forcing you to store all possible data elements in the model, but I prefer to use Javascript / JQuery. The following is an example of cascading a country / state:

Javascript is used to get states when choosing a country:

 <script type="text/javascript"> function AppendUrlParamTokens(url, params) { for (var param in params) { if (params[param] == null) { delete params[param]; } } return url + "?" + jQuery.param(params); } function OnCountriesChange(ddl) { jQuery.getJSON(AppendUrlParamTokens('@Url.Action("GetStates", "Data")', { countryId: ddl.options[ddl.selectedIndex].value }), function (result) { var target = jQuery('#states_ddl'); target.empty(); jQuery(result).each(function() { jQuery(document.createElement('option')) .attr('value', this.Value) .text(this.Text) .appendTo(target); }); }); }; </script> 

Country dropdown menu:

 @Html.DropDownListFor(model => model.Country, new SelectList(Model.Countries, "Value", "Text", Model.PreviousCountrySelected), "(Select One)", new { id = "countries_ddl", onchange = "OnCountriesChange(this)" }) 

Status Dropdown Menu:

 Html.DropDownListFor(model => model.State, Model.States != null ? new SelectList(Model.States, "Value", "Text", Model.PreviousStateSelected) : new SelectList(new List<SelectListItem>(), "Value", "Text"), new { id = "states_ddl" }) 

Controller method for retrieving states:

 public ActionResult GetStates(short? countryId) { if (!countryId.HasValue) { return Json(new List<object>(), JsonRequestBehavior.AllowGet); } var data = GetAllStatesForCountry(countryId.Value).Select(o => new { Text = o.StateName, Value = o.StateId }); return Json(data, JsonRequestBehavior.AllowGet); } 

The idea is that when you select dropdown 1, you use ajax to get the second value of the dropdown.

Edit: Forgot to enable the utility method for creating urls

+7
source

The .change event of your first choice should populate the second choice by invoking a server method that returns option data based on the selected value. Given the following presentation model

 public class MyModel { [Required(ErrorMessage = "Please select an organisation")] [Display(Name = "Organisation")] public int? SelectedOrganisation { get; set; } [Required(ErrorMessage = "Please select an employee")] [Display(Name = "Employee")] public int? SelectedEmployee { get; set; } public SelectList OrganisationList { get; set; } public SelectList EmployeeList { get; set; } } 

controller

 public ActionResult Edit(int ID) { MyModel model = new MyModel(); model.SelectedOrganisation = someValue; // set if appropriate model.SelectedEmployee = someValue; // set if appropriate ConfigureEditModel(model); // populate select lists return View(model); } [HttpPost] public ActionResult Edit(MyModel model) { if(!ModelState.IsValid) { ConfigureEditModel(model); // reassign select lists return View(model); } // save and redirect } private void ConfigureEditModel(MyModel model) { // populate select lists model.OrganisationList = new SelectList(db.Organisations, "ID", "Name"); if(model.SelectedOrganisation.HasValue) { var employees = db.Employees.Where(e => e.Organisation == model.SelectedOrganisation.Value); model.EmployeeList = new SelectList(employees, "ID", } else { model.EmployeeList = new SelectList(Enumerable.Empty<SelectListItem>()); } } [HttpGet] public JsonResult FetchEmployees(int ID) { var employees = db.Employees.Where(e => e.Organisation == ID).Select(e => new { ID = e.ID, Name = e.Name }); return Json(employees, JsonRequestBehavior.AllowGet); } 

View

 @model MyModel .... @Html.LabelFor(m => m.SelectedOrganisation) @Html.DropDownListFor(m => m.SelectedOrganisation, Model.OrganisationList, "-Please select-") @Html.ValidationMessageFor(m => m.SelectedOrganisation) @Html.LabelFor(m => m.SelectedEmployee) @Html.DropDownListFor(m => m.SelectedEmployee, Model.EmployeeList, "-Please select-") @Html.ValidationMessageFor(m => m.SelectedEmployee) .... 

Script

 var url = '@Url.Action("FetchEmployees")'; var employees = $('SelectedEmployee'); $('#SelectedOrganisation').change(function() { employees.empty(); if(!$(this).val()) { return; } employees.append($('<option></option>').val('').text('-Please select-')); $.getJson(url, { ID: $(this).val() }, function(data) { $.each(data, function(index, item) { employees.append($('<option></option>').val(item.ID).text(item.Text)); }); }); }); 
+3
source

Source: https://habr.com/ru/post/1211786/


All Articles