Заполнение выпадающего списка с использованием MVC2 на основе другого выпадающего списка (каскадный DropDownList) - PullRequest
6 голосов
/ 19 сентября 2010

Я делаю заявку, которая занимается транспортными средствами.Мне нужны два DropDownLists:

  • Makes: все машины делают
  • Модели: модели, которые относятся к выбранному значению Make DropDownList

Как это делается в MVC2?

Моя идея: использовать ли вызов ajax, когда выбран мой первый список, и затем вернуть модели для привязки к DDL модели?Как привязка модели может вступить в игру таким образом?

ОБНОВЛЕНИЕ Я опубликовал то, что в итоге сделал, в качестве ответа.Это супер просто и прекрасно работает.

Вы также можете использовать get, если вы чувствуете себя таким склонным, но вы должны указать, что вам так нравится ... return Json(citiesList, JsonRequestBehavior.AllowGet);

Ответы [ 3 ]

13 голосов
/ 19 сентября 2010

Это то, что я в итоге сделал ... Не нужно дополнительных плагинов / 1000 строк кода ...

HTML

//The first DDL is being fed from a List in my ViewModel, You can change this...
<%: Html.DropDownList("MakeList", new SelectList(Model.Makes, "ID", "Name")) %>
<select id="ModelID" name="ModelID" disabled="disabled"></select>

JQuery

    $(document).ready(function () {
        $('#MakeList').change(function () {
            $.ajaxSetup({ cache: false });
            var selectedItem = $(this).val();
            if (selectedItem == "" || selectedItem == 0) {
                //Do nothing or hide...?
            } else {
                $.post('<%: ResolveUrl("~/Sell/GetModelsByMake/")%>' + $("#MakeList > option:selected").attr("value"), function (data) {
                    var items = "";
                    $.each(data, function (i, data) {
                        items += "<option value='" + data.ID + "'>" + data.Name + "</option>";
                    });
                    $("#ModelID").html(items);
                    $("#ModelID").removeAttr('disabled');
                });
            }
        });
    });

Акция

    [HttpPost]
    public ActionResult GetModelsByMake(int id)
    {
        Models.TheDataContext db = new Models.TheDataContext();
        List<Models.Model> models = db.Models.Where(p=>p.MakeID == id).ToList();

        return Json(models);
    }
9 голосов
/ 19 сентября 2010

Вот хороший способ сделать это:

Предположим, что у нас есть два раскрывающихся списка, страна и город, раскрывающийся список городов по умолчанию отключен, и при выборе страны происходит следующее:

1. city drop down list gets enabled.
2. An AJAX call is made to an action method with the selected country and a list of cities is returned.
3. the city drop down list is populated with the JSON data sent back.

Кредиты за оригинальный код отправляются на King Wilder из MVC Central . Этот пример является упрощенной версией, извлеченной из его кода в серии Golf Tracker .

.

HTML

<select id="Country">
// a List of Countries Options Goes Here.
</select></div>

<select id="City" name="City" disabled="disabled">
// To be populated by an ajax call
</select>

JavaScript

// Change event handler to the first drop down ( Country List )
$("#Country").change(function() {
    var countryVal = $(this).val();
    var citySet = $("#City");

    // Country need to be selected for City to be enabled and populated.
    if (countryVal.length > 0) {
        citySet.attr("disabled", false);
        adjustCityDropDown();
    } else {
        citySet.attr("disabled", true);
        citySet.emptySelect();
    }
});

// Method used to populate the second drop down ( City List )   
function adjustCityDropDown() {
    var countryVal = $("#Country").val();
    var citySet = $("#City");
    if (countryVal.length > 0) {
        // 1. Retrieve Cities that are in country ...
        // 2. OnSelect - enable city drop down list and retrieve data
        $.getJSON("/City/GetCities/" + countryVal ,
        function(data) {
            // loadSelect - see Note 2 bellow
            citySet.loadSelect(data);
        });
    }
}

Метод действия

[HttpGet]
public ActionResult GetCities(string country)
{
    Check.Require(!string.IsNullOrEmpty(country), "State is missing");

    var query  = // get the cities for the selected country.

    // Convert the results to a list of JsonSelectObjects to 
    // be used easily later in the loadSelect Javascript method.         
    List<JsonSelectObject> citiesList = new List<JsonSelectObject>();
        foreach (var item in query)
        {
            citiesList.Add(new JsonSelectObject { value = item.ID.ToString(),
                                                  caption = item.CityName });
        }        

    return Json(citiesList, JsonRequestBehavior.AllowGet);
}

