在上篇《基于Metronic的Bootstrap开发框架经验总结(2)--列表分页处理和插件JSTree的使用》介绍了数据的分页处理,使用了Bootstrap Paginator插件,另外对树形列表,采用了JSTree插件,本篇继续介绍在编辑页面中常用到的控件Select2,这个控件可以更加丰富传统的Select下拉列表控件,提供更多的功能和更好的用户体验。

1、Select2控件介绍

这个插件是基于Select的扩展插件,能够提供更加丰富的功能和用户体验,它的github官网地址为:https://select2.github.io/,具体的使用案例,可以参考地址:https://select2.github.io/examples.html。

我们在整个框架里面,用到了很多Select2控件来处理内容的显示,包括单选的下拉列表(包括级联选择框)、复选的下拉列表、树形下拉列表等方式,界面效果如下所示。

1)编辑界面下的省份、城市、所在行政区的级联界面效果,选择省份,会加载对应省份下的城市,选择城市,会继续加载城市下的行政区,从而实现多级关联的下拉列表效果。

2)编辑界面下的多项选择下拉列表

但我们选择其中的内容的时候,系统自动显示出没有选择的列表数据,非常直观友好,如下所示。

3)树形列表的下拉列表

有时候,我们的一些数据可能有层次关系的,如所属机构、上层列表等等。

2、Select2控件的实际使用代码分析1)基础界面代码及操作

使用select2控件,一般是在常规的select控件上,设置一下即可(设置它的class为select2)。

<divclass="col-md-6"><divclass="form-group"><labelclass="control-labelcol-md-4">重要级别</label><divclass="col-md-8"><selectid="Importance"name="Importance"class="form-controlselect2"placeholder="重要级别..."></select></div></div></div><divclass="col-md-6"><divclass="form-group"><labelclass="control-labelcol-md-4">认可程度</label><divclass="col-md-8"><selectid="Recognition"name="Recognition"class="form-controlselect2"placeholder="认可程度..."></select></div></div></div>

如果是固定列表,那么也就是设置它的Option内容即可,如下所示。

<divclass="col-md-6"><divclass="form-group"><labelclass="control-labelcol-md-4">吸烟</label><divclass="col-md-8"><selectid="Smoking"name="Smoking"type="text"class="form-controlselect2"placeholder="吸烟..."><option>吸烟</option><option>不吸烟</option></select></div></div></div>


简单的select2控件初始化代码如下所示。

$(document).ready(function(){$(".js-example-basic-single").select2();});

一般情况下,如果允许复选多个项目,那么设置multiple="multiple"即可,如下代码所示。

<selectid="ResponseDemand"name="ResponseDemand"multiple="multiple"class="form-controlselect2"></select>

2)异步数据绑定操作

一般情况下,我们的select控件的数据,是从数据库里面动态加载的,因此一般是通过Ajax方式获取数据并进行绑定即可。

基于代码可重用性的考虑,我们编写一个公用的JS函数,用来减少绑定操作的代码,提高代码重用性。

//绑定字典内容到指定的Select控件functionBindSelect(ctrlName,url){varcontrol=$('#'+ctrlName);//设置Select2的处理control.select2({allowClear:true,formatResult:formatResult,formatSelection:formatSelection,escapeMarkup:function(m){returnm;}});//绑定Ajax的内容$.getJSON(url,function(data){control.empty();//清空下拉框$.each(data,function(i,item){control.append("<optionvalue='"+item.Value+"'>&nbsp;"+item.Text+"</option>");});});}

这样,绑定公用字典模块的数据,也就可以通过下面进一步封装处理即可。

//绑定字典内容到指定的控件functionBindDictItem(ctrlName,dictTypeName){varurl='/DictData/GetDictJson?dictTypeName='+encodeURI(dictTypeName);BindSelect(ctrlName,url);}

这样我们初始化Select2 控件,并动态绑定对应的字典值或者其他数据,则可以通过下面初始化代码即可实现。其中BindDictItem就是直接绑定字典内容的操作,BindSelect则是根据URL进行数据的获取并绑定,而$("#Province").on("change", function (e) {});这样的函数处理,就是处理选择内容变化的联动操作了。

//初始化字典信息(下拉列表)functionInitDictItem(){//部分赋值参考BindDictItem("Area","市场分区");BindDictItem("Industry","客户行业");BindDictItem("Grade","客户级别");BindDictItem("CustomerType","客户类型");BindDictItem("Source","客户来源");BindDictItem("CreditStatus","信用等级");BindDictItem("Stage","客户阶段");BindDictItem("Status","客户状态");BindDictItem("Importance","重要级别");//绑定省份、城市、行政区(联动处理)BindSelect("Province","/Province/GetAllProvinceNameDictJson");$("#Province").on("change",function(e){varprovinceName=$("#Province").val();BindSelect("City","/City/GetCitysByProvinceNameDictJson?provinceName="+provinceName);});$("#City").on("change",function(e){varcityName=$("#City").val();BindSelect("District","/District/GetDistrictByCityNameDictJson?cityName="+cityName);});}

