前言

  记得还是15年的时候,工作需要,独自写后台管理系统。。记得那时候,最让我头疼的不是后台逻辑,而是数据的列表展示。 列很多的时候,页面显示问题;分页样式问题;表格样式问题;数据加载...很多细节的问题,费时,而且总是达不到我想要的效果...也是那个时候,第一次接触了datatable.js插件,只需要简单的修改配置值,就可以改变表格的方方面面,真的是非常好的体验。。。

  不过,因为一些历史原因,和时间问题,那时候对 ajax加载+服务端分页+页面刷新,仍然是一直很迷迷糊糊...刚好最近工作中需要做一个列表管理页,所以就很自然的选择了datatable.js,并且总算把  ajax加载数据+服务端分页+reload这套流程弄通。也许还有很多种方案可以达到效果,但至少这个是肯定可行的.

  样式是基于bootstrap风格.

正文

一.前端

  需要引的js文件

<!-- datatables样式和bootstrap支持样式 -->
<link rel="stylesheet" type="text/css" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/plug-ins/28e7751dbec/integration/bootstrap/3/dataTables.bootstrap.css"> <script type="text/javascript" language="javascript" src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/1.10.15/js/jquery.dataTables.min.js"></script>
<script type="text/javascript" language="javascript" src="https://cdn.datatables.net/plug-ins/28e7751dbec/integration/bootstrap/3/dataTables.bootstrap.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> <!--form ajax提交-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.2.1/jquery.form.js"></script>

  html部分

<!-- search 框start -->
<div class="container">
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="用户姓名" name="userName" id="searchUserName">
</div>
&
<div class="form-group">
<input type="text" class="form-control" placeholder="律所名" name="officeName" id="searchOfficeName">
</div>
&
<div class="form-group">
<input type="number" class="form-control" placeholder="状态" name="be_valid" id="searchValid">
</div>
<button type="button" class="btn btn-success" onclick="searchData()">搜索</button>
</form>
<form class="navbar-form navbar-right">
<button type="button" class="btn btn-primary btn-sm btn-warning" data-toggle="modal" data-target="#addModal">
新增律所
</button>
</form>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid --> </nav>
</div>
<!-- search 框end -->
<div class="container">
<table id="mytable" class="table table-striped table-bordered table-hover" cellspacing="0" width="100%" style="white-space: nowrap;">
<thead>
<tr>
<th>用户名</th>
<th>用户ID</th>
<th>邮箱</th>
<th>身份</th>
<th>律所</th>
<th>律所id</th>
<th>律所简报</th>
<th>律所创建时间</th>
<th>限制人数</th>
<th>验证码</th>
<th>状态</th>
<th>备注信息</th>
<th>操作</th>
</tr>
</thead>
<tbody></tbody>
<tfoot>
<tr>
<th>用户名</th>
<th>用户ID</th>
<th>邮箱</th>
<th>身份</th>
<th>律所</th>
<th>律所id</th>
<th>律所简报</th>
<th>律所创建时间</th>
<th>限制人数</th>
<th>验证码</th>
<th>状态</th>
<th>备注信息</th>
<th>操作</th>
</tr>
</tfoot>
</table>
</div>

  因为是服务端分页,所以我页面做了搜索框,进行自定义的参数搜索.

  js部分

<script type="text/javascript">
var oTable;
$(function(){
LoadData();
}); function searchData(){
oTable.draw(true);
// oTable.ajax.reload(null,true);
}function LoadData() {
oTable = $('#mytable').DataTable({
//sDom: 'T<"clear">lfrtip',
oLanguage: {
sZeroRecords: "对不起,查询不到任何相关数据",
sInfoEmpty: "记录数为0"
},
sScrollX: "100%",
sScrollXInner: "110%",
bScrollCollapse: false, //可滚动
bDestory: true, //数据允许清空
bServerSide: true, //服务端处理分页
bLengthChange: false, //是否允许自定义每页显示条数.
iDisplayLength: 20, //每页显示10条记录
bPaginate: true, //是否分页
//sPaginationType: "amaze", //分页样式 "full_numbers"
//bJQueryUI: true,//是否将分页样式应用到表格
bProcessing: true, //当datatable获取数据时候是否显示正在处理提示信息。
bFilter: false, //是否启用条件查询
bSearchable: false,
//bStorable: false,//是否启用列排序
//bInfo: true, //是否显示分页信息(页脚信息)
order: [[7, "desc"]], //默认按照第几列排序,从1开始
bAutoWidth: false, //自动宽度
bStateSave: true, //状态保存,使用了翻页或者改变了每页显示数据数量,会保存在cookie中,下回访问时会显示上一次关闭页面时的内容
ajax:{
dataType:'json',
type:'POST',
url: '/adminUserList',
headers: {
'token': window.localStorage.token //取localStorage中的token,用来做安全校验
},
dataSrc: "aaData",
data:function(d){
             //取搜索的参数值,在请求服务端时,附加到请求参数中
var userName=$('#searchUserName').val();
var officeName=$('#searchOfficeName').val();
var be_valid=$('#searchValid').val(); d.userName=userName;
d.officeName=officeName;
d.be_valid=be_valid;
}
},
columns: [
{
data: "name",
bSortable: false
},
{
data: "user_id",
bSortable: false
},
{
data: "email",
bSortable: false
},
{
data: "level_name",
bSortable: false
},
{
data: "office_name",
bSortable: false
},
{
data: "office_id",
bSortable: false
},
{
data: "officeBriefing",
bSortable: false
},
{ data: "office_create_time"},
{
data: "limited_num",
bSortable: false
},
{
data: "verify_code",
bSortable: false
},
{
data: "be_valid",
bSortable: false
},
{
data: "remark",
bSortable: false
},
{
data: null,
render: function (data, type, row) {
return '<button type="button" class="btn btn-primary btn-sm" onclick="editShow(\''+data.user_id+'\')">编辑</button>';
},
bSortable: false
}
]
}); }
</script>

