简体   繁体   中英

ASP.NET MVC cascading dropdown

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM