Reputation: 1501
I am trying to select a manufacturer from a list and then based on what manufacturer the user selects, populate a list of models.
View:
<div class="form-group">
@Html.LabelFor(model => model.Manufacturer.ManufacturerName, "Model",
htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-5">
@Html.DropDownList("ManufacturerID", (List<SelectListItem>)ViewBag.Manufacturers,
htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Manufacturer.ManufacturerName, "",
new { @class = "text-danger", onchange = "PopulateModels()" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Model.ModelName, "Model",
htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-5">
@Html.DropDownList("ModelID", (List<SelectListItem>)ViewBag.Models,
htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Model.ModelName, "",
new { @class = "text-danger" })
</div>
</div>
<script>
function PopulateModels()
{
var url = '@Html.Raw(Url.Action("GetModelList", "FaultController", new { manufacturer="ManufacturerID" }))';
window.location = url;
}
</script>
Controller:
public List<SelectListItem> GetModelList(Manufacturer manufacturer)
{
List<SelectListItem> modelList = new List<SelectListItem>();
var models = db.Models.Where(m => m.ManufacturerID == manufacturer.ManufacturerID);
foreach (Model model in models)
{
modelList.Add(new SelectListItem
{
Text = model.ModelName,
Value = model.ModelID.ToString()
});
}
var sortedModelList = (from model in modelList
orderby model.Text
select model).ToList();
return sortedModelList;
}
public ActionResult Create(...)
{
.
.
.
ViewBag.Models = new List<SelectListItem>();
ViewBag.Manufacturers = GetManufacturerList();
}
As you can see, the ViewBag for Models is initially empty, when a manufacturer is selected I want this ViewBag to be updated with all of the models that hold that manufacturer.
I feel like I'm close but cannot figure out what to next, a point in the right direction would be great. I'm also not sure if what I have done so far is completely correct, so if anyone can spot anything I've overlooked or any suggestions on how to improve my code would also be appreciated.
I hope this makes sense, any help is appreciated, thanks in advance.
Updated Code:
View:
<div class="form-group">
@Html.LabelFor(model => model.Manufacturer.ManufacturerName, "Model",
htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-5">
@Html.DropDownList("ManufacturerID", (List<SelectListItem>)ViewBag.Manufacturers,
htmlAttributes: new { @class = "form-control" , @id= "Manufacturers" })
@Html.ValidationMessageFor(model => model.Manufacturer.ManufacturerName, "",
new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Model.ModelName, "Model",
htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-5">
@Html.DropDownList("ModelID", (List<SelectListItem>)ViewBag.Models,
htmlAttributes: new { @class = "form-control" , @id = "Models"})
@Html.ValidationMessageFor(model => model.Model.ModelName, "",
new { @class = "text-danger" })
</div>
</div>
<script type="text/javascript">
$(function(){
$("#Manufacturers").change(function(){
var v= $(this).val();
$("#Models").empty();
$.getJSON("@Url.Action("GetModels","Fault")?id="+v,function(data){
$.each(data,function(a,b){
$("#Models").append('<option value="'+b.Value+'">'+b.Text+'</option>');
});
});
});
});
</script>
Controller:
public ActionResult GetModels(int id)
{
var models = db.Models.Where(m => m.ManufacturerID == id)
.Select(x => new SelectListItem
{
Value = x.ModelID.ToString(),
Text = x.ModelName
}).ToList();
return Json(models, JsonRequestBehavior.AllowGet);
}
Upvotes: 1
Views: 2221
Reputation: 218702
Your current code is making the browser to navigate to the other action method. But what you ideally need is to get this data using ajax and use that to build the SELECT options for the second dropdown.
So setup a change event handler for the first dropdiwn.
$(function(){
$("#ManufacturerID").change(function(){
var v= $(this).val();
$("#Models").empty();
$.getJSON("@Url.Action("GetModels","YourControlleName")?id="+v,function(data){
$.each(data,function(a,b){
$("#Models").append('<option value="'+b.Value+'">'+b.Text+'</option>');
});
});
});
});
Now you have a GetModels
action method which accepts the manufacturer id in Id parameter and return the corresponding model.
public ActionResult GetModels(int id)
{
var models = db.Models.Where(m => m.ManufacturerID == id)
.Select(x=>new SelectListItem { Value=x.Id.ToString(),
Text=x.Name}).ToList();
return Json(models,JsonRequestBehavior.AllowGet);
}
Here is a working dotnetfiddle with dummy data for your reference.
Upvotes: 2