I am trying to Create a page that has 3 cascading dropdowns for vehicle Make, Model and Variant.
Clicking on Search button must post the page to another controller and view using the ViewModel which will show the details of the vehicle selected on the index page.
Models
public class Vehicle
{
public IEnumerable<SelectListItem> Make{ get; set; }
public IEnumerable<SelectListItem> Model { get; set; }
public IEnumerable<SelectListItem> Variant { get; set; }
}
public class Details
{
public string PowerOutput{ get; set; }
public string NumberOfDoors{ get; set; }
public string VariantName { get; set; }
}
HomeController
VehicleEntities db = new VehicleEntities();
public ActionResult Index()
{
var model = new Vehicle
{
BrandName = GetMakes()
};
return View(model);
}
private IEnumerable<SelectListItem> GetMakes()
{
IEnumerable<SelectListItem> brandname = from s in db.prcGetMakes(null)
select new SelectListItem
{
Selected = s.Make.ToString() == "Active",
Text = s.Make,
Value = s.Make
};
return new SelectList(brandname, "Value", "Text");
}
public JsonResult GetModels(string make)
{
var list = db.prcGetModels(make);
return Json(new SelectList(list, "Model", "Model"), JsonRequestBehavior.AllowGet);
}
public JsonResult GetVariants(string model)
{
var list = db.prcGetVariants(model);
return Json(new SelectList(list, "Variant", "Variant"), JsonRequestBehavior.AllowGet);
}
View
@model WebApplication7.ViewModels.VehicleDetailsViewModel**
@using (Html.BeginForm("Index", "Vehicle", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
<div class="form-group">
<div class="col-md-3">
@Html.Label("Make", new { @class = "col-md-2 control-label" })
@Html.DropDownList("Make", Model.Make as SelectList, htmlAttributes: new { @class = "form-control minimal", @onchange = "refreshModelFromBrandName()" })
</div>
<div class="col-md-3">
@Html.LabelFor(model => model.Model, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.DropDownList("Model", Model.Model as SelectList, htmlAttributes: new { @class = "form-control minimal", @onchange = "refreshVariantFromModel()" })*@
</div>
<div class="col-md-3">
@Html.LabelFor(model => model.Brand, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.DropDownList("Variant", Model.Variant as SelectList, htmlAttributes: new { @class = "form-control minimal", @onchange = "" })*@
</div>
<div class="col-md-3">
<input id="search" type="submit" value="Search" />
</div>
</div>
}
<script type="text/javascript">
function refreshBrandName() {
// get references to the source and target drop downs html controls
// These are jquery searches to find the drop down controls
// find a control with id=BrandName
src = $("#Make");
// find a control with id=Model (you need to add this to your view)
tgt = $("#BrandName");
// clear drop down
tgt.empty();
// Get new model dataset via ajax
// based on BrandName
// The url parameter points at your web method
$.ajax({
type: 'GET',
//url: 'GetMakes',
url: 'GetMakes',
dataType: 'json',
data: { brandName: src.val() },
// success is called when dataset returns
success: function (p) {
// Populate with each returned member
$.each(p, function (i, pr) {
tgt.append(
'<option value="' + pr.Value + '">' +
pr.Text + '</option>'
);
})
}
});
}
function refreshModelFromBrandName() {
// get references to the source and target drop downs html controls
// These are jquery searches to find the drop down controls
// find a control with id=BrandName
src = $("#Make");
// find a control with id=Model (you need to add this to your view)
tgt = $("#Model");
// clear drop down
tgt.empty();
// Get new model dataset via ajax
// based on BrandName
// The url parameter points at your web method
$.ajax({
type: 'GET',
url: 'GetModels',
dataType: 'json',
data: { brandName: src.val() },
// success is called when dataset returns
success: function (p) {
// Populate with each returned member
$.each(p, function (i, pr) {
tgt.append(
'<option value="' + pr.Value + '">' +
pr.Text + '</option>'
);
})
}
});
}
function refreshVariantFromModel() {
// get references to the source and target drop downs html controls
// These are jquery searches to find the drop down controls
// find a control with id=BrandName
src = $("#Model");
// find a control with id=Model (you need to add this to your view)
tgt = $("#Variant");
// clear drop down
tgt.empty();
// Get new model dataset via ajax
// based on BrandName
// The url parameter points at your web method
$.ajax({
type: 'GET',
url: 'GetVariants',
dataType: 'json',
data: { modelName: src.val() },
// success is called when dataset returns
success: function (p) {
// Populate with each returned member
$.each(p, function (i, pr) {
tgt.append(
'<option value="' + pr.Value + '">' +
pr.Text + '</option>'
);
})
}
});
}
</script>
This works nicely and the cascading dropdowns do what they are expected to and the form posts to the correct Controller
VehicleController
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Details model)
{
return View(model);
}
But this is where I get stuck. How do I get the Vehicle Controller to pass the VehicleDetailsViewModel to the View attached to the VehicleController?
I know it has something to do with the fact that I am only using the Vehicle class in the HomeController but I have no idea how to create the implement the VehicleDetailsViewController so that ViewModel works on the HomeController view and on the VehicleController view.
I think the ViewModel must be something like this
public class VehicleDetailsViewModel
{
public IEnumerable<SelectListItem> Brands { get; set; }
public IEnumerable<SelectListItem> Models { get; set; }
public IEnumerable<SelectListItem> Variants { get; set; }
public string PowerOutput { get; set; }
public string NumberOfDoors { get; set; }
public string VariantName { get; set; }
public VehicleDetailsViewModel()
{
this.Brands = new List<SelectListItem>();
this.Models = new List<SelectListItem>();
this.Variants = new List<SelectListItem>();
}
}
Any help will be much appreciated :)