下拉联动(级联)
程序员文章站
2023-08-13 18:04:15
前言 平时工作中下拉联动是相对比较麻烦的地方,虽然逻辑简单,但是需要写一堆js跟ajax请求。现在打算在.net core mvc下封装一个下拉联动组件方便使用。 下面将实现一个 国家 语言 省市区 的多级联动 创建实体模型 写出对应下拉的Action方法 这里 下拉contorler名称约定为Dr ......
前言
平时工作中下拉联动是相对比较麻烦的地方,虽然逻辑简单,但是需要写一堆js跟ajax请求。现在打算在.net core mvc下封装一个下拉联动组件方便使用。
下面将实现一个 国家 语言 省市区 的多级联动
创建实体模型
1 public class UserModel 2 { 3 /// <summary> 4 /// 用户名 5 /// </summary> 6 public string UserName { get; set; } 7 8 9 /// <summary> 10 /// 国家 11 /// </summary> 12 public int CountryId { get; set; } 13 14 /// <summary> 15 /// 语言 16 /// </summary> 17 public int LanguageId { get; set; } 18 19 /// <summary> 20 ///省 21 /// </summary> 22 public int PronviceId { get; set; } 23 24 /// <summary> 25 /// 市 26 /// </summary> 27 public int CityId { get; set; } 28 29 /// <summary> 30 /// 区 31 /// </summary> 32 public int GetDistrictId { get; set; } 33 34 } 35 36 public class Area 37 { 38 public int Id { get; set; } 39 40 public string Name { get; set; } 41 42 public int? ParentId { get; set; } 43 } 44 45 public class Language 46 { 47 public int Id { get; set; } 48 49 public int CountryId { get; set; } 50 51 public string Name { get; set; } 52 }
写出对应下拉的Action方法
这里 下拉contorler名称约定为DropdownListController,Action名称约定为 Get +字段名的方式,参数名称约定使用 父级字段的名称。这样在前台页面就不用指定获取数据源的url了
1 public class DropdownListController : Controller 2 { 3 private List<Area> areas; 4 5 private List<Language> languages; 6 7 public DropdownListController() 8 { 9 areas = new List<Area> 10 { 11 new Area { Id = 1, Name = "中国", ParentId = null }, 12 new Area { Id = 2, Name = "美国", ParentId = null }, 13 new Area { Id = 3, Name = "江苏省", ParentId = 1 }, 14 new Area { Id = 4, Name = "浙江省", ParentId = 1 }, 15 new Area { Id = 5, Name = "纽约州", ParentId = 2 }, 16 new Area { Id = 6, Name = "南京市", ParentId = 3 }, 17 new Area { Id = 7, Name = "杭州市", ParentId = 4 }, 18 new Area { Id = 8, Name = "纽约市", ParentId = 5 }, 19 new Area { Id = 9, Name = "曼哈顿区", ParentId = 8 }, 20 new Area { Id = 10, Name = "老庙区", ParentId = 6 }, 21 new Area { Id = 11, Name = "西湖区", ParentId = 7 } 22 }; 23 24 languages = new List<Language> 25 { 26 new Language{ Id=1,CountryId=1, Name="简体中文" }, 27 new Language{ Id=2,CountryId=2, Name="美式英语"}, 28 }; 29 } 30 31 public IActionResult GetCountryId() 32 { 33 return Json(areas.FindAll(x => x.ParentId == null).Select(x => new { value = x.Id, text = x.Name })); 34 } 35 36 public IActionResult GetLanguageId(int countryId) 37 { 38 return Json(languages.FindAll(x => x.CountryId == countryId).Select(x => new { value = x.Id, text = x.Name })); 39 } 40 41 public IActionResult GetPronviceId(int countryId) 42 { 43 return Json(areas.FindAll(x => x.ParentId == countryId).Select(x => new { value = x.Id, text = x.Name })); 44 } 45 46 public IActionResult GetCityId(int pronviceId) 47 { 48 return Json(areas.FindAll(x => x.ParentId == pronviceId).Select(x => new { value = x.Id, text = x.Name })); 49 } 50 51 public IActionResult GetDistrictId(int cityId) 52 { 53 return Json(areas.FindAll(x => x.ParentId == cityId).Select(x => new { value = x.Id, text = x.Name })); 54 } 55 }
前台Html
引用了 bootstrap, jquery
@model UserModel <a asp-action="Edit" class="btn btn-success m-b-15">去编辑页</a> <div class="form-inline row"> <div class="form-group "> <label>国家</label> <select asp-for="CountryId" class="form-control" asp-items="ViewBag.CountryList" data-select-childids="LanguageId,PronviceId"> <option value="">请选择</option> </select> </div> <div class="form-group "> <label>语言</label> <select asp-for="LanguageId" class="form-control"> <option value="">请选择</option> </select> </div> <div class="form-group"> <label>省</label> <select asp-for="PronviceId" class="form-control" data-select-childids="CityId"> <option value="">请选择</option> </select> </div> <div class="form-group"> <label>市</label> <select asp-for="CityId" class="form-control" data-select-childids="DistrictId"> <option value="">请选择</option> </select> </div> <div class="form-group"> <label>区</label> <select asp-for="DistrictId" class="form-control"> <option value="">请选择</option> </select> </div> </div>
下拉联动的js,基于 jquery
$(function () { //下拉联动初始化 $('select[data-select-childids]').each(function () { getChildSelect($(this).attr("id"), true); }); //下拉联动 data-select-childids 填写联动的Id,data-select-url 数据请求路径,data-select-paramids 追加的参数,data-select-value 当前值 $('select[data-select-childids]').change(function (e) { getChildSelect($(this).attr("id")); }); //清空下拉联动子选择项 function getChildSelect(selectid, isInit) { var select = $('#' + selectid); var selectchildIds = select.data('select-childids'); if (!selectchildIds) return; var childIds = selectchildIds.split(',') for (var i = 0; i < childIds.length; i++) { if (!childIds[i]) continue; var child = $('#' + childIds[i]); var childValue = child.val(); if (!childValue) childValue = child.data("select-value"); child.empty(); //默认值设定 var hasdefault = child.data("select-hasdefault"); if (hasdefault != "false") { child.append('<option value="">请选择</option>'); } //父级下拉有值时,ajax获取数据 if (select.val()) {var url = child.data('select-url') ? child.data('select-url') : '/DropdownList/Get' + child.attr("id");//url默认值 var verb = child.data('verb') ? child.data('verb') : 'GET';//请求的方法 var paramObj = {};//追加参数 getParentSelectParam(selectid, paramObj) //追加控制参数 var paramids = child.data('select-paramids'); if (paramids) { var paramidsArr = paramids.split(',') for (var k = 0; k < paramidsArr.length; k++) { paramObj[paramidsArr[k]] = $('#' + paramidsArr[k]).val(); } } $.ajax({ type: verb, url: url, data: paramObj, async: false, contentype: "application/x-www-form-urlencoded; charset=UTF-8", success: function (data) { if (data) { for (var j = 0; j < data.length; j++) { var selected = data[j].value == childValue ? 'selected = "selected"' : ''; child.append('<option value="' + data[j].value + '" ' + selected + '>' + data[j].text + '</option>'); } } } }); } //子级下拉如果还有下级,非初始化的时候 递归 if (!isInit && child.data('select-childids')) getChildSelect(child.attr("id")); } } //递归获取父级选中的值 param追加的url参数 function getParentSelectParam(selectid, param) { var select = $("#" + selectid); param[selectid] = $(select).val(); $('select[data-select-childids]').each(function () { var id = $(this).attr("id"); if (selectid != id) { var childids = $(this).data('select-childids'); if (childids) { childidsArr = childids.split(','); for (var i = 0; i < childidsArr.length; i++) { if (childidsArr[i] == selectid) { getParentSelectParam(id, param);//继续向父级查找 } } } } }); } });
后台 action
public class HomeController : Controller { private List<Area> areas; public HomeController() { areas = new List<Area> { new Area { Id = 1, Name = "中国", ParentId = null }, new Area { Id = 2, Name = "美国", ParentId = null }, new Area { Id = 3, Name = "江苏省", ParentId = 1 }, new Area { Id = 4, Name = "浙江省", ParentId = 1 }, new Area { Id = 5, Name = "纽约州", ParentId = 2 }, new Area { Id = 6, Name = "南京市", ParentId = 3 }, new Area { Id = 7, Name = "杭州市", ParentId = 4 }, new Area { Id = 8, Name = "纽约市", ParentId = 5 }, new Area { Id = 9, Name = "曼哈顿区", ParentId = 8 }, new Area { Id = 10, Name = "老庙区", ParentId = 6 }, new Area { Id = 11, Name = "西湖区", ParentId = 7 } }; } public IActionResult Index() { ViewBag.CountryList = areas.FindAll(x => x.ParentId == null).Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Name }); return View(new UserModel()); } public IActionResult Edit() { ViewBag.CountryList = areas.FindAll(x => x.ParentId == null).Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Name }); return View(new UserModel() { CountryId = 2, PronviceId = 5, CityId=8,DistrictId = 9, LanguageId = 2 }); } }
运行效果
用法说明
<a asp-action="Index" class="btn btn-success m-b-15">返回</a> <br /><br /> <div class="form-inline row"> <div class="form-group "> <label>国家</label> <select asp-for="CountryId" class="form-control selectList" asp-items="ViewBag.CountryList" data-select-childids="LanguageId,PronviceId"> <option value="">请选择</option> </select> </div> <div class="form-group "> <label>语言</label> <select asp-for="LanguageId" class="form-control" data-select-value="@Model.LanguageId" data-select-url="/DropDownList/GetLanguageId?id=1" data-select-paramids="CountryId" data-select-hasdefault="false" data-verb="Get" 请求的方式 > <option value="">请选择</option> </select> </div> <div class="form-group"> <label>省</label> <select asp-for="PronviceId" class="form-control" data-select-childids="CityId" data-select-value="@Model.PronviceId" data-select-url="/DropDownList/GetPronviceId?id=1" data-select-paramids="CountryId" > <option value="">请选择</option> </select> </div> <div class="form-group"> <label>市</label> <select asp-for="CityId" class="form-control" data-select-childids="DistrictId" data-select-value="@Model.CityId" data-select-url="/DropDownList/GetCityId" data-select-paramids="PronviceId" > <option value="">请选择</option> </select> </div> <div class="form-group"> <label>区</label> <select asp-for="DistrictId" class="form-control" data-select-value="@Model.DistrictId" data-select-url="/DropDownList/GetDistrictId" > <option value="">请选择</option> </select> </div> </div>
data-select-childids :设置联动的select下拉的Id逗号分隔。例如在国家的下拉中 data-select-childids="LanguageId,PronviceId"表示,国家的下拉影响 语言和 省
data-select-value: 数据加载时的初始值 用在编辑表单时,存储当前下拉
data-select-url: 请求的url
data-select-paramids: 参数值的Id