0

I am very new to MVC and I am trying to create a cascading drop down. The user will select the name of the practice and the drop down below will populate with the names of the opticians who work at that practice.

Optician Model:

public class Optician
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid OpticianId { get; set; }

[ForeignKey("User")]
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
public IEnumerable<SelectListItem> UserList { get; set; }

[ForeignKey("Practice")]
public Guid PracticeId { get; set; }
public virtual Practice Practice { get; set; }
public IEnumerable<SelectListItem> PracticeList { get; set; }

public virtual ICollection<ApplicationUser> Users { get; set; }

public virtual ICollection<Practice> Practices { get; set; }
}

Practice Model:

public class Practice
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Display(Name = "Practice")]
public Guid PracticeId { get; set; }

[Display(Name = "Practice Name")]
public string PracticeName { get; set; }


public virtual ICollection<Optician> Opticians { get; set; }

public virtual ICollection<Booking> Bookings { get; set; }
}

Application User Model:

public class ApplicationUser : IdentityUser
{
[Display(Name = "Title")]
public string Title { get; set; }

[Display(Name = "First Name")]
public string FirstName { get; set; }

[Display(Name = "Last Name")]
public string LastName { get; set; }
}

The Controller:

public ActionResult TestDropDown()
    {

        var practices = new SelectList(db.Practices, "PracticeId", "PracticeName");
        ViewData["Practices"] = practices;

        return View();
    }

    [HttpPost]
    public JsonResult Opticians(Guid? Id)
    {
        var opticianList = db.Opticans.Where(a => a.PracticeId == Id).Select(a => a.User).ToList();


        return Json(opticianList, JsonRequestBehavior.AllowGet);
    }

The View:

<script src="~/Scripts/jquery-1.10.2.js"></script>

<script>
$(document).ready(function () {
    $("#Optician").prop("disabled", true);
    $("#Practice").change(function () {
        $.ajax({
            url : "@Url.Action("Opticians","Bookings1")",
            type : "POST",
            data : {Id : $(this).val() }
        }).done(function(OpticianList){
            $("#Optician").empty();
            for (var i = 0; i < OpticianList.length; i++) {
                $("#Optician").append("<option>" + OpticianList[i].FirstName + "</option>");
            }
            $("#Optician").prop("disabled", false);
        });
});
});

</script>


@using (Html.BeginForm("TestDropDown", "Bookings1", FormMethod.Post))
{
@Html.AntiForgeryToken()
<h4>Select Practcie & Opticians</h4>
<hr />
@Html.ValidationSummary()
<div class="form-group">
    @Html.Label("Select Practice :", new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        @Html.DropDownList("PracticeId", ViewData["Practices"] as SelectList, new { @class = "form-control" })
    </div>
</div><br />
<div class="form-group">
    @Html.Label("Select Optician :", new { @class = "col-md-2 control-label" })
    <div class="col-md-10">
        <select id="Optician"></select>
    </div>
</div>
<div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <input type="submit" class="btn btn-default" value="Submit" />
    </div>
</div>
}

I can select the Name of the practice but the drop down for the Optician First Name does not populate. Any help would be greatly appreciated Thanks

coto2
  • 179
  • 4
  • 15
  • 1
    What errors are you getting in the browser console? –  Sep 01 '15 at 08:30
  • 1
    And if you only want the `FirstName` property of `ApplicationUser`, then it should be `.Select(a => a.User.FirstName)` - no point sending a whole lot of extra data back to the browser when you don't even use it –  Sep 01 '15 at 08:32
  • @StephenMuecke Thanks. There are no errors in the browser console – coto2 Sep 01 '15 at 08:54
  • 1
    The `$("#Practice").change(function () {` function wont ever be hit - your first dropdown is ` –  Sep 01 '15 at 08:58
  • @StephenMuecke Thanks Stephen, I changed it and the optician drop down seems to be populating however the two options in the drop down are displaying as "undefined" – coto2 Sep 01 '15 at 09:17
  • @StephenMuecke Got it... I still had $("#Optician").append(""); and had changed the Json to .Select(a => a.User.FirstName). I removed the .FirstName on the $("#Optician").append and it works. Thanks for your help, I had been stuck on this for ages! – coto2 Sep 01 '15 at 09:24
  • Are you using `.Select(a => a.User.FirstName)` or `.Select(a => a.User)`? –  Sep 01 '15 at 09:24
  • There are a few other poor practices in you script, so I will post an answer later –  Sep 01 '15 at 09:25

2 Answers2

1

You first <select> has id="PracticeId" but you script refers to an element with id="Practice" which does not exist, therefore is never run. Change you script to

var optician = $("#Optician"); // cache elements that you repeately refer to
optician.prop("disabled", true);
$("#PracticeId").change(function () { // change the selector
  $.ajax({
      url : "@Url.Action("Opticians","Bookings1")",
      type : "POST",
      data : {Id : $(this).val() }
  }).done(function(OpticianList){
      optician.empty();
      for (var i = 0; i < OpticianList.length; i++) {
          optician.append("<option>" + OpticianList[i].FirstName + "</option>");
      }
      optician.prop("disabled", false);
  });
});

or you could just use the .getJSON() shortcut

$.getJSON('@Url.Action("Opticians","Bookings1")', { Id : $(this).val() }, function(OpticianList) {
  // add the option elements
}

Since you only need the FirstName property of ApplicationUser, your controller code should be

var opticianList = db.Opticans.Where(a => a.PracticeId == Id).Select(a => a.User.FirstName)

and the script adjusted to

optician.append("<option>" + OpticianList[i] + "</option>");

or

optician.append($('<option></option>').text(OpticianList[i]));

so your not sending back a whole lot of extra data across the wire that you never use.

0

Try this in your action:

    [HttpPost]
    public JsonResult Opticians(Guid? Id)
    {
        var opticianList = db.Opticans.Where(a => a.PracticeId == Id).Select(a => a.User).ToList();
        SelectList mySelectList = new SelectList(opticianList, "IDField", "DisplayField", 0);

        return Json(mySelectList );
    }

Here is the post I followed when I implemented this. Fill drop down list on selection of another drop down list

Community
  • 1
  • 1
  • Nonsense. Why would you send back extra properties such as the `Selected` property of `SelectListItem`. And if you _needed to add the SelectList_ then you doing something wrong –  Sep 01 '15 at 08:52
  • @akemp I tried that and updated the script but its still not working – coto2 Sep 01 '15 at 09:01