我正在使用最新版本的jQuery和ASP.NET MVC 3以及Razor视图引擎。
我已经尝试过Google在选择父下拉项时加载子下拉列表的一个不错的示例。我希望使用jQuery
通过AJAX
JSON
执行此操作。我对此的了解是零。
我有一个包含类别列表的Category类。这是一个亲子协会。
如果我从父下拉列表中选择一个类别,则所有子类别都需要列在所选父类别的子下拉列表中。
这是我目前所拥有的,但需要完成它,不确定我是否朝着正确的方向前进:
$(document).ready(function () {
$('#ddlParentCategories').change(function () {
alert('changed');
});
});
我从我的视图模型中加载了我的下拉列表:
@Html.DropDownListFor(x => x.ParentCategoryId, new SelectList(Model.ParentCategories, "Id", "Name", Model.ParentCategoryId), "-- Select --", new { id = "ddlParentCategories" })
第一项包含文本“ - 选择 - ”(父级和子级下拉列表)。在初始页面加载时,必须在子下拉列表中加载任何内容。选择值后,必须填充子下拉列表。当在父下拉列表中再次选择“ - 选择 - ”时,除了“ - 选择 - ”之外,必须清除子项下拉列表中的所有项目。
如果可能,如果正在加载子类别,如何显示“圆形”加载图标?
更新
我已将代码更新为Darin的代码,但我无法使其正常工作:
Category
上课:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string MetaKeywords { get; set; }
public string MetaDescription { get; set; }
public bool IsActive { get; set; }
public int? ParentCategoryId { get; set; }
public virtual Category ParentCategory { get; set; }
public virtual ICollection<Category> ChildCategories { get; set; }
}
EditProductViewModel
上课:
public class EditProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
public bool IsActive { get; set; }
public string PageTitle { get; set; }
public bool OverridePageTitle { get; set; }
public string MetaKeywords { get; set; }
public string MetaDescription { get; set; }
public int ParentCategoryId { get; set; }
public IEnumerable<Category> ParentCategories { get; set; }
public int ChildCategoryId { get; set; }
public IEnumerable<Category> ChildCategories { get; set; }
}
ProductController
上课:
public ActionResult Create()
{
EditProductViewModel viewModel = new EditProductViewModel
{
ParentCategories = categoryService.GetParentCategories()
.Where(x => x.IsActive)
.OrderBy(x => x.Name),
ChildCategories = Enumerable.Empty<Category>(),
IsActive = true
};
return View(viewModel);
}
public ActionResult AjaxBindingChildCategories(int parentCategoryId)
{
IEnumerable<Category> childCategoryList = categoryService.GetChildCategoriesByParentCategoryId(parentCategoryId);
return Json(childCategoryList, JsonRequestBehavior.AllowGet);
}
Create
查看:
<tr>
<td><label>Parent Category:</label> <span class="red">*</span></td>
<td>@Html.DropDownListFor(x => x.ParentCategoryId,
new SelectList(Model.ParentCategories, "Id", "Name", Model.ParentCategoryId),
"-- Select --",
new { data_url = Url.Action("AjaxBindingChildCategories"), id = "ParentCategories" }
)
@Html.ValidationMessageFor(x => x.ParentCategoryId)
</td>
</tr>
<tr>
<td><label>Child Category:</label> <span class="red">*</span></td>
<td>@Html.DropDownListFor(x => x.ChildCategoryId,
new SelectList(Model.ChildCategories, "Id", "Name", Model.ChildCategoryId),
"-- Select --",
new { id = "ChildCategories" }
)
@Html.ValidationMessageFor(x => x.ChildCategoryId)
</td>
</tr>
<script type="text/javascript">
$(document).ready(function () {
$('#ParentCategories').change(function () {
var url = $(this).data('url');
var data = { parentCategoryId: $(this).val() };
$.getJSON(url, data, function (childCategories) {
var childCategoriesDdl = $('#ChildCategories');
childCategoriesDdl.empty();
$.each(childCategories, function (index, childCategory) {
childCategoriesDdl.append($('<option/>', {
value: childCategory, text: childCategory
}));
});
});
});
});
</script>
它进入我的AjaxBindingChildCategories操作并且它带回记录,它只是不想显示我的子类别下拉列表。我查看了Fire Bug,我得到的错误是:
GET AjaxBindingChildCategories?parentCategoryId=1
500 Internal Server Error
答案 0 :(得分:3)
以下是级联下拉列表的示例。一如既往地定义视图模型:
public class MyViewModel
{
[DisplayName("Country")]
[Required]
public string CountryCode { get; set; }
public IEnumerable<SelectListItem> Countries { get; set; }
public string City { get; set; }
public IEnumerable<SelectListItem> Cities { get; set; }
}
然后是控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
// TODO: Fetch countries from somewhere
Countries = new[]
{
new SelectListItem { Value = "FR", Text = "France" },
new SelectListItem { Value = "US", Text = "USA" },
},
// initially we set the cities ddl to empty
Cities = Enumerable.Empty<SelectListItem>()
};
return View(model);
}
public ActionResult Cities(string countryCode)
{
// TODO: based on the selected country return the cities:
var cities = new[]
{
"Paris", "Marseille", "Lyon"
};
return Json(cities, JsonRequestBehavior.AllowGet);
}
}
观点:
@model MyViewModel
@using (Html.BeginForm())
{
<div>
@Html.LabelFor(x => x.CountryCode)
@Html.DropDownListFor(
x => x.CountryCode,
Model.Countries,
"-- Select country --",
new { data_url = Url.Action("cities") }
)
@Html.ValidationMessageFor(x => x.CountryCode)
</div>
<div>
@Html.LabelFor(x => x.City)
@Html.DropDownListFor(
x => x.City,
Model.Cities,
"-- Select city --"
)
@Html.ValidationMessageFor(x => x.City)
</div>
<p><input type="submit" value="OK" /></p>
}
最后是一个不显眼的javascript在一个单独的文件中:
$(function () {
$('#CountryCode').change(function () {
var url = $(this).data('url');
var data = { countryCode: $(this).val() };
$.getJSON(url, data, function (cities) {
var citiesDdl = $('#City');
citiesDdl.empty();
$.each(cities, function (index, city) {
citiesDdl.append($('<option/>', {
value: city,
text: city
}));
});
});
});
});
答案 1 :(得分:1)
jQuery脚本将如下所示:
<script type="text/javascript">
function getCities(abbr) {
$.ajax({
url: "@Url.Action("Cities", "Locations")",
data: {abbreviation: abbr},
dataType: "json",
type: "POST",
error: function() {
alert("An error occurred.");
},
success: function(data) {
var items = "";
$.each(data, function(i, item) {
items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
});
$("#City").html(items);
}
});
}
$(document).ready(function(){
$("#State").change(function() {
var abbr = $("#State").val();
getCities(abbr);
});
});
</script>
检索数据的存储库可能看起来像这样(显然可以将其连接到实时数据):
public class LocationRepository : ILocationRepository
{
public IQueryable<State> GetStates()
{
return new List<State>
{
new State { Abbreviation = "NE", Name = "Nebraska" },
new State { Abbreviation = "NC", Name = "North Carolina" }
}.AsQueryable();
}
public IQueryable<City> GetCities(string abbreviation)
{
var cities = new List<City>();
if (abbreviation == "NE")
{
cities.AddRange(new List<City> {
new City { Id = 1, Name = "Omaha" },
new City { Id = 2, Name = "Lincoln" }
});
}
else if (abbreviation == "NC")
{
cities.AddRange(new List<City> {
new City { Id = 3, Name = "Charlotte" },
new City { Id = 4, Name = "Raleigh" }
});
}
return cities.AsQueryable();
}
}
public interface ILocationRepository
{
IQueryable<State> GetStates();
IQueryable<City> GetCities(string abbreviation);
}
控制器可能如下所示:
public class LocationsController : Controller
{
private ILocationRepository locationRepository = new LocationRepository();
[HttpPost]
public ActionResult States()
{
var states = locationRepository.GetStates();
return Json(new SelectList(state, "Id", "Name"));
}
[HttpPost]
public ActionResult Cities(string abbreviation)
{
var cities = locationRepository.GetCities(abbreviation);
return Json(new SelectList(cities, "Abbreviation", "Name"));
}
}
答案 2 :(得分:1)
我假设您从服务器端填充父下拉列表,此父dd中的第一个选项是"--- Select ---"
你可以试试这个
$(document).ready(function () {
var $parent = $('#ddlParentCategories');
var $child = $('#ddlChildCategories');
$child.find("option:gt(0)").remove();
if(!$parent.children().eq(0).is(":selected")){
$parent.change(function () {
$.ajax({
url: "urlToFetchTheChild",
data: { categoryId: this.value },
success: function(data){
//The data you send should be a well formed array of json object containing code/value pair of child categories
for(var i = 0;i<data.length;i++){
$child.append("<option value='"+ data[i].code +"'>"+ data[i].value +"</option>");
}
}
});
});
}
});