Devoneous
Devoneous

Reputation: 15

Getting drop down city list to show after state is selected ASP MVC5

I feel like I have a working idea but I am getting a "Object reference not set to an instance of an object" error when I build the application. I am simply trying to display a drop down list for cities after the selection for state is made. I have a list of states in a seperate class that I am using for a drop down list in a form. What I am attempting to do is grab the selected state and pass it as a perameter into a different class in order to select the correct list of cities to be displayed as another drop down. So if someone selects washington state then cities such as Seattle and Tacoma show up and not cities from a different state. Here is the razor for the drop downs (the state works fine):

<div class="form-group">
            @Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.State, WebGridProject.Models.StateCodes.GetStatesList(), new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.City, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.City, WebGridProject.Models.CityNames.GetStateCities(Model.State), new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.City, "", new { @class = "text-danger" })
            </div>
        </div>

And here is the class for cities:

   public class CityNames
    {
        public static IEnumerable<SelectListItem> GetStateCities(string stateName)
        {

            IList<SelectListItem> cities = new List<SelectListItem>();

            switch (stateName)
            {
                case "AK":
                    cities = new List<SelectListItem>
                    {
                        new SelectListItem() {Text = "", Value = ""},
                        new SelectListItem() {Text = "Anchorage", Value = "Anchorage"},
                        new SelectListItem() {Text = "Fairbanks", Value = "Fairbanks"},
                    };
                    break;
                case "AL":
                    cities = new List<SelectListItem>
                    {
                        new SelectListItem() {Text = "", Value = ""},
                        new SelectListItem() {Text = "Auburn", Value = "Auburn"},
                        new SelectListItem() {Text = "Birmingham", Value = "Birmingham"},
                        new SelectListItem() {Text = "Dothan", Value = "Dothan"},
                        new SelectListItem() {Text = "Mobile", Value = "Mobile"},
                    };
                    break;
                case "AZ":
                    cities = new List<SelectListItem>
                    {
                        new SelectListItem() {Text = "", Value = ""},
                        new SelectListItem() {Text = "Pheonix", Value = "Pheonix"},
                        new SelectListItem() {Text = "Flagstaff", Value = "Flagstaff"},
                        new SelectListItem() {Text = "Prescott", Value = "Prescott"},
                        new SelectListItem() {Text = "Tucson", Value = "Tucson"},
                    };
                    break;
                case "AR":
                    cities = new List<SelectListItem>
                    {
                        new SelectListItem() {Text = "", Value = ""},
                        new SelectListItem() {Text = "Fayetteville", Value = "Fayetteville"},
                        new SelectListItem() {Text = "Fort smith", Value = "Fort smith"},
                        new SelectListItem() {Text = "Jonesboro", Value = "Jonesboro"},
                        new SelectListItem() {Text = "Texarkana", Value = "Texarkana"},
                    };
                    break;
                default:
                    cities = new List<SelectListItem>
                    {
                        new SelectListItem() {Text = "", Value = ""},
                        new SelectListItem() {Text = "Please Select State", Value = "Please Select State"},
                    };
                    break;
            }
            return cities;
        }
    }

to me the error seemed to be pointing to there being no default value and having an issue with loading a null value. But I have a default case in the switch statement to cover this issue. I am pretty new to MVC and I will continue to work on this on my own. But if anyone has any ideas I am all ears because I am struggling to figure this out. Just FYI, the states class is also an IList<> that returns the list of state names.

request for action to be posted:

public ActionResult MyHomePage()
        {
            return View();
        }
        //Post method
        [HttpPost]
        public ActionResult MyHomePage(WebGridTable TWG)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    UserManager UM = new UserManager();
                    UM.addNewUser(TWG);
                    ModelState.Clear();
                    return View();
                }
                return View();
            }
            catch (Exception e)
            {
                return View("Error");
            }
        }

action doesnt really mean anything without the method I wrote for managing the form:

public void addNewUser(WebGridTable AddNew)
        {
            using (WebGridDBEntities4 db = new WebGridDBEntities4())
            {
                WebGridTable TWG = new WebGridTable();
                TWG.Name = AddNew.Name;
                TWG.DOB = AddNew.DOB;
                TWG.AddressLine1 = AddNew.AddressLine1;

                // TO DO: Figure out issue with accepting null value into database.
                if (AddNew.AddressLine2 != null)
                {
                    TWG.AddressLine2 = AddNew.AddressLine2;
                }
                else if (AddNew.AddressLine2 == null)
                {
                    TWG.AddressLine2 = 0;
                }

                TWG.State = AddNew.State;
                TWG.City = TWG.City;
                TWG.Zip = AddNew.Zip;
                TWG.Gender = AddNew.Gender;

                db.WebGridTables.Add(TWG);
                db.SaveChanges();
            }
        }

Upvotes: 0

Views: 2600

Answers (1)

MRebati
MRebati

Reputation: 599

You need to use JQuery actions on Changes of the States DropDownList. Send the value to a specific Action in your Controller and Call your States.GetStatesName('Value') in that. Check the Code below. I think it would help.

$("#State").on('change',function () {
    var loadingoption = $('<option></option>').text("Pleas Wait");
    $('#city').attr("disabled","disabled").empty().append(loadingoption);

    jQuery.getJSON("/Home/CityJson/" + $("#State > option:selected").attr("value"), function (data) {
        var defaultoption = $('<option value="">Please choose a City</option>');
        $('#city').removeAttr("disabled").empty().append(defaultoption);
        jQuery.each(data, function (i) {
            var option2 = $('<option></option>').attr("value", data[i].Name).text(data[i].Name);
            $("#city").append(option2);
        });
    });
});

I used ActionResult "CityJson" in my HomeController. So choose your Action in getJSON.

Here is the Controller:

public ActionResult CityJson(string id)
    {
        var state = db.States.FirstOrDefault(x => x.Name == id);
        var model = db.Cities.Where(x => x.StateId == state.Id).Select(x => new { x.Name }).ToList();
        return Json(model, JsonRequestBehavior.AllowGet);
    }

you can call your actions inside the Class and send them using Json.

Good Luck.

Upvotes: 1

Related Questions