Trying to populate a sub-list on changing the main

2019-09-20 19:22发布

问题:

I am not sure if this jquery script is correct. The Sublist populates on changing main list using where clause on whatever value is selected in main list. Do i need action method? What is the best solution?

 <script type="text/javascript">
$("#FKCountyId").change(function () {
    $.ajax({
        url: "@Url.Action("", "")",
        dataType: 'json',
        type: 'POST',
        data: { txt: $("#FKCountyId").val() },
        success: function (data) {
            $('#FKCityId').empty();
            // need help here
        },
        error: function (jqXHR, textStatus, errorThrown) {
            alert(errorThrown);
        }
    });
});

View

@Html.LabelFor(m => m.FKCountyId, new { @class = "col-sm-2 col-sm-2 control-label" })
@Html.DropDownListFor(m => m.FKCountyId, Model.GetCounty())
@Html.LabelFor(m => m.FKCityId, new { @class = "col-sm-2 col-sm-2 control-label" })
@Html.DropDownListFor(m => m.FKCityId, Model.GetCity())

Model

     public class NewsModel : BaseModel
     {
      [Required]
      public int? FKCountyId { get; set; }
      public string County { get; set; }
      [Required]
      public int? FKCityId { get; set; }
      public string City { get; set; }


    public List<SelectListItem> GetCounty()
    {
        List<SelectListItem> lst = new List<SelectListItem>();
        lst.Add(new SelectListItem() { Text = "Please select County", Value = "" });
        foreach (var item in LambertonContext.NewsCounties)
        {
            lst.Add(new SelectListItem() { Text = item.County, Value = item.PKCountyId.ToString() });
        }
        return lst;
    }

    public List<SelectListItem> GetCity()
    {
        List<SelectListItem> lst = new List<SelectListItem>();
        lst.Add(new SelectListItem() { Text = "Please select City", Value = "" });
        foreach (var item in LambertonContext.NewsCities)
        {
            lst.Add(new SelectListItem() { Text = item.City, Value = item.PKCityId.ToString() });
        }
        return lst;
        }
}

回答1:

Your View and Model are not correct, One way to achieve your goal is to create a ViewModel that will handle both of your lists , this way you can leave your base models abstract.

Here's how i would rearrange your code.


Model

using System;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using System.Web.Mvc;

namespace Alundra.Models
{
    public class CountyCityViewModel
    {
        public List<CountyModel> Countymodel { get; set; }
        public SelectList SelectedCity { get; set; }
    }

    public class CountyModel
    {
        public int ID { get; set; }
        public string CountyName { get; set; }
    }
    public class CityModel
    {
        public int ID { get; set; }
         public string CityName { get; set; }
        //Foreign key for the County model
        public int CountyID { get; set; }
        public virtual CountyModel County { get; set; }

    }
}   

Controller

using System;
using System.Web.Mvc;
using System.Collections.Generic;
using Alundra.Models;
using System.Linq;

namespace HelloWorldMvcApp
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            CountyCityViewModel CountyCityviewmodel = new CountyCityViewModel();
            CountyCityviewmodel.Countymodel = new List<CountyModel>();
            CountyCityviewmodel.Countymodel = GetAllCounties();
            return View(CountyCityviewmodel);
        }


        //This is the action you will call using AJAX from your view
        [HttpPost]
        public ActionResult GetCityByCountyID(int CountyID)
        {
            List<CityModel> ListOfCities = new List<CityModel>();
            ListOfCities = GetAllCities().Where(s => s.CountyID == CountyID).ToList();
            SelectList SelectListOfCities = new SelectList(ListOfCities, "ID", "CityName", 0);
            return Json(SelectListOfCities);
        }
        // Populate counties collection Or you can extract from DB
        public List<CountyModel> GetAllCounties()
        {
            List<CountyModel> Countymodel = new List<CountyModel>();
            Countymodel.Add(new CountyModel { ID = 0, CountyName = "Select a county" });
            Countymodel.Add(new CountyModel { ID = 1, CountyName = "Freedom county" });
            Countymodel.Add(new CountyModel { ID = 2, CountyName= "Not so good county" });
            Countymodel.Add(new CountyModel { ID = 3, CountyName = "Best county" });
            Countymodel.Add(new CountyModel { ID = 4, CountyName = "Crazy county" });
            Countymodel.Add(new CountyModel { ID = 5, CountyName = "Happy county" });
            return Countymodel;
        }
        //Populate cities collection Or you can extract from DB
        public List<CityModel> GetAllCities()
        {
            List<CityModel> CityModel = new List<CityModel>();
            CityModel.Add(new CityModel { ID = 1, CountyID = 3, CityName = "City1-1" });
            CityModel.Add(new CityModel { ID = 2, CountyID = 3, CityName = "City2-1" });
            CityModel.Add(new CityModel { ID = 3, CountyID = 2, CityName = "City4-1" });
            CityModel.Add(new CityModel { ID = 4, CountyID = 2, CityName = "City1-2" });
            CityModel.Add(new CityModel { ID = 5, CountyID = 1, CityName = "City1-3" });
            CityModel.Add(new CityModel { ID = 6, CountyID = 5, CityName = "City4-2" });
            CityModel.Add(new CityModel { ID = 7, CountyID = 5, CityName = "City4-2" });
            CityModel.Add(new CityModel { ID = 8, CountyID= 1, CityName = "City4-2" });
            CityModel.Add(new CityModel { ID = 9, CountyID = 2, CityName = "City4-2" });
            CityModel.Add(new CityModel { ID = 10, CountyID = 4, CityName = "City4-2" });
            return CityModel;
        }
    }
}

and finally your view

@model Alundra.Models.CountyCityViewModel
@{

}
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

<script>
    function GetCitieslist(Countyid) {
    var procemessage = "<option value='0'> Please wait...</option>";
        $("#ddlcity").html(procemessage).show();

    var url = '@Url.Action("GetCityByCountyID")';



        $.ajax({
            url: url,
            data: { CountyID: Countyid },
            cache: false,
            type: "POST",
            success: function (data) {
                var markup = "<option value='0'>Select City</option>";
                for (var i = 0; i < data.length; i++) {
                    markup += "<option value=" + data[i].Value + ">" + data[i].Text + "</option>";
                }
                $("#CitiesDropDown").html(markup).show();
            },
            error: function (reponse) {
                alert("error : " + reponse);
            }
        });

    }
</script>


    <h4><i class="fa fa-connectdevelop fa-3x pull-left fa-border"></i><span class="label label-warning">Cascade Dropdown menues using JQuery</span></h4>

@using (Html.BeginForm())
{
    @Html.DropDownListFor(m => m.Countymodel, new SelectList(Model.Countymodel, "ID", "CountyName"), new { @id = "StateDropDown", @onchange = "javascript:GetCitieslist(this.value);" })
    <br />
    <br />
    <select id="CitiesDropDown" name="ddlcity" style="width: 200px">

    </select>


  }


    <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>

EXTRA: You can implement a loading image while the cities DD is getting the data.

Here's a .net fiddle link to a working example