I am new to MVC and having great difficulty creating a cascading drop down from database. Upon selecting a practice the opticians who work in that practice populate however it will not save to dataView Model:
public class BookingViewModel
{
[Display (Name = "Select Patient")]
public Guid PatientId { get; set; }
public IEnumerable<SelectListItem> PatientList { get; set; }
[Display(Name = "Select Practice")]
public Guid PracticeId { get; set; }
public IEnumerable<SelectListItem> PracticeList { get; set; }
[Display(Name = "Select Optician")]
public Guid OpticianId { get; set; }
public IEnumerable<SelectListItem> OpticiansList { get; set; }
[Display(Name = "Select Date")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime Date { get; set; }
[Display(Name = "Select Time")]
public Guid TimeId { get; set; }
public IEnumerable<SelectListItem> TimeList { get; set; }
}
}
My Bookings Controller:
public ActionResult Create()
{
// Creates a new booking
BookingViewModel bookingViewModel = new BookingViewModel();
// Initilises Select List
ConfigureCreateViewModel(bookingViewModel);
return View(bookingViewModel);
}
// Initilises Select List
public void ConfigureCreateViewModel(BookingViewModel bookingViewModel)
{
// Displays Opticians Name
bookingViewModel.OpticiansList = db.Opticians.Select(o => new SelectListItem()
{
Value = o.OpticianId.ToString(),
Text = o.User.FirstName
});
// Displays Patients name
bookingViewModel.PatientList = db.Patients.Select(p => new SelectListItem()
{
Value = p.PatientId.ToString(),
Text = p.User.FirstName
});
// Displays Practice Name
bookingViewModel.PracticeList = db.Practices.Select(p => new SelectListItem()
{
Value = p.PracticeId.ToString(),
Text = p.PracticeName
});
// Displays Appointment Times
bookingViewModel.TimeList = db.Times.Select(t => new SelectListItem()
{
Value = t.TimeId.ToString(),
Text = t.AppointmentTime
});
}
// Allows Admin to create booking for patient
// POST: Bookings1/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(BookingViewModel bookingViewModel)
{
// to ensure date is in the future
if (ModelState.IsValidField("Date") && DateTime.Now > bookingViewModel.Date)
{
ModelState.AddModelError("Date", "Please enter a date in the future");
}
// if model state is not valid
if (!ModelState.IsValid)
{
// Initilises Select lists
ConfigureCreateViewModel(bookingViewModel);
return View(bookingViewModel); // returns user to booking page
}
else // if model state is Valid
{
Booking booking = new Booking();
// Sets isAvail to false
booking.isAvail = false;
booking.PracticeId = bookingViewModel.PracticeId;
booking.OpticianId = bookingViewModel.OpticianId;
booking.PatientId = bookingViewModel.PatientId;
booking.Date = bookingViewModel.Date;
booking.TimeId = bookingViewModel.TimeId;
// Generates a new booking Id
booking.BookingId = Guid.NewGuid();
// Adds booking to database
db.Bookings.Add(booking);
// Saves changes to Database
db.SaveChanges();
// Redirects User to Booking Index
return RedirectToAction("Index");
}
}
// Json for cascading drop down, to allow the user to select an optician from the selected practice.
[HttpPost]
public JsonResult Opticians(Guid Id)
{
var opticianList = db.Opticians.Where(a => a.PracticeId == Id).Select(a => a.User.FirstName).ToList();
return Json(opticianList);
}
My View:
<script>
$(document).ready(function () {
$("#OpticianId").prop("disabled", true);
$("#PracticeId").change(function () {
$.ajax({
url : "@Url.Action("Opticians","Bookings")",
type : "POST",
data : {Id : $(this).val() }
}).done(function (opticianList) {
$("#OpticianId").empty();
for (var i = 0; i < opticianList.length; i++) {
$("#OpticianId").append("<option>" + opticianList[i] + "</option>");
}
$("#OpticianId").prop("disabled", false);
});
});
});
<div class="form-group">
@Html.Label("Select Optician :", new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.DropDownListFor(model => model.OpticianId, Model.OpticiansList, "-Please Select-", new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.OpticianId, "", new { @class = "text-danger" })
</div>
</div>
The cascading drop down works fine but when I try to save it to database I am getting the Validation error -
The value 'Name' is not valid for Select Optician
Any help would be greatly appreciated. Thanks
Because your Opticians(Guid Id)
method is only returning the User.FirstName
property from your Opticians
table, so that the selected value of the dropdownlist for OpticianId
posts back the selected FirstName
value which cannot be bound to a Guid
property. The html your generating is
<option>Some Name</option>
but it needs to be
<option value="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx">Some Name</option>
Change the method to return both the ID and Name properties
[HttpPost]
public JsonResult Opticians(Guid Id)
{
var opticianList = db.Opticians.Where(a => a.PracticeId == Id).Select(a => new
{
Value = a.OpticianId,
Text = a.User.FirstName
}).ToList();
return Json(opticianList);
}
and then change the script to
var opticians = $("#OpticianId"); // cache elements you repeatedly refer to
opticians.prop("disabled", true);
$("#PracticeId").change(function () {
$.ajax({
url : "@Url.Action("Opticians","Bookings")",
type : "POST",
data : {Id : $(this).val() }
}).done(function (opticianList) {
opticians.empty();
$.each(opticianList, function(index, item) {
opticians.append($('<option></option>').val(item.Value).text(item.Text));
});
opticians.prop("disabled", false);
});
});
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.