2015-01-23 4 views
5

Я пытаюсь создать представление, которое имеет два DropDownLists. Параметры, доступные во втором DropDownList, зависят от того, что пользователь выбрал в первом. Я передаю эти данные на мой взгляд в ViewBag следующим образом:MVC 4 Razor - Создание динамического DropDownList

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

Первый объект имеет выбор для первого DropDownList. Когда пользователь выбирает один из них, мне нужно получить соответствующий список вариантов для второго DropDownList из моего Словаря. Я просто не могу понять, как этого добиться. Если я получу новый выбор первого DropDownList в функции Javascript onchange(), похоже, не будет никакого способа использовать это значение в качестве ключа для моего словаря C#.

Конечно, я видел эту функциональность в Интернете, поэтому я знаю, что это возможно как-то. Как я могу это достичь?

Спасибо!

ответ

7

Существует несколько способов сделать это, не заставляя вас хранить все возможные элементы данных в модели, но я предпочитаю использовать Javascript/JQuery. Вот пример страны/государственного каскадные раскрывающийся:

Javascript используется для получения состояния, когда выбрана страна:

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

Страна выпадающий:

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

раскрытом состоянии:

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" }) 

Метод контроллера для извлечения состояний:

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

Идея состоит в том, что при выборе выпадающего списка 1 вы используете ajax, чтобы получить второе значение выпадающего списка.

Edit: Забыл включить служебный метод для построения URLs

+0

Это именно то, что я искал! Благодарю. –

3

.change события вашего первых выбери следует заполнить второй выбор, вызвав метод сервера, который возвращает данные опции на основе выбранного значения. Учитывая следующий вид модель

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

Контроллера

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

Просмотр

@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)); 
    }); 
    }); 
}); 
+0

Также отличный ответ. Благодаря! –

Смежные вопросы