bootstrap table 服务端搜索/分页/异步刷新

最近项目中用到了很多的Table,在jsp中构建的话太过繁琐,不宜与后续dom的操作。所以特意研究了一下Bootstrap Table这个插件!!

Java Json包 https://github.com/FasterXML/jackson

插件地址:Bootstrap Table

使用该插件需要Jquery与Bootstrap支持

Html部分

<!DOCTYPE html>
<html lang="en">
 
<head>
	<meta charset="UTF-8">
	<title>Deomo</title>
	<link rel="stylesheet" href="/assets/css/bootstrap.min.css" />
	<link rel="stylesheet" href="/assets/css/bootstrap-table.min.css">
</head>
 
<body>
	<!--查询窗体-->
	<div class="widget-content">
		<form method="post" class="form-horizontal" id="eventqueryform">
			<input type="text" class="span3" name="eventName" placeholder="事件名称"> <input type="text" class="span2" name="status" placeholder="灾情状态"> 
			<input type="text" class="span3" name="location" placeholder="发现位置">
			<div data-date="" class="input-append date datepicker" data-date-format="yyyy-mm-dd">
				<input type="text" class="span10" name="startdate" placeholder="起始日期"> <span class="add-on"><i class="icon-th"></i></span>
			</div>
			<div data-date="" class="input-append date datepicker" data-date-format="yyyy-mm-dd">
				<input type="text" class="span10" name="enddate" placeholder="结束日期"> <span class="add-on"><i class="icon-th"></i></span>
			</div>
			<input type="button" class="btn btn-default span1" id="eventquery" value="查询">
		</form>
	</div>
 
	<div class="widget-content">
		<!--工具条-->
		<div id="toolbar">
			<button class="btn btn-success btn-xs" data-toggle="modal" data-target="#add">添加事件</button>
		</div>
		<table id="eventTable"></table>
	</div>
 
	<script src="/assets/js/jquery.min.js"></script>
	<script src="/assets/js/bootstrap.min.js"></script>
	<script src="/assets/js/bootstrap-table.min.js"></script>
	<script src="/assets/js/bootstrap-table-zh-CN.min.js"></script>
	<script src="/assets/js/event.js"></script>
 
</body>
 
</html>

JS部分

$(document).ready(function() {
	// 初始化表格
	initTable();
});

// 表格初始化
function initTable() {
	$('#eventTable').bootstrapTable({
		method: 'post', // 向服务器请求方式
		contentType: "application/x-www-form-urlencoded", // 如果是post必须定义
		url: '/program/event/findbyitem', // 请求url
		cache: false, // 是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
		striped: true, // 隔行变色
		dataType: "json", // 数据类型
		pagination: true, // 是否启用分页
		showPaginationSwitch: false, // 是否显示 数据条数选择框
		pageSize: 5, // 每页的记录行数(*)
		pageNumber: 1, // table初始化时显示的页数
		search: false, // 不显示 搜索框
		sidePagination: 'server', // 服务端分页
		classes: 'table table-bordered', // Class样式

		// showRefresh : true, // 显示刷新按钮

		silent: true, // 必须设置刷新事件

		toolbar: '#toolbar', // 工具栏ID
		toolbarAlign: 'right', // 工具栏对齐方式

		queryParams: queryParams, // 请求参数,这个关系到后续用到的异步刷新

		columns: [{
			field: 'eventName',
			title: '事件名称',
			align: 'center'
		}, {
			field: 'date',
			title: '日期',
			align: 'center'
		}, {
			field: 'location',
			title: '发生位置',
			align: 'center'
		}, {
			field: 'mesures',
			title: '防治方案',
			align: 'center'
		}, {
			field: 'status',
			title: '灾情状态',
			align: 'center'
		}, {
			field: 'id',
			title: '操作',
			align: 'center',
			width: '280px',
			formatter: function(value, row, index) {
				var view = '查看 ';
				var update = '修改 ';
				var review = '申请专家会审 ';

				// console.log(JSON.stringify(row));

				if (row.status === '已得到控制') {
					return view + update
				} else {
					return view + update + review;
				}

			}
		}],
	});
}

