今天很激动啊,昨天下午赶时间写的省市县乡村 动态级联加载控件AreaRender(一)已经有博友评论了,
对于刚开始写博客的我是莫大的鼓励,我会继续写下去,逐步提高自己的文学素养,写出像 T2噬菌体博主一样受到大家欢迎的作品。
好了,言归真转,接下来我们先分析一下关于分布视图~/Views/AreaManager/AreaRender.cshtml的编写问题。
该分布视图包含两个部分:隐藏域(即用户要搜集的数据部分)和五个select下拉列表
@* //功能:实现对省市县乡村的自动级联加载 //作者:刘帅 liushuai@upway.cn //时间:2012.11.29 周四 //使用说明:首先,用户需要提供一个字典,其中键对应字段名称,值就是对应字段的值; // 其次,要提供获取省份数据的url和获取下一级区划的url。 //版本:v1.0 *@ @if (Model.data != null) { //原始数据 Dictionary<string, string> ds = Model.data; //随即生成工作区,以免相互干扰 Random random = new Random(); System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append((char)random.Next(65, 90)); sb.Append((char)random.Next(97, 122)); sb.Append((char)random.Next(97, 122)); sb.Append((char)random.Next(97, 122)); //定义工作区 <div id="@sb.ToString()-div"> @{ //生成隐藏域,一次按照省市县乡村的顺序进行加载,便于操作 for (int i = 0; i < ds.Count; i++) { <input type="hidden" id="@ds.ElementAt(i).Key.Replace('.', '-')" name="@ds.ElementAt(i).Key" value="@ds.ElementAt(i).Value" /> } //生成级联加载的结束标记 <input type="hidden" id="end" value="@ds.ElementAt(5).Key.Replace('.', '-')" /> //生成五个select:id,name和class的前缀均为'Spring-'以免发生冲突,也是我最喜欢的单词和季节; //onchange事件:1.刷新隐藏域的值,2.加载下一级; //第一个参数是工作区,第二个参数当前select的Id,第三个参数是下一个select的id,第四个参数是获取下一级区划的url,第五个参数是select的类 <select id="Spring-province" name="Spring-province" class="Spring-select" οnchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-province','Spring-city','@Model.nextUrl',' .Spring-select')"> </select> <select id="Spring-city" name="Spring-city" class="Spring-select" οnchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-city','Spring-country','@Model.nextUrl',' .Spring-select')"> </select> <select id="Spring-country" name="Spring-country" class="Spring-select" οnchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-country','Spring-town','@Model.nextUrl',' .Spring-select')"> </select> <select id="Spring-town" name="Spring-town" class="Spring-select" οnchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-town','Spring-village','@Model.nextUrl',' .Spring-select')"> </select> <select id="Spring-village" name="Spring-village" class="Spring-select" οnchange="AddNextLevel('#' + '@sb.ToString()-div #','Spring-village','','',' .Spring-select')"> </select> <script type="text/javascript"> //触发加载省份信息 AddProvince("#" + "@sb.ToString()-div #", "Spring-province", "Spring-city", "@ds.ElementAt(0).Key.Replace('.', '-')", "@ds.ElementAt(1).Key.Replace('.', '-')", '@Model.provinceUrl', '@Model.nextUrl'); </script> } </div> }
出于对通用性的要求,我将该控件包含在一个动态生成id的div中,以避免不必要的冲突;
这样一来,该控件就可以在同一个页面中存在多个,而又不产生混淆。当然这段代码也不是一蹴而就的,是在不断地思考,不断地修改。
并且尽量减少该分部视图对外部的耦合度。
我又详细的注释,大家又不理解的地方可以提出来,共同讨论。
到目前为止,还有最终要的js文件没有编写,接下来让我们开始吧:
首先,为便于理解,我将每一个方法都独立为一个Js文件。
为了将该问题简化,我将该控件的加载过程很自然的分为两个阶段(大家很自然就能想到):
1.为下拉选项卡赋值阶段
2.动态级联加载阶段,也就是select的onchange事件
其中第一阶段包含三个函数:AddProvince、SetValue和InitNextLevel
//功能:初始化省份,调用SetValue为select赋值 //作者:刘帅 liushuai@upway.cn //时间:2012.11.29 周四 //参数说明:c->工作区div; province->省份对应的select的id; city->市对应的select的id // f->当前隐藏域的id; s->下一个隐藏域的id; provinceUrl->获取省份信息的路径 // nextUrl->获取下一级数据的路径 //版本:v1.0 function AddProvince(c, province, city, f, s, provinceUrl, nextUrl) { //当前省份对应的select var sprovince = $(c + province); //异步加载所有省份,加载之后根据隐藏域的值为select赋值 $.ajax( { type: "post", url: provinceUrl, datatype: "Json", success: function (data) { if (data != null) { //清空残留 sprovince.empty(); //追加新的options var option = $("<option>").text(" ").val(""); sprovince.append(option); $.each(data, function (i, item) { var option = $("<option>").text(item.Name).val(item.Code) sprovince.append(option); }); SetValue(c, province, city, f, s, nextUrl); } } }); }
//功能:初始化数据时,为select赋值,并调用InitNextLevel加载下一级 // 当没有初始值时返回,当遇到结束标志是返回 //作者:刘帅 liushuai@upway.cn //时间:2012.11.29 周四 //参数说明:c->工作区div; fs->当前select的id; ss->下一个select的id // f->当前隐藏域的id; s->下一个隐藏域的id; url->获取下一级数据的路径 //版本:v1.0 function SetValue(c, fs, ss, f, s, url) { //隐藏域的值 var hiddenValue = $(c + f).val(); if (hiddenValue == 0 || hiddenValue == null || hiddenValue == 'undefined') { //alert("没有值!!"); 没有初始值,返回 return; } //为select赋值 $(c + fs).val(hiddenValue); //如果遇到结束标志,返回 if (f == $(c + "end").val()) { return; } //初始化下一级 InitNextLevel(c, fs, ss, f, s, url); }
//功能:初始化省以外的select,并调用SetValue为select赋值 //作者:刘帅 liushuai@upway.cn //时间:2012.11.29 周四 //参数说明:c->工作区div; fs->当前select的id; ss->下一个select的id // f->当前隐藏域的id; s->下一个隐藏域的id; url->获取下一级数据的路径 //版本:v1.0 function InitNextLevel(c, fs, ss, f, s, url) { //隐藏域的值,根据上一个select的值获取下级数据 var hiddenValue = $(c + f).val(); var nextSelect = $(c + ss); $.ajax({ type: "post", data: { "code": hiddenValue }, url: url, datatype: "Json", success: function (data) { if (data != null) { nextSelect.empty(); var option = $("<option>").text(" ").val(""); nextSelect.append(option); $.each(data, function (i, item) { var option = $("<option>").text(item.Name).val(item.Code) nextSelect.append(option); }); //移动到下一级别 fs = ss; ss = $(c + fs).next("select").attr("id"); f = s; s = $(c + f).next("input").attr("id"); SetValue(c, fs, ss, f, s, url); } } }); }
第二个阶段包含一个方法:AddNextLevel
//功能:select的onchange事件,保存已选值,加载下一级数据 //作者:刘帅 liushuai@upway.cn //时间:2012.11.29 周四 //参数说明:c->工作区div; fs->当前select的id; ss->下一个select的id selectClass->select的class //版本:v1.0 function AddNextLevel(c, fs, ss, url, selectClass) { //清除当前节点之后所有select的值 $(c + fs).nextAll("select").each(function (i, item) { $(item).empty(); }); var selects = $(c.substr(0, c.length - 2) + selectClass); var ids = $(c.substr(0, c.length - 2) + " input"); //遍历c区域中所有的select值,并赋值给隐藏域(包含两部分:id和name,需要重载) for (var i = 0; i < 5; i++) { ids[i].value = selects[i].value; var selectValue = $(c + selects[i].id + " option:selected").text(); ids[i + 5].value = selectValue; } var nextSelect = $(c + ss); //异步加载下一级别 $.ajax({ type: "post", data: { "code": $(c + fs + " option:selected").val() }, url: url, datatype: "Json", success: function (data) { if (data != null) { nextSelect.empty(); var option = $("<option>").text(" ").val(""); nextSelect.append(option); $.each(data, function (i, item) { var option = $("<option>").text(item.Name).val(item.Code) nextSelect.append(option); }); } } }); }
F5调试:
更改第一个省份之后:
修改第二个的所有值:
生成的html代码:
<!DOCTYPE html> <html> <head> <title>测试地区的级联加载</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script> </head> <body> <script src="http://www.cnblogs.com/Scripts/InitNextLevle.js" type="text/javascript"></script> <script src="http://www.cnblogs.com/Scripts/AddNextLevel.js" type="text/javascript"></script> <script src="http://www.cnblogs.com/Scripts/SetValue.js" type="text/javascript"></script> <script src="http://www.cnblogs.com/Scripts/AddProvince.js" type="text/javascript"></script> <form action="/Home/Save" method="post"> <div id="Sjih-div"> <input type="hidden" id="pro-id" name="pro.id" value="650000000000" /> <input type="hidden" id="cit-id" name="cit.id" value="650100000000" /> <input type="hidden" id="cou-id" name="cou.id" value="650102000000" /> <input type="hidden" id="tow-id" name="tow.id" value="650102002000" /> <input type="hidden" id="vil-id" name="vil.id" value="650102002002" /> <input type="hidden" id="pro-name" name="pro.name" value="新疆维吾尔自治区" /> <input type="hidden" id="cit-name" name="cit.name" value="乌鲁木齐市" /> <input type="hidden" id="cou-name" name="cou.name" value="天山区" /> <input type="hidden" id="tow-name" name="tow.name" value="燕儿窝街道" /> <input type="hidden" id="vil-name" name="vil.name" value="燕儿窝南社区居委会" /> <input type="hidden" id="end" value="pro-name" /> <select id="Spring-province" name="Spring-province" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-province','Spring-city','/Home/GetNextLevel',' .Spring-select')"> </select> <select id="Spring-city" name="Spring-city" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-city','Spring-country','/Home/GetNextLevel',' .Spring-select')"> </select> <select id="Spring-country" name="Spring-country" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-country','Spring-town','/Home/GetNextLevel',' .Spring-select')"> </select> <select id="Spring-town" name="Spring-town" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-town','Spring-village','/Home/GetNextLevel',' .Spring-select')"> </select> <select id="Spring-village" name="Spring-village" class="Spring-select" onchange="AddNextLevel('#' + 'Sjih-div #','Spring-village','','',' .Spring-select')"> </select> <script type="text/javascript"> //触发加载省份信息 AddProvince("#" + "Sjih-div #", "Spring-province", "Spring-city", "pro-id", "cit-id", '/Home/GetProvinces', '/Home/GetNextLevel'); </script> </div> <div id="Rwpe-div"> <input type="hidden" id="pro-id" name="pro.id" value="650000000000" /> <input type="hidden" id="cit-id" name="cit.id" value="650100000000" /> <input type="hidden" id="cou-id" name="cou.id" value="650102000000" /> <input type="hidden" id="tow-id" name="tow.id" value="650102002000" /> <input type="hidden" id="vil-id" name="vil.id" value="650102002002" /> <input type="hidden" id="pro-name" name="pro.name" value="新疆维吾尔自治区" /> <input type="hidden" id="cit-name" name="cit.name" value="乌鲁木齐市" /> <input type="hidden" id="cou-name" name="cou.name" value="天山区" /> <input type="hidden" id="tow-name" name="tow.name" value="燕儿窝街道" /> <input type="hidden" id="vil-name" name="vil.name" value="燕儿窝南社区居委会" /> <input type="hidden" id="end" value="pro-name" /> <select id="Spring-province" name="Spring-province" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-province','Spring-city','/Home/GetNextLevel',' .Spring-select')"> </select> <select id="Spring-city" name="Spring-city" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-city','Spring-country','/Home/GetNextLevel',' .Spring-select')"> </select> <select id="Spring-country" name="Spring-country" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-country','Spring-town','/Home/GetNextLevel',' .Spring-select')"> </select> <select id="Spring-town" name="Spring-town" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-town','Spring-village','/Home/GetNextLevel',' .Spring-select')"> </select> <select id="Spring-village" name="Spring-village" class="Spring-select" onchange="AddNextLevel('#' + 'Rwpe-div #','Spring-village','','',' .Spring-select')"> </select> <script type="text/javascript"> //触发加载省份信息 AddProvince("#" + "Rwpe-div #", "Spring-province", "Spring-city", "pro-id", "cit-id", '/Home/GetProvinces', '/Home/GetNextLevel'); </script> </div> </form> </body> </html>
到这里,我已经把所有的文件都分享出来了,希望大家提出其中的bug和修改办法,共同学习进步!
期待大家的评论,顺便可以加关注!呵呵呵