CaptnA
CaptnA

Reputation: 115

Drop Down List Giving Incorrect Values

I have followed the following tutorial for my project:

https://www.youtube.com/watch?v=h_ViuyVs4AE

The issue that I have is that when I click an item in the first drop down box, it does not give the correct values in the second box, it only gives one value and it is incorrect. It should display all the Model_Name's(Vehicle_Model table) that are for each Make_Name(Vehicle_Make table).

Index.cshtml code:

@model GoogleMap.Models.MyPageViewModel

<script>
    $(function () {
        $("#ContID").change(function () {
            $.get("/Map/GetModById", { MID: $("#ContID").val() }, function (data) {
                var $list = $("#St");
                $list.empty();
                $.each(data, function() {
                    $("<option />")
                        .val(this.Model_ID)
                        .text(this.Model_Name)
                        .appendTo($list);
                });
            })
        });
    });
</script>

@Html.DropDownListFor(p => p.SelectedMake_Id, ViewBag.Vehicle_Make as SelectList, "Select Vehicle Make", new { id = "ContID" })

MapController.cs code:

public class MapController : Controller
{
    private GoogleMapEntities db = new GoogleMapEntities();
    //Get the select ID???
    int SelectedMake_Id = 0;

    // GET: Map
    public ActionResult Index()
    {    
        GoogleMapEntities GE = new GoogleMapEntities();
        List<Vehicle_Details> vehList = db.Vehicle_Details.ToList();

        GoogleMapViewModel GMviewmodel = new GoogleMapViewModel();
        List<GoogleMapViewModel> GMviewmodelList = new List<GoogleMapViewModel>();

        //Populate the ViewModel
        MyPageViewModel vm = new Models.MyPageViewModel();
        vm.GoogleMapViewModelList = GMviewmodelList;
        vm.SelectedMake_Id = SelectedMake_Id;

        ViewBag.Vehicle_Make = new SelectList(db.Vehicle_Make, "Make_ID", "Make_Name");

        return View(vm);               
    }

    public JsonResult GetModById(int MID)
    {
        db.Configuration.ProxyCreationEnabled = false;
        return Json(db.Vehicle_Model.Where(p => p.Model_ID == MID), JsonRequestBehavior.AllowGet);
    }

    [HttpPost]
    public ActionResult Search(string Location)
    {
        GoogleMapEntities GE = new GoogleMapEntities();
        ////SELECT Make_Name DATA FROM DB1
        // var result = GE.Vehicle_Model.Where(x => x.Model_Name.StartsWith(Location)).ToList();
        var GetVeh = db.GetMapSearch().Where(x => x.Model_Name.StartsWith(Location)).ToList();

        return Json(GetVeh, JsonRequestBehavior.AllowGet);
    }
}

Vehicle_Make has Make_ID (pk) and Make_Name.

Vehicle_Model has Model_ID (pk) and Model_Name.

Vehicle_Details has Vehicle_ID (pk), Model_ID (fk), Make_ID (fk).

So what needs to happen is when I click a vehicle name(Make_Name), it must display all of it's Model_Name's in the second drop down list.

EDIT: I have made a proc called DropDL which has the query that will display the Model name's with their Model_ID's and Make_ID's.

Query in proc:

SELECT          Vehicle_Model.Model_Name, Vehicle_Details.Model_ID, 
                Vehicle_Details.Make_ID
FROM            Vehicle_Make INNER JOIN
                Vehicle_Details ON Vehicle_Make.Make_ID = 
                Vehicle_Details.Make_ID INNER JOIN
                Vehicle_Model ON Vehicle_Details.Model_ID =  
                Vehicle_Model.Model_ID

The procedure that I have made(GetMapSearch) which linked 4 tables tables for something else, where it linked all of those tables using ID's and getting specific values from each table, worked well, so I do not understand why I'd need to add Make_ID to the Vehicle_Model table unless the drop down list does require that.

Updated code:

    public JsonResult GetModById(int MID)
    {
        db.Configuration.ProxyCreationEnabled = false;
        return Json(db.DropDL().Where(p => p.Model_ID == MID)
        .Select(p => new SelectListItem { Text = p.Model_Name, Value = 
        p.Model_ID.ToString() }).ToList(),
        JsonRequestBehavior.AllowGet);
    }