// 分页查询参数,是以键值对的形式设置的
function queryParams(params) {
	return {
		eventName: $('#eventqueryform input[name=\'eventName\']').val(), // 请求时向服务端传递的参数
		status: $('#eventqueryform input[name=\'status\']').val(), // 请求时向服务端传递的参数
		location: $('#eventqueryform input[name=\'location\']').val(), // 请求时向服务端传递的参数
		startdate: $('#eventqueryform input[name=\'startdate\']').val(), // 请求时向服务端传递的参数
		enddate: $('#eventqueryform input[name=\'enddate\']').val(), // 请求时向服务端传递的参数

		limit: params.limit, // 每页显示数量
		offset: params.offset, // SQL语句偏移量
	}
}

// 搜索按钮触发事件
$(function() {
	$("#eventquery").click(function() {
		$('#eventTable').bootstrapTable(('refresh')); // 很重要的一步,刷新url!
		// console.log("/program/area/findbyItem?offset="+0+"&"+$("#areaform").serialize())
		$('#eventqueryform input[name=\'eventName\']').val('')
		$('#eventqueryform input[name=\'status\']').val('')
		$('#eventqueryform input[name=\'location\']').val('')
		$('#eventqueryform input[name=\'startdate\']').val('')
		$('#eventqueryform input[name=\'enddate\']').val('')
	});
});

表单验证(这里是应用项目中的)

// 表单验证
$(function () {
	$("#add form :input.required").each(function () {
		var $required = $("<span class='help-inline'> 必填</span>"); // 创建元素
		$(this).parent().append($required); // 然后将它追加到文档中
	});
 
	// 文本框失去焦点后
	$('#add form :input').blur(function () {
		var $parent = $(this).parent();
		
		// 验证正则
		var checktxt = /^[\u4e00-\u9fa5a-zA-Z0-9]+$/;
 
		if ($(this).is("input[name='areaName']") || $(this).is("input[name='treeType']") || $(this).is("input[name='niceTreeType']")) {
			if (!checktxt.test(this.value) || this.value.length < 2) {
				$parent.find(".help-inline").html("错误");
				$parent.find(".help-inline").css('color', 'red');
			} else {
				$parent.find(".help-inline").html("正确");
				$parent.find(".help-inline").css('color', '#62c462');
			}
		}
 
	}).keyup(function () {
		$(this).triggerHandler("blur");
	}).focus(function () {
		$(this).triggerHandler("blur");
	});
 
});

服务端实现

/**
 * sql查询语句
 */
@Override
public PageBean<EventBean> findByItem(int offset, int limit, String eventName, String status, String location, Date startDate, Date endDate) {
	PageBean<EventBean> cutBean = new PageBean<EventBean>();
 
	// 基本SQL语句
	String sql = "SELECT e.*, a.a_name FROM event AS e, area AS a WHERE e.e_areaid = a.id ";
 
	// 动态条件的SQL语句
	String itemSql = "";
 
	if (eventName != null && eventName.length() != 0) {
		itemSql += "and e.e_name like '%" + eventName + "%' ";
	}
 
	if (status != null && status.length() != 0) {
		itemSql += "and e.e_status like '%" + status + "%' ";
	}
	if (location != null && location.length() != 0) {
		itemSql += "and a.a_name like '%" + location + "%' ";
	}
	if (startDate != null) {
		itemSql += "and e.e_date >= '" + startDate + "' ";
	}
	if (endDate != null) {
		itemSql += "and e.e_date <= '" + endDate + "' ";
	}
 
	// 获取sql连接
	this.setConnection();
	try {
		ps = con.prepareStatement(sql + itemSql + "limit ?,?");
		ps.setInt(1, offset);
		ps.setInt(2, limit);
		rs = ps.executeQuery();
		while (rs.next()) {
			EventBean bean = new EventBean();
			bean.setId(rs.getInt("id"));
			bean.setEventName(rs.getString("e_name"));
			bean.setImgPath(rs.getString("e_imgpath"));
			bean.setStatus(rs.getString("e_status"));
			bean.setDetail(rs.getString("e_details"));
			bean.setFindWay(rs.getString("e_findway"));
			bean.setAreaId(rs.getInt("e_areaid"));
			bean.setDisasterType(rs.getString("e_disastertype"));
			bean.setLoss(rs.getString("e_loss"));
			bean.setInfluenceArea(rs.getString("e_infuencearea"));
			bean.setSuggestion(rs.getString("e_suggestion"));
			bean.setMesures(rs.getString("e_mesures"));
			bean.setDate(rs.getDate("e_date"));
			bean.setLocation(rs.getString("a_name"));
 
			cutBean.getRows().add(bean);
		}
		// 得到总记录数,注意,也需要添加动态条件
		ps = con.prepareStatement("SELECT count(*) as c FROM event e ,area a WHERE a.id=e.e_areaid " + itemSql);
		rs = ps.executeQuery();
		if (rs.next()) {
			cutBean.setTotal(rs.getInt("c"));
		}
	} catch (SQLException e) {
		e.printStackTrace();
	} finally {
		this.closeConnection();
	}
	return cutBean;
}
import java.util.ArrayList;
import java.util.List;
 