Важные примечания:

1. JsonSelectObject помогает упростить процесс преобразования результатов в тег опции, так как он будет использоваться в методе javascript loadSelect ниже. в основном это класс со значением и заголовком двух свойств:

public class JsonSelectObject
{
    public string value { get; set; }
    public string caption { get; set; }
}

2. Функция loadSelect - это вспомогательный метод, который принимает список объектов json, изначально принадлежащих к типу JsonSelectObject, и преобразует его в список параметров, которые будут добавлены в раскрывающийся список вызовов. Это классный трюк из книги «jQuery In Action», на который ссылается оригинальный код, он включен в файл jquery.jqia.selects.js, на который вам нужно будет сослаться. Вот код в этом файле js:

(function($) {
    $.fn.emptySelect = function() {
        return this.each(function() {
            if (this.tagName == 'SELECT') this.options.length = 0;
        });
    }

    $.fn.loadSelect = function(optionsDataArray) {
        return this.emptySelect().each(function() {
            if (this.tagName == 'SELECT') {
                var selectElement = this;
                selectElement.add(new Option("[Select]", ""), null);
                $.each(optionsDataArray, function(index, optionData) {
                    var option = new Option(optionData.caption,
                                  optionData.value);
                    if ($.browser.msie) {
                        selectElement.add(option);
                    }
                    else {
                        selectElement.add(option, null);
                    }
                });
            }
        });
    }

})(jQuery);

Этот метод может быть сложным ,,, но в конце у вас будет чистый и компактный код, который вы сможете использовать везде.

Надеюсь, это было полезно ,,,


Обновление

Использование POST вместо GET в вызове AJAX

Вы можете заменить вызов $.getJSON следующим кодом, чтобы сделать вызов ajax с использованием POST вместо GET.

$.post("/City/GetCities/", { country: countryVal }, function(data) {
     citySet.loadSelect(data);
 });

также не забудьте изменить метод Action для приема запросов POST, изменив аннотацию [HttpGet] с помощью [HttpPost] и удалив JsonRequestBehavior.AllowGet при возврате результата в метод действия.

Важное примечание

Обратите внимание, что мы используем значение выбранного элемента, а не имя. например, если пользователь выбрал следующую опцию.

<option value="US">United States</option>

тогда «US» отправляется методу Action, а не «United States»

Обновление 2: доступ к выбранным значениям в контроллере

предположим, что в вашей Vehicle viewmodel есть следующие два свойства:

public string Maker { get; set; }
public string Model { get; set; }

и вы называете выбранные элементы тем же именем, что и свойства ViewModel.

<select id="Maker" name="Maker">
// a List of Countries Options Goes Here.
</select></div>

<select id="Model" name="Model" disabled="disabled">
// To be populated by an ajax call
</select>

Тогда выбранные значения будут автоматически привязаны к вашей ViewModel, и вы сможете получить к ним доступ непосредственно в вашем методе действия.

Это будет работать, если страница строго типизирована для этой ViewModel.


Примечание. Для первого списка (The Makes List) вы можете создать MakersList типа SelectList в вашей ViewModel и использовать помощник HTML, чтобы автоматически заполнить ваш Makers Drop Down списком в вашей ViewModel. код будет выглядеть примерно так:

<%= Html.DropDownListFor(model => model.Maker, Model.MakersList) %>

В этом случае сгенерированное имя для этого выбора также будет «Создатель» (имя свойства в ViewModel).

Я надеюсь, что это ответ, который вы ищете.

2 голосов
/ 19 сентября 2010

Самый простой способ - использовать плагин jQuery "cascade".http://plugins.jquery.com/project/cascade (посмотрите на демонстрационную страницу там).

Если вы хотите разрешить значение с помощью ajax, это также поможет вам и исключит много кода из предыдущего ответа, так что вы можете сосредоточитьсяпо вашей логике:)

В гугле можно найти много примеров, но в итоге вы получите только следующий скрипт:

$('#myChildSelect').cascade('#myParentSelect', 
{
    ajax: '/my/url/action',
    template: function(item) {
        return "<option value='" + item.value + "'>" + item.text + "</option>"; },
    match: function(selectedValue) { return this.when == selectedValue; }    
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...