二.后端

  java服务端代码

@ResponseBody
@RequestMapping(value = "/adminUserList",method = RequestMethod.POST)
public AjaxListResponseDTO<AppUserShowDTO> getAdminUserList(
@ApiParam(required = true, name = "start", value = "开始条数") @RequestParam Integer start,
@ApiParam(required = true, name = "length", value = "取多少条") @RequestParam Integer length,
@ApiParam(required = true, name = "userName", value = "用户名") @RequestParam String userName,
@ApiParam(required = true, name = "officeName", value = "律所名") @RequestParam String officeName,
@ApiParam(required = true, name = "be_valid", value = "状态") @RequestParam Integer be_valid,
HttpServletRequest request) throws Exception{// Map<String,String[]> paramMap=request.getParameterMap(); String[] orderTypeArr=request.getParameterValues("order[0][dir]");
String lawOfficeOrderType="";
if(null!=orderTypeArr){
lawOfficeOrderType=orderTypeArr[0];
} AjaxListResponseDTO<AppUserShowDTO> responseDTO=new AjaxListResponseDTO<>(); //datatable.js 相关参数
String[] drawStrArr=request.getParameterValues("draw");
if(null!=drawStrArr){
responseDTO.setSEcho(Integer.parseInt(drawStrArr[0]));
} Page<AppUserShowDTO> appUserShowDTOPage = authUserService.findAllUserAndLawOffice(userName,officeName,be_valid,null!=start?start:0,null!=length?length:20,lawOfficeOrderType,"超级管理员"); responseDTO.setITotalRecords((int) Math.ceil(appUserShowDTOPage.getTotal()));//实际需要传数据总数,此处值不对
responseDTO.setITotalDisplayRecords((int) Math.ceil(appUserShowDTOPage.getTotal()));
responseDTO.setAaData(appUserShowDTOPage.getResult()); return responseDTO;
}

   start(起始条数,注意,是条数而不是页数 )和length(取多少条数据)为datatable默认会传到服务端的2个参数, userName/officeName/be_valid则为我前端自定义的附加参数。

   Page是List<T>泛型集合,是开源项目PageHelper-mybatis中的类。

   服务端返回给前端的json数据也有格式要求,具体见AjaxListResponseDTO类定义.

/**
* Created by xinhuiyang on 2017/6/9.
*/
@Data
public class AjaxListResponseDTO<T>{ private Integer sEcho; private Integer iTotalRecords; private Integer iTotalDisplayRecords; private List<T> aaData;
}

  自此,就实现了带搜索功能的服务端分页效果.

三. FixColumn(固定第一列和最后一列效果)

  首先,在之前的基础上,需要添加一个js文件引用

<!-- 固定列 插件js -->
<script src="https://cdn.datatables.net/fixedcolumns/3.2.2/js/dataTables.fixedColumns.min.js"></script>

  其次,在配置项中添加一项:

