datatable.js 服務端分頁+fixColumns列固定

前言

  記得仍是15年的時候,工做須要,獨自寫後臺管理系統。。記得那時候,最讓我頭疼的不是後臺邏輯,而是數據的列表展現。 列不少的時候,頁面顯示問題;分頁樣式問題;表格樣式問題;數據加載...不少細節的問題,費時,並且老是達不到我想要的效果...也是那個時候,第一次接觸了datatable.js插件,只須要簡單的修改配置值,就能夠改變表格的方方面面,真的是很是好的體驗。。。javascript

  不過,由於一些歷史緣由,和時間問題,那時候對 ajax加載+服務端分頁+頁面刷新,仍然是一直很迷迷糊糊...恰好最近工做中須要作一個列表管理頁,因此就很天然的選擇了datatable.js,而且總算把  ajax加載數據+服務端分頁+reload這套流程弄通。也許還有不少種方案能夠達到效果,但至少這個是確定可行的.css

  樣式是基於bootstrap風格.html

正文

一.前端

  須要引的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則爲我前端自定義的附加參數。java

   Page是List<T>泛型集合,是開源項目PageHelper-mybatis中的類。jquery

   服務端返回給前端的json數據也有格式要求,具體見AjaxListResponseDTO類定義.ajax

/**
 * 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文件引用json

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

  其次,在配置項中添加一項:bootstrap

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;
    }

    而後,頁面的頁碼顯示就正確了(如圖):

 

 

 

本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利;

本文出自:博客園--別問是誰

相關文章
相關標籤/搜索