/**
 * 分页实体类
 */
public class PageBean<T> {
	/** 行实体类 */
	private List<T> rows = new ArrayList<T>();
	/** 总条数 */
	private int total;
 
	public PageBean() {
		super();
	}
 
	public List<T> getRows() {
		return rows;
	}
 
	public void setRows(List<T> rows) {
		this.rows = rows;
	}
 
	public int getTotal() {
		return total;
	}
 
	public void setTotal(int total) {
		this.total = total;
	}
 
}
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.codehaus.jackson.map.ObjectMapper;
 
import com.lovo.bean.AreaBean;
import com.lovo.bean.PageBean;
import com.lovo.service.IAreaService;
import com.lovo.service.impl.AreaServiceImpl;
 
/**
 * Servlet实现类
 */
@WebServlet(urlPatterns = { "/area/findbyItem" })
public class AreaFindByItemSetvlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private IAreaService service = new AreaServiceImpl();
 
	public AreaFindByItemSetvlet() {
		super();
	}
 
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}
 
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/json; charset=UTF-8");
 
		// 得到表单数据
		int offset = Integer.parseInt(request.getParameter("offset").trim());
		int limit = Integer.parseInt(request.getParameter("limit").trim());
		String areaName = request.getParameter("areaName").trim();
		String treeType = request.getParameter("treeType").trim();
		String className = request.getParameter("className").trim();
 
		// 获取客户端提交参数
//		System.out.println("=====================================");
//		Enumeration<String> en = request.getParameterNames();
//		while (en.hasMoreElements()) {
//			String el = en.nextElement().toString();
//			System.out.println(el + "=" + request.getParameter(el));
//		}
//		System.out.println("=====================================");
 
		// 调用业务组件,得到结果
		PageBean<AreaBean> pageBean = service.findByItem(offset, limit, areaName, treeType, className);
		ObjectMapper oMapper = new ObjectMapper();
		oMapper.writeValue(response.getWriter(), pageBean);
 
	}
 
}
  1. Alax 2017.05.25 9:37am

    上面bootstrap table的自定义查询那个绑定里面,$("#eventquery").click(function() {
    $(‘#eventTable’).bootstrapTable((‘refresh’)); // 很重要的一步,刷新url!
    // console.log("/program/area/findbyItem?offset="+0+"&"+$("#areaform").serialize())
    $(‘#eventqueryform input[name=\’eventName\’]’).val(”)
    $(‘#eventqueryform input[name=\’status\’]’).val(”)
    $(‘#eventqueryform input[name=\’location\’]’).val(”)
    $(‘#eventqueryform input[name=\’startdate\’]’).val(”)
    $(‘#eventqueryform input[name=\’enddate\’]’).val(”)
    });
    这样子的查询结果集如果很大的话会导致查询结果无法分页吧

    • Jalena 2017.05.25 10:08am

      这个是通过参数去请求一个json数据回来,分页不是这里控制的

      • Alax 2017.05.25 10:34am

        哦哦,我知道,因为看到你那里全部把input都置空了,每回点下一页的时候会失效。
        对了,博主知道这个bootstrapTable如何将ajax返回的json数据单独拿出来操作吗?
        比如我json数据里面返回了一个flag标志,flag如果为success表示成功,才能将后续查询结果给bootstrapTable,如果返回的是error,就让Table显示无相关查询结果。就是当返回error的时候怎样去单独地对json数据中的这个flag值进行处理,看了api没啥头绪

        • Jalena 2017.05.26 10:57am

          那你就用$.ajax去请求你的json回来,然后在回调里面把你要操作的json对象传进去呗

HTML tag cannot be used in this comment.