Bootstrap嵌入jqGrid,使你的table牛逼起来
Bootstrap原生的table组件只能满足简单的数据展示,满足不了更富有操作性的要求。当然了,你可以找到一款叫做“DataTables-1.10.11”的基于bootstrap的table组件,但如果你对API看得不甚了解的话,用起来可就痛苦了,但是如果你选择使用jqGrid,那么本篇教程就给你带来了解决这种富操作性table的解决方案。 一、效果展示OK,就展示这一张图片,相信你已经爱上了bootstrap版的jqGrid,和bootstrap很兼容,简直完美,当然了,这需要我们在缘由的jqGrid上进行一些改动,同时对组件进行一定的封装。 二、资源下载我反正挺热爱分享的,关于jqGrid的组件代码,你可以从jqGrid的官网上下载,但是下载下来需要一些改动,那么我直接将改动后的jqGrid上传到了git,你只需要把提供的文件导入到你对应的项目即可。 另外,你还需要下载一个jquery-ui-1.10.0.custom.css,我就不提供下载地址了,不过我相信,你肯定会找得到,就算是用频出事故的度娘,你也可以找得到。 三、本篇都讲一些什么自从建了QQ群后,“络绎不绝”的有同学加入到群中,但我也发现,进群的一步人直接来找我要demo,或者项目代码,这个我可不喜欢,自己动手做一做,去实现以下,改造一下,才会是你自己的东西,完全照搬我的代码显然你得不到更多的帮助,希望以上同学学习的时候再主动一些。 说完上面这点小废话后,我们言归正传,来说说我们本篇博客主要来讲些什么,什么才是在bootstrap中嵌入jqGrid的关键所在,我总结有如下:
暂定分为以上部分来说明,但必须注意,限于篇幅,博客中只提供思路和部分代码。 ①、 jqGrid在bootstrap中的布局方案<!DOCTYPE html>
<html lang="zh-CN">
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ include file="/components/common/taglib.jsp"%>
<%@ include file="/components/common/csslib.jsp"%>
<head>
<link type="text/css" rel="stylesheet" href="${ctx}/css/deal/my_pay_list.css" />
</head>
<body>
<div class="container">
<form class="form-horizontal" id="jqgridForm" role="form" action="${ctx}/deal/datablePayDealOrdersList" method="post">
<div class="form-group">
<div class="col-sm-12">
<label for="name" class="control-label pull-left">项目名称:</label>
<div class="col-sm-3">
<input type="text" name="name" class="form-control" id="name" placeholder="请输入项目名称" value="" />
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<button type="button" class="btn btn-primary pull-right" id="searchBtn">检索</button>
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<table id="pageGrid" rel="jqgridForm" class="jqgrid"></table>
<div id="pageGridPager"></div>
</div>
</div>
</form>
</div>
<%@ include file="/components/common/jslib.jsp"%>
<script type="text/javascript" src="${ctx}/js/deal/my_pay_list.js"></script>
</body>
</html>
介于每个人的项目千差万别,列出的代码中我们只关注jqGrid部分:
②、 jqGrid自身的构造化参数构造化参数,我把他提取到了①中的my_pay_list.js中。 $(function() {
var jqOption = {
datatype : "xml",mtype : "POST",shrinkToFit : true,viewrecords : false,rownumbers : false,autowidth : true,height : "100%",colNames : [ 'id','status','项目信息','项目状态','订单号','项目名称','下单时间','支付金额','支持数量','订单状态','操作' ],colModel : [
{
name : 'id',index : 'id',hidden : true
},{
name : 'status',index : 'status',{
name : 'image_str',index : 'image_str',width : 140,resizable : false,sortable : false,formatter : function(cellvalue,options,rowObject) {
if (cellvalue == '支付总花费:') {
return cellvalue;
}
},align : 'left'
},{
name : 'oper',index : 'oper',width : 90,align : 'center',rowObject) {
var status = parseInt($(rowObject).find("status").text());
var id = $(rowObject).find("id").text();
if (status == 0) {
return '<a class="color0088cc" width="700" target="dialog" href="' + common.ctx + '/deal/initPayg/' + id + '">去支付</a>';
}
if (status == 1 || status == 3) {
return '<a class="color0088cc" target="_blank" href="' + common.ctx + '/deal/showDealOr/' + id + '">查看详情</a>';
}
if (status == 2) {
return '<a class="color0088cc" target="ajaxTodo" href="' + common.ctx + '/deal/receivder/' + id + '">确认收货</a>';
}
},} ],xmlReader : {
repeatitems : false,root : "PageGrid",row : "map",page : 'page',total : 'total',records : 'records',id : 'ID'
},rowNum : 50,rowList : [ 50,100,200,300 ],pager : "#pageGridPager",footerrow : true,loadError : YUNM.ajaxError,gridComplete : function() {
var $form = $("#" + $("#pageGrid").attr("rel"));
$.ajax({
type : $form.method || 'POST',url : common.ctx + "/deal/getAllOrded",data : $form.serializeArray(),dataType : "json",cache : false,success : function(json) {
$("#pageGrid").footerData("set",{
image_str : "支付总花费:",order_price : json.message
});
},error : YUNM.ajaxError
});
if ($.fn.ajaxTodo) {
$("a[target=ajaxTodo]",$("#pageGrid")).ajaxTodo();
}
// dialog
if ($.fn.ajaxTodialog) {
$("a[target=dialog]",$("#pageGrid")).ajaxTodialog();
}
},};
initEnv(jqOption);
});
一点都不熟悉jqGrid的同学,建议先看jqGrid的demo,以及jqGrid的官方文档,当然了,对于已经熟悉jqGrid的同学,doc和demo肯定是必看的。 以上文件列出的属性非常多,对于jqGrid,我不做过多的介绍,本篇的主旨主要来介绍如何将jqGrid嵌入到bootstrap,那么重点就不在于介绍jqGrid上,我只介绍几个关键点:
③、jqGrid在bootstrap中的模块化②中我们注意到initEnv方法,那么这个方法内部就是专门针对jqGrid做的模块化封装工作。 initEnv方法 function initEnv(jqOption) {
$(window).resize(function() {
initLayout();
});
initUI(null,jqOption);
}
该方法中,我们将会看到initLayout方法和initUI方法,具体内容稍候介绍。 initLayout function initLayout() {
$("table[rel=jqgridForm]").each(function() {
var rel = $(this).attr("rel");
if (rel) {
var $form = $("#" + rel);
var tableWidth = $form.width();
$(this).setGridWidth(tableWidth,true);
}
});
}
也就是说,在窗口缩放的时候,我们为jqGrid重新绘制宽度,使其自适应于bootstrap的响应式布局。使用的方法就是jqGrid的setGridWidth方法。 initUI function initUI(_box,jqOption) {
var $p = $(_box || document);
if (jqOption) {
YUNM.debug("初始化jqgrid");
var $form = $("#" + $("#pageGrid").attr("rel"));
YUNM.debug(YUNM.array2obj($form.serializeArray()));
// 初始化
var op = $.extend({
url : $form.attr("action"),postData : YUNM.array2obj($form.serializeArray()),},jqOption);
$("#pageGrid").jqGrid(op);
// 检索按钮
$("#searchBtn",$form).click(function() {
$("#pageGrid").jqGrid('setGridParam',{
url : $form.attr("action"),page : 1,});
$("#pageGrid").trigger("reloadGrid");
});
// toolbar,将button的圆角去掉
$(".btn",$form).each(function() {
var $this = $(this);
$this.css({
"border-radius" : "0px","border-bottom" : "0",});
});
}
}
array2obj : function(array) {
var params = $({});
$.each(array,function(i) {
var $param = $(this)[0];
params.attr($param.name,$param.value);
});
return params[0];
},
如果你曾看过我之前的系列文章,对于initUi方法就不会太陌生,熟悉dwz的朋友,自然也不会陌生,我项目中的大部分模板还是依赖于dwz,谢谢这些前辈们。
④ 、jqGrid的数据操作数据操作部分,我认为包含有 检索参数传递、分页排序参数传递、sql语句的编写。 关于参数传递,前端的参数封装在③中已有介绍,我们来看一看controller中如何处理数据的。 首先,我们来定义PageGrid,也就是jqGrid中xmlReader的数据源。 package com.honzh.common.page;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("pageGrid")
@SuppressWarnings("rawtypes")
public class PageGrid {
private int page;
private int total;
private int records;
private List data;
public int getPage() {
return this.page;
}
public void setPage(int page) {
this.page = page;
}
public int getTotal() {
return this.total;
}
public void setTotal(int total) {
this.total = total;
}
public int getRecords() {
return this.records;
}
public void setRecords(int records) {
this.records = records;
}
public List getData() {
return this.data;
}
public void setData(List data) {
this.data = data;
}
}
项目中需要xstream.jar,自行下载。 XStreamComponent.java package com.honzh.common.page;
import org.apache.commons.lang.StringUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.mapper.DefaultMapper;
import com.thoughtworks.xstream.mapper.XStream11XmlFriendlyMapper;
public class XStreamComponent {
private XStream xstream;
public static XStreamComponent newInstance() {
XStreamComponent xmlComponent = new XStreamComponent();
xmlComponent.alias(new Class[] { PageGrid.class });
return xmlComponent;
}
public XStreamComponent() {
this.xstream = new XStream(new DomDriver());
}
public String toXML(Object obj) {
return this.xstream.toXML(obj);
}
public String toPageXML(Object obj) {
registerConverter(new MapCustomConverter(new DefaultMapper(XStream11XmlFriendlyMapper.class.getClassLoader())));
return toXML(obj);
}
public Object fromPageXML(String xml) {
registerConverter(new MapCustomConverter(new DefaultMapper(XStream11XmlFriendlyMapper.class.getClassLoader())));
return fromXML(xml);
}
public Object fromXML(String xml) {
return this.xstream.fromXML(xml);
}
@SuppressWarnings("rawtypes")
public void processAnnotations(Class type) {
this.xstream.processAnnotations(type);
}
@SuppressWarnings("rawtypes")
public void processAnnotations(Class[] types) {
this.xstream.processAnnotations(types);
}
@SuppressWarnings("rawtypes")
public void alias(String name,Class type) {
this.xstream.alias(name,type);
}
@SuppressWarnings("rawtypes")
public void alias(Class[] types) {
for (Class type : types) {
String className = type.getName();
try {
String[] classNames = StringUtils.split(className,".");
this.xstream.alias(classNames[(classNames.length - 1)],type);
} catch (Exception ex) {
this.xstream.alias(className,type);
}
}
}
public void registerConverter(Converter converter) {
this.xstream.registerConverter(converter);
}
@SuppressWarnings("rawtypes")
public void useAttributeFor(Class definedIn,String fieldName) {
this.xstream.useAttributeFor(definedIn,fieldName);
}
}
主要将pageGrid封装为xml对象,进而传递会前端。 MapCustomConverter.java package com.honzh.common.page;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;
public class MapCustomConverter extends AbstractCollectionConverter {
public MapCustomConverter(Mapper mapper) {
super(mapper);
}
@SuppressWarnings("rawtypes")
public boolean canConvert(Class type) {
return (type.equals(HashMap.class)) || (type.equals(Hashtable.class))
|| (type.getName().equals("java.util.LinkedHashMap"))
|| (type.getName().equals("sun.font.AttributeMap"));
}
@SuppressWarnings({ "rawtypes" })
public void marshal(Object source,HierarchicalStreamWriter writer,MarshallingContext context) {
Map map = (Map) source;
for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
writer.startNode(entry.getKey() == null ? "null" : entry.getKey().toString());
writer.setValue(entry.getValue() == null ? "" : entry.getValue().toString());
writer.endNode();
}
}
@SuppressWarnings("rawtypes")
public Object unmarshal(HierarchicalStreamReader reader,UnmarshallingContext context) {
Map map = (Map) createCollection(context.getRequiredType());
populateMap(reader,context,map);
return map;
}
@SuppressWarnings({ "rawtypes","unchecked" })
protected void populateMap(HierarchicalStreamReader reader,UnmarshallingContext context,Map map) {
while (reader.hasMoreChildren()) {
reader.moveDown();
Object key = reader.getNodeName();
Object value = reader.getValue();
map.put(key,value);
reader.moveUp();
}
}
}
主要将数据库中获取的hashmap转换为标准的xml格式数据。 BaseConditionVO.java package com.honzh.common.persistence;
import java.util.HashMap;
import java.util.Map;
import org.apache.ibatis.session.RowBounds;
/** * 分页查询时的参数设置类.<br> * * <P> * 1.PAGE_SHOW_COUNT──当然默认一页显示10。<br> * 2.pageNum──第几页。<br> * 3.numPerPage──一页显示多少,为空时,显示PAGE_SHOW_COUNT。<br> * 4.totalCount──总共数目。totalCount/numPerPage=多少页<br> * 5.orderField──排序的列。<br> * 6.orderDirection──排序的方向。 * </P> */
public class BaseConditionVO {
public final static int PAGE_SHOW_COUNT = 50;
private int pageNum = 1;
private int numPerPage = 0;
private long totalCount = 0;
private String orderField = "";
private String orderDirection = "";
/** * @Fields ps : 对参数类型进行封装. */
private Map<String,Object> mo = new HashMap<String,Object>();
public int getPageNum() {
return pageNum;
}
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
}
public int getNumPerPage() {
return numPerPage > 0 ? numPerPage : PAGE_SHOW_COUNT;
}
public void setNumPerPage(int numPerPage) {
this.numPerPage = numPerPage;
}
public String getOrderField() {
return orderField;
}
public void setOrderField(String orderField) {
this.orderField = orderField;
}
public String getOrderDirection() {
return "desc".equals(orderDirection) ? "desc" : "asc";
}
public void setOrderDirection(String orderDirection) {
this.orderDirection = orderDirection;
}
public long getTotalCount() {
return totalCount;
}
public void setTotalCount(long totalCount) {
this.totalCount = totalCount;
}
public int getStartIndex() {
int pageNum = this.getPageNum() > 0 ? this.getPageNum() - 1 : 0;
return pageNum * this.getNumPerPage();
}
public RowBounds createRowBounds() {
RowBounds ro = new RowBounds(this.getStartIndex(),this.getNumPerPage());
return ro;
}
/** * @Title: addParams * @Description: 添加查询条件 * @param key * @param value */
public void addParams(String key,Object value) {
this.getMo().put(key,value);
}
/** * @Title: getParams * @Description: 获取查询条件 * @param key * @return */
public Object getParams(String key) {
return this.getMo().get(key);
}
/** * @return the mo */
public Map<String,Object> getMo() {
return mo;
}
/** * @param mo * the mo to set */
public void setMo(Map<String,Object> mo) {
this.mo = mo;
}
@Override
public String toString() {
return "条件:" + pageNum + "," + numPerPage + "," + totalCount + "," + orderField + "," + orderDirection + ","
+ mo;
}
}
分页的查询数据对象,包括分页、排序、检索域。 protected BaseConditionVO getBaseConditionVOForTable() {
BaseConditionVO vo = new BaseConditionVO();
// 分页的参数
int currentPage = getParaToInt("page");
int sizes = getParaToInt("rows");
String sortOrder = getPara("sord");
String sortCol = getPara("sidx");
vo.setNumPerPage(sizes);
vo.setPageNum(currentPage);
vo.setOrderField(sortCol);
vo.setOrderDirection(sortOrder);
return vo;
}
将jqGrid传递的参数转换为BaseConditionVO分页查询对象。 protected void renderXml(HttpServletResponse res,String xmlResponse) {
try {
res.setCharacterEncoding("UTF-8");
res.setHeader("Content-type","text/xml");
PrintWriter out = res.getWriter();
out.print(xmlResponse);
if (out != null) {
out.close();
}
} catch (IOException e) {
logger.error(e.getMessage());
logger.error(e.getMessage(),e);
}
}
将xml写入到输出流中。 定义完了这些基础的对象,接下来,我们就要着手获取数据和传递数据了。 @SuppressWarnings("rawtypes")
@RequestMapping(value = "datablePayDealOrdersList")
public void datablePayDealOrdersList(HttpServletResponse response) {
try {
logger.debug("获取我支付的订单");
XStreamComponent xstreamComponent = XStreamComponent.newInstance();
// 获取列表参数
BaseConditionVO vo = getBaseConditionVOForTable();
vo.addParams("name",getPara("name"));
logger.debug("我支付的订单查询" + vo);
// 我创建的项目
List myDealOrders = dealOrderService.getByIssueUid(vo,vo.createRowBounds());
Long count = dealOrderService.searchIssueTotalCount(vo);
String xmlResponse = xstreamComponent.toPageXML(createPageGrid(myDealOrders,vo,count.intValue()));
renderXml(response,xmlResponse.replaceAll("__","_"));
} catch (UncategorizedSQLException e) {
logger.error(e.getMessage());
logger.error(e.getMessage(),e);
renderXml(response,Constants.QUERY_ERROR);
} catch (Exception e) {
logger.error(e.getMessage());
logger.error(e.getMessage(),Constants.SERVER_ERROR);
}
}
我们来详细说明一下: 最后,我们来介绍,通过mybatis如何获取分页数据。 mapper.java package com.honzh.biz.database.mapper;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import org.apache.ibatis.session.RowBounds;
import com.honzh.common.persistence.BaseConditionVO;
public interface DealOrderMapper {
@SuppressWarnings("rawtypes")
List<HashMap> getByIssueUid(BaseConditionVO vo,RowBounds createRowBounds);
}
想mapper.xml传递的两个对象,分别是BaseConditionVO 还有分页的RowBounds ,xml中sql就会自动分页。 mapper.xml <select id="getByIssueUid" resultType="hashmap" parameterType="map">
select * from daa
WHERE is_delete=0
<if test="mo.name != null and mo.name != ''">
and y.name like CONCAT('%','${mo.name}','%')
</if>
<choose>
<when test="orderField !=null and orderField !=''">
ORDER BY ${orderField} <if test="orderDirection != null and orderDirection != ''">${orderDirection}</if>
</when>
<otherwise>
order by d.order_time DESC
</otherwise>
</choose>
</select>
到此为止,整篇的Bootstrap嵌入jqGrid就圆满结束了,ok,使你的table牛逼起来吧!
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |