Reputation: 1
I have three tables in my database as follows:
University
id Name
1 A
2 B
Faculty
id id_uni name
1 1 AA
2 1 AA
cafedry
id id_uni id_faculty name
1 1 1 cc
I would like to create a cascading dropdown which will allow me to first select a University then a Faculty followed by a Cafedry. Below code is what i have tried so far.
public ActionResult Create()
{
ViewBag.fak_kod = new SelectList(db.Fakulteler, "id", "adi");
ViewBag.unikod = new SelectList(db.Universitetler, "id", "adi");
return View();
}
// POST: kafedras/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,unikod,fak_kod,adi")] kafedra kafedra)
{
if (ModelState.IsValid)
{
db.kafedra.Add(kafedra);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.fak_kod = new SelectList(db.Fakulteler , "id", "adi", kafedra.fak_kod);
ViewBag.unikod = new SelectList(db.Universitetler, "id", "adi", kafedra.unikod);
return View(kafedra);
}
and this cshtml
<div class="form-horizontal">
<h4>kafedra</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.unikod, "unikod", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("unikod", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.unikod, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.fak_kod, "fak_kod", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownList("fak_kod", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.fak_kod, "", new { @class = "text-danger" })
</div>
</div>
How can update this code to create a cascading dropdown with the three tables?
Upvotes: 0
Views: 8060
Reputation: 218922
To start with, create a view model which has properties to render the options and store the selected item value.
public class CreateVm
{
[Required]
public int SelectedUniversity { set;get;}
[Required]
public int SelectedFaculty { set;get;}
public List<SelectListItem> Universities { set;get;}
public List<SelectListItem> Faculties { set;get;}
public CreateVm()
{
this.Faculties = new List<SelectListItem>();
this.Universities = new List<SelectListItem>();
}
}
Now in your GET action, create an object of this, load the Universities
property and send the object to the view
public AcitonResult Create()
{
var vm=new CreateVm();
vm.Universities= GetUniversities();
return View(vm);
}
private List<SelectListItem> GetUniversities()
{
return db.Universitetler
.Select(x=>new SelectListItem { Value = x.Id,
Text = x.Name)
.ToList();
}
Now in your View, which is strongly typed to our CreateVm
view model. we will use the DropDownListFor
helper method to render the drop-downs
@model CreateVm
@using (Html.BeginForm("Create", "Home"))
{
@Html.DropDownListFor(a=>a.SelectedUniversity,Model.Universities,"Select one")
@Html.DropDownListFor(a => a.SelectedFaculty , Model.Faculties, "Select one",
new { data_url = Url.Action("GetFaculties") })
<input type="Submit" />
}
This will render 2 dropdowns, one with University options and the second one will be empty (because we did not load anything to the Faculties
property). Now we will have some javascript(we are using jquery here for easy DOM manipulation) which will listen to the change event of the first drop-down(Universities) ,read the selected value and make an ajax call to the GetFaculties
method and passing the selected university option value.
You can see that , i set a html5 data attribute for the second dropdown where i am storing the relative url to the GetFaculties
method. So in my javascript, i can simply read this data attribute value and make a call to that url to get the data.
$(function () {
$("#SelectedUniversity").change(function () {
var v = $(this).val();
var url = $("#SelectedFaculty").data("url") + '?u=' + v;
var $fac= $("#SelectedFaculty");
$.getJSON(url, function (data) {
$fac.empty();
$.each(data, function (i, item) {
$fac.append($("<option>").text(item.Text).val(item.Value));
});
});
});
});
Now, let's add a GetFaculties
action method which accepts the university id and return the faculties for that university in a list of SelectListItem
as JSON array.
public ActionResult GetFaculties(int u)
{
var facultyList = db.Fakulteler
.Where(a=>a.id_uni==u)
.Select(x=>new SelectListItem { Value=x.Id,
Text=x.Name).ToList();
return Json(facultyList , JsonRequestBehavior.AllowGet);
}
You may use the same view model in the HttpPost action
[HttpPost]
public ActionResult Create(CreateVm vm)
{
if (ModelState.IsValid)
{
//read from vm and save
var k=new kafedra {
UniveristyId=vm.SelectedUniversity,
FacultyId=vm.SelectedFaculty,
};
db.kafedra.Add(k);
db.SaveChanges();
return RedirectToAction("Index");
}
vm.Universities= GetUniversities();
return View(vm);
}
Upvotes: 3