Voici une petit tutorial pour créer un effet de cascade sur les DropDownList en MVC Razor.
Nous partirons sur un modele de Marque et de Voiture. Simple. Marque 1.n –> 1.1 Voiture. Avec ID et Libelle.
Déjà nous avons besoin dans la vue de 2 DropDownList.
Vue :
@Html.DropDownListFor(model => model.MarqueID, Model.Marques, new { onChange = "MarqueDDL()"})
@Html.ValidationMessageFor(model => model.MarqueID)
@Html.DropDownListFor(model => model.VoitureID, Model.Voitures)
@Html.ValidationMessageFor(model => model.VoitureID)
Vous pouvez passez par le ViewBag, personnellement j’ai opter pour une ViewModel plus simple.
Ensuite chargons les valeurs dans le contrôleur lors de l’appelle de la page. :
Controller :
model.MarqueID = 0;
model.Marques = new SelectList(db.Marque, "MarqueID", "Libelle", model.MarqueID);
model.Voitures = new SelectList(db.Voiture.Where(x => x.MarqueID == model.MarqueID), "VoitureID", "Libelle");
On retourne dans la Vue pour implementer la fonctions de cascade :
Vue
function ProjetDDL() {
var DDLparent = '#MarqueID'
var DDLchild = '#VoitureID'
cascade('@Url.Action("getVoitures")', 'marqID', $(DDLchild), false, DDLparent );
}
function cascade(url, paramName, childSelect, childCascade, parent) {
var selectedValue = $(parent).val();
var params = {};
params[paramName] = selectedValue;
childSelect.empty();
$.getJSON(url, params, function (items) {
$.each(items, function (index, item) {
childSelect.append($('').attr('value', item.Id).text(item.Name));
if (item.Selected) {
$(childSelect).children().last().attr("selected", true);
}
});
if (childCascade) { childSelect.change(); }
});
}
La fonction cascade est une adaptation du script que l’on peut trouver ici.
Cette fonction demande les paramètres suivant : l’URL de la fonction qui retournera la nouvelle liste à afficher (voir çi-dessous), le nom paramètre d’entrée (et non sa valeur), la DropDownList à peupler, si la DropDownList peupler va entraîner une nouvelle cascade, et la DropDownList qui vient d’être modifier.
Et nous retournons dans le contrôleur pour renvoyé à la vue les valeurs de la DropDownList enfant.
Controller
[HttpGet]
public ActionResult getVoitures(int marqID)
{
//Récupération via un paramètre
//Id et Name sont obligatoire, même pour des Enumerable
var voitures = db.Voiture.Where(x => x.MarqueID == marqID).Select(
x => new
{
Id = x.LotID,
Name = x.Libelle
});
return Json(voitures, JsonRequestBehavior.AllowGet);
}
Vous remarquerez que le nom de la variable d’entrée est celle qui a été indiqué dans la fonction en JS cascade().
Petit bonus, si vous souhaitez préselectionner une valeur dans la DropDownList enfant, il suffit lors de la création de la SelectList d’indiqué le paramètre Selected à true comme ceçi :
var voitures = db.Voiture.Where(x => x.MarqueID == marqID).Select(
x => new
{
Id = x.VoitureID,
Name = x.Libelle,
Selected = x.MiseEnAvant == true ? true : false
});
Dans cet exemple, j’ai une variable MiseEnAvant de type bool, mais ça pourrait être un int, un string une valeur par défaut.
Update : Problème de Cache sous IE 7 – 8
Voir en bas de ce billet précédent