而其中MVC控制器返回的数据,我们是返回一个JSON数据列表给前端页面的,他们的数据格式如下所示。

[{"Text":"","Value":""},{"Text":"学术会议","Value":"学术会议"},{"Text":"朋友介绍","Value":"朋友介绍"},{"Text":"广告媒体","Value":"广告媒体"}]

这样前端页面绑定Select2控件的时候,就使用了JSON对象的属性即可。

//绑定Ajax的内容$.getJSON(url,function(data){control.empty();//清空下拉框$.each(data,function(i,item){control.append("<optionvalue='"+item.Value+"'>&nbsp;"+item.Text+"</option>");});});

控制器的实现代码如下:

///<summary>///根据字典类型获取对应的字典数据,方便UI控件的绑定///</summary>///<paramname="dictTypeName">字典类型名称</param>///<returns></returns>publicActionResultGetDictJson(stringdictTypeName){List<CListItem>treeList=newList<CListItem>();CListItempNode=newCListItem("","");treeList.Insert(0,pNode);Dictionary<string,string>dict=BLLFactory<DictData>.Instance.GetDictByDictType(dictTypeName);foreach(stringkeyindict.Keys){treeList.Add(newCListItem(key,dict[key]));}returnToJsonContent(treeList);}


3)树形列表的绑定操作

对于属性列表,如所属公司、所属部门机构等有层次性的数据,它的绑定操作也是类似的,如下代码所示。

//绑定添加界面的公司、部门、直属经理BindSelect("Company_ID","/User/GetMyCompanyDictJson?userId="+@Session["UserId"]);$("#Company_ID").on("change",function(e){varcompanyid=$("#Company_ID").val();BindSelect("Dept_ID","/User/GetDeptDictJson?parentId="+companyid);});$("#Dept_ID").on("change",function(e){vardeptid=$("#Dept_ID").val();BindSelect("PID","/User/GetUserDictJson?deptId="+deptid);});

只是它们返回的数据,我们把它作为有缩进的显示内容而已。

[{"Text":"爱奇迪集团","Value":"1"},{"Text":"广州分公司","Value":"3"},{"Text":"上海分公司","Value":"4"},{"Text":"北京分公司","Value":"5"}]

或者如下所示

[{"Text":"广州分公司","Value":"3"},{"Text":"总经办","Value":"6"},{"Text":"财务部","Value":"7"},{"Text":"工程部","Value":"8"},{"Text":"产品研发部","Value":"9"},{"Text":"  开发一组","Value":"14"},{"Text":"  开发二组","Value":"15"},{"Text":"  测试组","Value":"16"},{"Text":"市场部","Value":"10"},{"Text":"  市场一部","Value":"23"},{"Text":"  市场二部","Value":"24"},{"Text":"综合部","Value":"11"},{"Text":"生产部","Value":"12"},{"Text":"人力资源部","Value":"13"}]

综上两个部分,我们可以看到它们的Text的内容,是根据层次关系进行空格增加,从而实现了层次关系的显示。

不过从这个界面效果上讲,这样的处理确实没有EasyUI里面,对下拉列表树的展示好看,也许可以利用更好的Bootstrap插件进行这个树形内容的展示。

4)select2控件的赋值处理

上面介绍的方法,都是介绍select2控件的初始化,绑定相关的数据,那么如果初始化界面后,我们绑定编辑界面的值的时候,就需要赋值给控件,让它显示真正需要显示的项目了。

如清空控件的方法如下所示。

//清空Select2控件的值$("#PID").select2("val","");$("#Company_ID").select2("val","");$("#Dept_ID").select2("val","");

如果对于多个控件,需要清除,则可以使用集合进行处理

varselect2Ctrl=["Area","Industry","Grade","CustomerType","Source","CreditStatus","Stage","Status","Importance"];$.each(select2Ctrl,function(i,item){varctrl=$("#"+item);ctrl.select2("val","");});

给Select2 控件赋值,让它显示对应值内容的项目,那么操作也就和上面的类似了。

$("#CustomerType").select2("val",info.CustomerType);$("#Grade").select2("val",info.Grade);$("#CreditStatus").select2("val",info.CreditStatus);$("#Importance").select2("val",info.Importance);$("#IsPublic").select2("val",info.IsPublic);

如果需要级联显示的,那么做法增加一个onchange的函数处理就可以了,如下级联代码的赋值处理如下。

$("#Province").select2("val",info.Province);$("#Province").trigger('change');//联动$("#City").select2("val",info.City);$("#City").trigger('change');//联动$("#District").select2("val",info.District);$("#Company_ID1").select2("val",info.Company_ID);$("#Company_ID1").trigger('change');$("#Dept_ID1").select2("val",info.Dept_ID);$("#Dept_ID1").trigger('change');$("#PID1").select2("val",info.PID);

多个列表项目数据的绑定。

我们从案例里面可以看到,Select2支持多项值的选择,它们保存后会以逗号分开,如果我们需要在编辑的时候显示存储的多个记录,那么需要把字符串转换为数组列表才能进行正确绑定,如下所示。

$("#Permission").select2("val",info.Permission.split(','));

最后来两个整体性的界面效果,供参考。