扩展 jquery miniui 组件实现自动查询数据
主题
之前写过一篇文章分享了公司basecode查找数据后台是怎么实现的(http://www.cnblogs.com/abcwt112/p/6085335.html).今天想分享一下公司前台是怎么扩展jquery miniui组件去配合后台实现自动查找数据的.
一个使用例子
项目中多多少少会遇到要下拉一些数据(不只是下拉,可能还有选择框等等).

这些数据来自数据库里的某张代码表(当然也可以是复杂的SQL查询).这些数据写死在前台明显是不可能的,因为不同环境下配置的数据可能不同.但是为了每个下拉框去写一个Controller方法,Service方法.Dao方法...好像代价又太大了,而且他们具有一定的同性.这就是Basecode的存在的一个原因.
前台实现
后台的实现请参考我另外一篇文章,这篇文章主要分享下怎么扩展jquery miniui组件(miniui是类似于jquery easyui的一个前台JS框架)来实现前台自动发送请求加载数据实现basecode的下拉.
jquery miniui不是开源的,所以自己写组件继承起来比较蛋疼...但是多多少少还是可以做一些简单的扩展的.
一个最简单的代码表下拉的例子
实现basecode自动下拉的主要原理是利用了beforeload事件.
我们自己定义的组件继承了原本miniui的组件,重写了部分方法,在组件在初始化的时候额外加入了beforeload事件并触发,这样这个组件就会自动去后台查找数据了.
mini.extend(framework.component.ComboList , mini.ComboBox , {
codeType : "", //绑定代码类型
remote : false, //是否从远端加载数据
textField : "label",
uiCls: "mini-ext_combolist",
valueField : "value",
queryparam : {},
/**
* 重定义加载数据的方法,根据codeType指定的加载数据
*/
load : function(data){
if(this.codeType && this.codeType.length > 0){
if(basecode[this.codeType] && !this.remote){
this.setData(basecode[this.codeType]);
}else{
this.setUrl(common.getBascodeUrl()+"/"+this.codeType);
}
}
},
set : function(kv){
var me = this;
framework.component.ComboList.superclass.set.call(this,kv);
me.on('beforeload',function(e){
e.type = 'POST';
e.dataType = 'json';
e.contentType = 'application/json';
e.data = mini.encode(this.queryparam);
});
this.load({});
},
setCodeType: function (codeType) {
this.codeType = codeType;
},
getCodeType : function(){
return this.codeType ;
},
getAttrs: function (el) {
var attrs = framework.component.ComboList.superclass.getAttrs.call(this, el);
mini._ParseString(el, attrs , ['codeType']);
mini._ParseString(el, attrs , ['param']);
var param = attrs['param'];
if(param){
var cotrolids = param.match(common.PARAM_CMP_VALUE_REGEX);
if(cotrolids && cotrolids.length > 0){
$.each(param.match(common.PARAM_CMP_VALUE_REGEX),function(i,item){
var id = '#'+item.replace(/#/gi,'');
var tempobj = mini.get(id);
if(tempobj && tempobj.value){
param = param.replace(item , tempobj.getValue());
}
});
}
this.queryparam = mini.decode(param) != 'undefined' ? mini.decode(param) : "";
}
attrs['textField'] = attrs['textField'] || 'label';
attrs['valueField'] = attrs['valueField'] || 'value';
mini._ParseBool(el, attrs,['remote']);
return attrs;
}
});
mini.regClass(framework.component.ComboList , 'ext_combolist');
完整的一个扩展的组件代码如上面.
当组件被渲染的时候:
第一个被调用的方法是L48的getAttrs方法,这个方法的用处就是把你页面上HTML标签比如input里面的各种属性解析成JS对象里面的属性.
比如你<input codeType="ENUM_SEX">那codeType就会被解析成JS对象的一个属性,{codeType:"ENUM_SEX"}.当然.不同框架的解析方法肯定不同,所以这里并不需要仔细研究(而且也没有源码).
最主要的属性是codeType,当然param这些也有用处(param里的key和value相当于是查询SQL where里面的条件).但是最简单的例子里不需要用到这些额外的参数,只要知道codeType就能知道basecode里去查哪张表了(详见另外一篇文章)
第二个被调用的方法是L28 set方法:set的作用就是把之前getAttrs取出来的JS对象的各种属性设置到miniui组件的属性中去.所以getAttrs返回的值就是set方法的入参.
在这里除了调用父组件的set方法完成基本的set之外,额外做了一个操作,就是最核心的beforeload事件.为自定的组件绑定了beforeload事件.
beforeload事件里主要是定义了ajax请求的一些参数.比如dataType是json等等..还有一个比较重要的就是ajax传递的参数data是来自组件的queryparam属性(所以组件要传递的参数应该放到这个属性里).
第三个调用的当然是L18 load方法.它是在set方法最后一行被调用的
load方法里因为我们设置了codeType又设置了remote为true,所以会走else里面的代码.即从远程服务器端加载数据.
当我们调用setUrl方法以后miniui组件去发起get请求查找basecode的Controller的数据.后续后台流程请参考另外一篇文章.
至此前台请求发送完毕,把返回的数据根据textField和valueField显示到页面上即可.
当组件查询的值需要依赖于其他组件的时候(多级联动)
多级联动的情况在现实中还是比较常见的,公司本身扩展的组件也不是支持的很好,旁边小哥也自己扩展了一个,仍然有一些BUG.然后我又在他们的基础上修改了一下.(大部分时候开发还是自己去写valuechange事件,而不是自动多级联动)

多级联动和一般的查代码表的区别在于,多级联动的时候你后面的下拉框的查询的值要依赖于前面的值.
比如上面3个组件.大类A,种类B,小类C.
b能下拉出什么值依赖于a,c依赖于b.
所以我们在组件里要有个属性记录当前组件依赖的组件.
比如组件b的html标签:
<input baseValue="#a组件的id#" ........>
getAttrs: function (el) {
..........
this.baseValue = attrs['baseValue'];
...............
}
我们用的是baseValue.
当然在getAttrs里直接set属性是不好的,应该在set那个方法里去设置.不过这样做也没啥问题(反正也能用).
this.on('beforeload',function(e){
...............
var tmpBaseValue = this.baseValue;
............各种加工tmpBasevalue
this.queryParam = {};
this.queryParam.parent = (e.params && e.params['value']) || tmpBaseValue;
if(this.queryParam.initParam != undefined){
this.queryParam.initParam = (e.params && this.queryParam.initParam) ? null : this.queryParam.initParam;
}
var param = {};
$.extend(true, param,this.queryParam );
................
}
然后在beforeload事件里把baseValue对应的id的miniui组件的getValue值合并到param里(中间处理逻辑被我省略了..因为不同框架处理逻辑肯定不同,这里也没啥通用性).最后会发送给后台.这样在查询组件b的basecode的值的时候还会附带上组件a的值作为查询条件之一.
多级联动还有个小特点就是你选了a,最好要把b的值清空.
这里是用blur事件来做的.
var id = '#'+this.baseValue.replace(/#/gi,'');
var tempobj = mini.get(id);
if(tempobj){
tempobj.on("blur",function(){
if(!tempobj.oldValue || (tempobj.oldValue && tempobj.getValue() != tempobj.oldValue)){
tempobj.oldValue = tempobj.getValue();
me.setData([]);
me.setValue("");
me.setUrl(me.getUrl());
}
});
}
根据baseValue找到依赖的组件,然后为组件绑定blur事件,当依赖组件的焦点丢失的时候(这个时候肯定是操作过组件,并且新选择的值和原本的值不同),触发blur事件,更新当前组件的值.
不过这里只更新了当前组件,并没有修改依赖于当前组件的组件的值,算是有点瑕疵吧.
树组件
树组件是最复杂的一个组件了吧..不过我们这里用到的地方也不多,即使用到大部分时候也就CV一下别人写好的就OK了.不过学习的话还是有些地方值得研究研究的.
树组件复杂是因为有懒加载的情况,第一次取数据和后续取数据的SQL会有很大不同,比如第一次查数据的时候你的where条件里需要条件1,2,3....第二次加载子节点的时候你的where条件可能变成了只需要条件1加上父节点的代码值.所以where条件变化比较大,和一般的下拉框不同.
对于后台来说(详见另外一篇文章)就是filterSQL里依赖的参数Map不同.需要根据传过来的filterParam或者initParam来拼不同SQL.
对于前台来说就是怎么根据不同的情况组织不同的数据(主要是initParam怎么区分是第一次加载还是后续加载,因为initParam在第一次加载和后续加载的时候会传不同的参数,而filterParam则每次都会传一样的参数).
this.on('beforeload',function(e){
.................
this.queryParam.parent = (e.params && e.params['value']) || tmpBaseValue;
if(this.queryParam.initParam != undefined){
this.queryParam.initParam = (e.params && this.queryParam.initParam) ? null : this.queryParam.initParam;
}
................
}
忽略其他的代码,从这4行代码中可以看出,this.queryParam.parent取什么值是根据e.param来的.e.param到底什么时候会有值呢? 实践中发现是当你点击父节点加载子节点的时候才会有值(然而miniui的api中啥都没提到.).
那么这段代码就可以解释为:当第一次load树组件加载数据的时候,initParam是会有值的(自己写在html里),而parent是没值的,当后续懒加载点击父节点加载子树的时候initParam是null而parent是e.param也就是父节点的代码值.
这样就可以保证不同情况下树组件可以向后台传递不同的值.
一个小例子
<input .... param="{'initParam':{'SCENARIO':'NONE','SWJG_DM_VALUE':['#swjg-zgsws#']} ,'filterParam':{'SCENARIO':'ASSIGNSWKS','GDSLX_DM_VALUE':${loginDTO.gdslxDm}}}"/>

第一次加载树的时候请求的时候initParam有值

第二次加载子节点的时候请求initParam没有值,附加了一个parent节点的值.
小问题
组件虽然好用,但是还是有一点小问题的:
1.当没有使用filterParam,initParam的scenario的时候,html中的param是直接把key拼接到where里当做查询条件,把value设置到JPA的Query的Parameter里的.所以查询条件是有SQL注入的风险的.意思就是你如果构造了一个请求,传递的param是{1:"1"}那这样拼接成的SQL就是select.....from...where 1=1 and 1=1. 如果使用filterParam,initParam的scenario则没有问题,因为拼接的where条件是写在数据库里的.
2.拼接条件都是and连接的.如果你要复杂的条件,或者来个or连接就跪了...
小小结
虽然有一些不足的地方,但是公司封装的这套basecode在大多数情况下还是非常好用的,而且让我学到了不少知识:尤其是给我提供了一种自动加载数据的思路.
扩展 jquery miniui 组件实现自动查询数据的更多相关文章
- jQuery MiniUI开发系列之:数据验证
在开发应用系统界面时,往往需要进行很多.复杂的数据验证,当填写的数据符合规定,才能提交保存. jQuery MiniUI提供了比较完美的表单数据验证和错误显示的方式. 常见的表单控件,都有一个验证事件 ...
- 一例基于thinkphp,jquery和bootstrap渲染的查询数据分页器
对于某些查询记录很多的结果,web页面不得不采用分页器,现在奉上一例代码,其主要逻辑是:由页面的dom 节点发起ajax请求,返回的查询结果根据页面布局需要进行切片:并根据总记录数和页面展现的条数算出 ...
- 扩展JQUERY 表单加载JSON数据
$.fn.extend({ //表单加载json对象数据 setForm : function (jsonValue) { var obj = this; $.each(jsonValue, func ...
- Android开发 ---基本UI组件5:监听下拉选项,动态绑定下拉选项、全选/反选,取多选按钮的值,长按事件,长按删除,适配器的使用,提示查询数据,activity控制多按钮
效果图: 效果描述: 1.当点击 1 按钮后,进入选择城市的页面,会监听到你选中的城市名称:动态为Spinner绑定数据 2.当点击 2 按钮后,进入自动查询数据页面,只要输入首字母,就会动态查找以该 ...
- EasyUI的treegrid组件动态加载数据问题的解决办法
http://www.jquerycn.cn/a_3455 —————————————————————————————————————————————————————————————————————— ...
- Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)
jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...
- Web jquery表格组件 JQGrid 的使用 - 7.查询数据、编辑数据、删除数据
系列索引 Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引 Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数.ColModel API.事件 ...
- Web jquery表格组件 JQGrid 的使用 - 8.Pager、新增数据、查询、刷新、查看数据
系列索引 Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引 Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数.ColModel API.事件 ...
- jQuery MiniUI开发系列之:创建组件对象
jQuery MiniUI可以使用Javascript和Html两种方式来创建对象. 1)Javascript创建对象 使用JavaScript创建对象,是最基本的方式,有如下几个要点: 1)使用ne ...
随机推荐
- 使用ganglia监控hadoop及hbase集群
一.Ganglia简介 Ganglia 是 UC Berkeley 发起的一个开源监视项目,设计用于测量数以千计的节点.每台计算机都运行一个收集和发送度量数据(如处理器速度.内存使用量等)的名为 gm ...
- Hive安装(一)之环境配置
Hive Web Interface(HWI)简介:Hive自带了一个Web-GUI,功能不多,可用于效果展示,如果没有安装Hue的话,是个不错的选择. 由于hive-bin包中没有包含HWI的页面, ...
- 烂泥:centos6 yum方式升级内核
本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb 最近没有时间好久没有写文章了,今天由于需要安装docker学习虚拟容器的知识,需要升级O ...
- zabbix完整安装
一.nginx安装 1.必要软件准备: 为了支持rewrite功能,我们需要安装pcre: yum install pcre-* 需要ssl的支持,如果不需要ssl支持,请跳过这一步: yum ins ...
- python写红包的原理流程包含random,lambda其中的使用和见简单介绍
Python写红包的原理流程 首先来说说要用到的知识点,第一个要说的是扩展包random,random模块一般用来生成一个随机数 今天要用到ramdom中unifrom的方法用于生成一个指定范围的随机 ...
- 例解 Linux cd 命令
cd 命令是 *nix 系统中最基本的命令,它所做的事情是改变你当前所在的目录.本文详细介绍该命令,它所能完成的功能以及关于该命令内在的东西. cd 命令:一个内置命令 BASH Shell 是大多 ...
- 初识SpringMvc
初识SpringMvc springMvc简介:SpringMVC也叫Spring Web mvc,属于表现层的框架.Spring MVC是Spring框架的一部分,是在Spring3.0后发布的 s ...
- 安装ArcGIS Desktop 9.3
本文仅用于学习交流,商业用途请支持正版!转载请注明: http://www.cnblogs.com/mxbs/p/6216865.html 准备: ArcGIS Desktop 9.3.crack_f ...
- [No00008D]腾讯通RTX联系方式批量获取
公司用的RTX让我一直很不爽,QQ比RTX好多少为啥不让用,微信都有企业版了为啥还用腾讯通?终于今天发现唯一的好处是可以从服务器上拉公司妹子们的联系方式!!当然,我要这些联系方式,只是为了联tiao系 ...
- 【repost】js 常见错误类型
1)SyntaxError SyntaxError是解析代码时发生的语法错误 // 变量名错误 var 1a; // 缺少括号 console.log 'hello'); (2)Referenc ...