oTable = $('#mytable').DataTable({
//sDom: 'T<"clear">lfrtip',
oLanguage: {
sZeroRecords: "对不起,查询不到任何相关数据",
sInfoEmpty: "记录数为0"
},
sScrollX: "100%",
sScrollXInner: "110%",
bScrollCollapse: false,
fixedColumns: { //固定列的配置项
leftColumns: 1, //固定左边第一列
rightColumns:1 //固定右边第一列
},
bDestory: true,
bServerSide: true,
.....省略......

  然后,刷新页面...至此,固定列效果就ok了。

后言

  现在的页面效果,还有2个瑕疵:

    其一是后台返回"总条数"不对,我是时间赶,来不及写查询了..大家实际使用时,自己查询一下就行,这个好解决;

    其二是前端页面,下角显示页码总数和页脚信息显示有问题(见下图),不知道当后台"总条数"准确时,会不会就ok了。我后面还会找个时间,去修复一下的...当我有解决方案时,会补充在下面的,大家有知道原因和解决方案的,也欢迎评论在下方。

  页脚图

    1.左边数字没显示出来.

    2.实际83条数据,每页20条,应该最多到5页的,但实际上,可以点任意页,只不过从第6页开始,数据都为空.      

补充

  页面显示不对的问题已经找到原因并且解决.

  原因是:后端分页时,需要返回给前端更多的信息,如总数多少,过滤后多少等,所以我代码中的AjaxListResponseDTO类就不符合后端分页时的需求了,需要改动.

    修改后的类定义为:

/**
* Created by xinhuiyang on 2017/6/9.
*/
@Data
@ApiModel
public class AjaxListResponseDTO<T>{ @ApiModelProperty("必要。上面提到了,Datatables发送的draw是多少那么服务器就返回多少。 这里注" +
"意,作者出于安全的考虑,强烈要求把这个转换为整形,即数字后再" +
"返回,而不是纯粹的接受然后返回,这是 为了防止跨站脚本(XSS)攻击。")
private Integer draw; @ApiModelProperty("必要。即没有过滤的记录数(数据库里总共记录数)")
private Integer recordsTotal; @ApiModelProperty("必要。过滤后的记录数(如果有接收到前台的过滤条件,则返回的是过滤后的记录数)")
private Integer recordsFiltered; @ApiModelProperty("必要。表中中需要显示的数据。这是一个对象数组,也可以只是" +
"数组,区别在于 纯数组前台就不需要用 columns绑定数据,会自动按照顺序" +
"去显示 ,而对象数组则需要使用 columns绑定数据才能正常显示。")
private List<T> aaData; @ApiModelProperty("可选。你可以定义一个错误来描述服务器出了问题后的友好提示")
private String error;
}

    相应的,controller部分代码,也要给对应的属性附上正确的值,改动后代码如下:

    @ResponseBody
@RequestMapping(value = "/adminUserList",method = RequestMethod.POST)
public AjaxListResponseDTO<AppUserShowDTO> getAdminUserList(
@ApiParam(required = true, name = "start", value = "开始条数") @RequestParam Integer start,
@ApiParam(required = true, name = "length", value = "取多少条") @RequestParam Integer length,
@ApiParam(required = true, name = "userName", value = "用户名") @RequestParam String userName,
@ApiParam(required = true, name = "officeName", value = "律所名") @RequestParam String officeName,
@ApiParam(required = true, name = "be_valid", value = "状态") @RequestParam Integer be_valid,
HttpServletRequest request) throws Exception{ // Map<String,String[]> paramMap=request.getParameterMap(); String[] orderTypeArr=request.getParameterValues("order[0][dir]");
String lawOfficeOrderType="";
if(null!=orderTypeArr){
lawOfficeOrderType=orderTypeArr[0];
} AjaxListResponseDTO<AppUserShowDTO> responseDTO=new AjaxListResponseDTO<>(); //datatable.js 相关参数
String[] drawStrArr=request.getParameterValues("draw");
if(null!=drawStrArr){
responseDTO.setDraw(Integer.parseInt(drawStrArr[0]));
}
int totalCountBeforeFilter=authUserService.countUserByLevel("超级管理员"); Page<AppUserShowDTO> appUserShowDTOPage = authUserService.findAllUserAndLawOffice(userName,officeName,be_valid,null!=start?start:0,null!=length?length:20,lawOfficeOrderType,"超级管理员"); responseDTO.setAaData(appUserShowDTOPage.getResult());
responseDTO.setRecordsTotal(totalCountBeforeFilter);
responseDTO.setRecordsFiltered((int) appUserShowDTOPage.getTotal()); return responseDTO;
}

    然后,页面的页码显示就正确了(如图):

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利;

本文出自:博客园--别问是谁

 

datatable.js 服务端分页+fixColumns列固定的更多相关文章

  1. jquery.dataTables的探索之路-服务端分页配置

    最近闲来无事想研究下数据表格,因为之前接触过layui和bootstrap的数据表格,本着能学多少学多少的学习态度,学习下dataTables的服务端分页配置.特与同学们一块分享下从中遇到的问题和解决 ...

  2. asp.net mvc bootstrap datatable 服务端分页

    datatable 服务端分页 因项目需求变动,需处理大量数据,更改成服务端分页,自己两天的学习笔记 先上图[ jqueryui风格] 前端代码: @{ Layout = null;} <!DO ...

  3. asp.net mvc bootstrap datatable 服务端分页 更新槽糕的代码【1】

    datatable 服务端分页 因项目需求变动,需处理大量数据,更改成服务端分页,自己两天的学习笔记 datatable 1.10.7 百度云下载  密码:0ea1 先上图[ jqueryui风格] ...

  4. ThinkPHP整合datatables实现服务端分页

    最近做东西有一个需求,因为数据量很大,在这里我决定使用datatables的服务端分页,同时还需要传递查询条件到服务端.在网上搜索的大部分文章都感觉有些误差,于是自己封装了一下,主要配置/工具为: 服 ...

  5. BootStrap Table和Mybatis Plus实现服务端分页

    一.后台java代码(Mybatis Plus分页) (1)Mybatis Plus分页的配置,在mybatis的xml文件中增加如下配置(Mybatis Plus官方文档:http://baomid ...

  6. 基于SpringMVC+Bootstrap+DataTables实现表格服务端分页、模糊查询

    前言 基于SpringMVC+Bootstrap+DataTables实现数据表格服务端分页.模糊查询(非DataTables Search),页面异步刷新. 说明:sp:message标签是使用了S ...

  7. BootStrap table服务端分页

    涉及到的内容: 1.bootstrap-table插件: 2.mybatisplus分页查询: 3.spring封装对象匹配bootstrap-table插件格式: 4.sql查询隐藏手机号中间四位. ...

  8. Angularjs的真分页,服务端分页,后台分页的解决方案

    背景:项目的框架使用的是Angularjs,在做数据展示的时候,使用的是ng-table.用过ng-table的人都知道,他是自带分页的,默认分页方式是假分页.也就是一口气把所有的数据从数据库里取出来 ...

  9. AngularJS中实现服务端分页

    这个教程将介绍在AngularJS应用中的服务端分页处理.在任何涉及到列表或表格数据的应用中都可能会用到分页. 概念 当我们处理异步分页时,每次只从服务器上获取一页数据.也就是说当用户点击第二页,就只 ...

随机推荐

  1. SSMybatis整合(二) -- 加入SpringMVC进行多表级联操作

    ---上节课我们讲了Mybatis的单表增删改查,关于代码我注释的比较详细,我相信初学的小伙伴还是多少能有一些收获的. - 第一集传送门:http://blog.csdn.net/jacxuan/ar ...

  2. win 2003 / IIS6 部署网站的时候,文件IO操作、删除项目文件, 会导致IIS重启,Session丢失问题

    项目中经常需要打些日志(文件IO读写操作),已记录调试.错误等信息.比较方便的有log4net等开源项目. 问题描述: 最近用win 2003 / IIS6,部署了一个2.0 的网站,在操作文件的时候 ...

  3. java中异常介绍

    一.异常概述 异常处理已经成为衡量一门语言是否成熟的标准之一,目前的主流编程语言如C++.C#.Ruby.Python等,大都提供了异常处理机制.增加了异常处理机制后的程序有更好的容错性,更加健壮. ...

  4. HKC显示器开机亮一下就不显示了

    一台HKC显示器开机显一下就黑了 最近加了一个显示器做扩展屏幕,可以不亮有问题啊     芯片坏了引起的~ 不是自己的,不能拆机啊啊   文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎留言.评论 ...

  5. Twelves Monkeys (multiset解法 141 - ZOJ Monthly, July 2015 - H)

    Twelves Monkeys Time Limit: 5 Seconds      Memory Limit: 32768 KB James Cole is a convicted criminal ...

  6. pip换国内源

    pip换国内源 1.国内常用源   阿里云 http://mirrors.aliyun.com/pypi/simple/   中国科技大学 https://pypi.mirrors.ustc.edu. ...

  7. sql server使用sql插入中文字符串乱码问题

    在插入语句前加N就行了 sb.Append(string.Format("update chapter set [content]=N'{0}' where Id ={1} ;", ...

  8. VMware安装Centos7超详细过程(图文)

    1.软硬件准备 软件:推荐使用VMwear,我用的是VMwear 12 镜像:CentOS6 ,如果没有镜像可以在阿里云下载 https://mirrors.aliyun.com/centos/ 硬件 ...

  9. Xcode中利用git源代码版本号控制

    git是一个版本号控制系统,能够通过命令行来调用,也有专门的桌面软件.这里主要介绍在Xcode中怎样利用git来进行版本号的控制. 一.创建git源 从Xcode5開始引入了使用git的一些新特性.将 ...

  10. HTTP Cache怎样计算Age

    这里的Age指的是响应头Age.以下内容有部分翻译,也有部分自己的理解.欢迎讨论. 我们用now表示当前主机的当前时间,用request_time表示缓存发起请求的时间,用response_time表 ...