And Index.cshtml code:

@model GoogleMap.Models.MyPageViewModel

@using Mvc.CascadeDropDown

@Html.DropDownListFor(p => p.SelectedMake_Id, ViewBag.Vehicle_Make as         
SelectList, "Select Vehicle Make", new { id = "ContID" })

@Html.CascadingDropDownListFor(
expression: m => m.SelectedModelId,
triggeredByPropertyWithId: "ContID",  //Parent property that trigers 
dropdown data loading
url: Url.Action("GetModById", "Map"),  //Url of action that returns dropdown 
data
ajaxActionParamName: "MID", //Parameter name for the selected parent value 
that url action receives
optionLabel: "Please select a Model", // Option label
disabledWhenParentNotSelected: true, //If true, disables dropdown until 
parent dropdown is selected
htmlAttributes: new { @class = "form-control" })

Also, if I changed the ViewBag to use db.DropDL() instead of db.Vehicle_Make, it gets all of the makes but it brings all of the makes up multiple times.

After making the proc, I am still getting one or two Model_Name's for the Make_Name's and also some makes do not give model names. So it is linking the tables, but not correctly.

FIXED!

Okay I have fixed it, but does anyone know how to get it to display the Make_Name in alphabetical order and then Model_Name also in alphabetical order once a make name is clicked? Also, remove duplicate model_name's and show one of each instead ?

Also, how do I get the value from Model_Name, once clicked on, to work with my search:

Right now I have to search by typing, how do I get the clicked value's string (Model_Name) to be searched?

   [HttpPost]
    public ActionResult Search(string Location)
    {
        GoogleMapEntities GE = new GoogleMapEntities();

        var GetVeh = db.GetMapSearch().Where(x => 
        x.Model_Name.StartsWith(Location)).ToList();

        return Json(GetVeh, JsonRequestBehavior.AllowGet);

    }

Upvotes: 1

Views: 269

Answers (2)

Vegeta ZA
Vegeta ZA

Reputation: 70

Try changing p.Model_ID to p.Make_ID

public JsonResult GetModById(int MID)
{
    db.Configuration.ProxyCreationEnabled = false;
    return Json(db.DropDL().Where(p => p.Make_ID == MID)
    .Select(p => new SelectListItem { Text = p.Model_Name, Value = 
    p.Model_ID.ToString() }).ToList(),
    JsonRequestBehavior.AllowGet);
}

Upvotes: 0

Alex Art.
Alex Art.

Reputation: 8781

You can use a CascadeDropDownHelpers library to simplify you case a little bit ( disclaimer: I am the author ) :

1) install the nuget package.

2) add to your model SelectedModelId property:

public class MyPageViewModel{

    public string SelectedModelId {get;set;}

    // other properties...
} 

3) modify GetModById action to return a list of SelectListItems as json

public JsonResult GetModById(int MID)
{
    db.Configuration.ProxyCreationEnabled = false;
    return Json(db.Vehicle_Model.Where(p => p.Model_ID == MID)
          .Select(p=>  new SelectListItem {Text = p.Model_Name, Value = p.Model_ID.ToString()}).ToList(), 
    JsonRequestBehavior.AllowGet);
}

4) modify the view (no script additional scrips required):

@model GoogleMap.Models.MyPageViewModel

@Html.DropDownListFor(p => p.SelectedMake_Id, ViewBag.Vehicle_Make as SelectList, "Select Vehicle Make", new { id = "ContID" })

@Html.CascadingDropDownListFor( 
  expression: m => m.SelectedModelId, 
  triggeredByPropertyWithId: "ContID",  //Parent property that trigers dropdown data loading
  url: Url.Action("GetModById", "Map"),  //Url of action that returns dropdown data
  ajaxActionParamName: "MID", //Parameter name for the selected parent value that url action receives
  optionLabel: "Please select a Model", // Option label
  disabledWhenParentNotSelected: true, //If true, disables dropdown until parent dropdown is selected
  htmlAttributes: new { @class = "form-control" })

You can find additional usage examples here

Upvotes: 1

Related Questions