在開發web項目中,界面就是一個以豐富友好的樣式來展現數據的窗口,同樣的數據不用的展現形式給人不同的體驗,數據列表是數據是一種常見展現形式,對於數據列表的一個最基本的要求就是能夠實現分頁以及檢索功能。
datatables是一個不錯的基於jQuery的前端框架,它除了滿足我們基本的分頁和檢索要求還有其他高級的功能。如果對datatables的高級功能感興趣可以查看官網的API了解具體如何使用。
下面是一些datatables的常用的初始化配置。
頁面HTML代碼如下
- <table width="100%" class="display" id="dataGrid" cellspacing="0">
- <thead>
- <tr>
- <th>主鍵</th><th>序號</th><th>接口名稱</th><th>問題類型</th><th>問題內容</th><th>咨詢時間</th><th>聯系人</th><th>處理狀態</th><th>完成日期</th><th>問題細節</th><th>批次號</th><th>操作</th>
- </tr>
- </thead>
- </table>
在正式使用datatables的腳本之前我們需要做一些准備工作引入腳本文件等參考如下下面的文件中並沒有提到jquery和datatables腳本文件。這個兩個腳本文件 handlerbars是一個js模板引擎框架,fnReloadAjax是datatables的一個plugin插件。我們使用到了這兩個js腳本。
- <script src="${ctp}/js/handlebars-v4.0.5.js"></script>
- <script src="${ctp}/js/fnReloadAjax.js"></script>
- <script id="tpl" type="text/x-handlebars-template">
- {{#each func}}
- <button type="button" class="btn{{this.type}}" onclick="{{this.fn}}">{{this.name}}</button>
- {{/each}}
- </script>
下面是datatables核心的js腳本內容
- function initDataGrid(){
- var tpl = $("#tpl").html();
- //預編譯模板
- var template = Handlebars.compile(tpl);
- /**************初始化數據表格****************************/
- dataTable = $("#dataGrid").dataTable({
- "language": {
- "url": "${ctp}/jqueryplugin/datatables/js/Chinese.json"
- },
- //processing: true,
- serverSide: true,
- ajax: {
- url: '${ctp}/rest/dock/listDockQuestion',
- type: 'POST'
- },
- /**
- id,moId,createTime,processDate,questionType,
- questionContent,accessChannel,contactId,processResult,processDescription
- interfaceId,questionDetail,batchId,contactName,sequence
- */
- "columns": [
- { "data": "id","targets": -1,"visible": false },
- { "data": "sequence","targets": 0 },
- { "data": "interfaceId","targets": 1 },
- { "data": "questionType" ,"targets": 2},
- { "data": "questionContent","targets": 3 },
- { "data": "processDate" ,"targets": 4},
- { "data": "contactName" ,"targets": 5},
- { "data": "processResult" ,"targets": 6} ,
- { "data": "processDate" ,"targets": 7},
- { "data": "questionDetail" ,"targets": 8},
- { "data": "batchId" ,"targets": 9,"visible": false }
- ],
- //自定義功列
- "columnDefs": [
- {
- "render": function ( data, type, row ) {
- return $("#interfaceId_"+data).val();
- },
- "targets": 2
- },
- {
- "render": function ( data, type, row ) {
- return $("#questionType_"+data).val();
- },
- "targets": 3
- },
- {
- "render": function ( data, type, row ) {
- return $("#processResult_"+data).val();
- },
- "targets": 7
- },
- {
- "render": function ( data, type, row ) {
- var questionType=row['questionType'];
- return $("#TEC_PROBLEM_"+questionType+"_DETAIL_"+data).val();
- },
- "targets": 4
- },
- {
- "render": function ( data, type, row ) {
- var status=row['processResult'];
- var context =null;
- if("99"==status){
- context =
- {
- func:[
- {"name": "詳", "fn": "viewDockQuestion('"+row['id']+"')", "type": "5"}
- ]
- };
- }else{
- context =
- {
- func:[
- {"name": "辦", "fn": "updateDockQuestion('"+row['id']+"')", "type": "5"}
- ]
- };
- }
- var html = template(context);
- return html;
- },
- "targets": 11
- }
- ],
- //創建行回調函數 創建行之后
- "createdRow": function ( row, data, index ) {
- tmpData.push(data);
- }
- });
- dataGrid=dataTable;
- }
columnDefs屬性render 用來自定義表格顯示的數據,通常我們有些反顯數據時會用到,以及我們自定義一些操作寫一下function時會使用到 target 用來指向表格的哪一列。 createdRow 事件是指創建完一行之后觸發的事件,通過這一事件我們可以做些我們需要的工作。
接下來就是如何解決服務端如何分頁的問題,下面是一段Java代碼供大家進行參考,在代碼之后我會進行一個簡單描述
- @POST
- @Path("listDockQuestion")
- @Produces(MediaType.APPLICATION_JSON)
- public Object getDockQuestionList(@FormParam(value = "start") long start, @FormParam(value = "length") long length,
- @FormParam(value = "draw") String draw) {
- /**
- * { "draw": 1, "recordsTotal": 57, "recordsFiltered": 57, "data": [ { }]}
- */
- // 獲取Datatables發送的參數 必要
- // 定義查詢數據總記錄數
- // 條件過濾后記錄數 必要recordsFiltered
- // 表的總記錄數 必要 recordsTotal
- Map<String, Object> paramMap = new HashMap<String, Object>();
- paramMap.put("start", start);
- paramMap.put("length", length);
- paramMap.put("end", start + length);
- Map<String, Object> respMap = new HashMap<String, Object>();
- // respMap.put("draw", "1");
- Long sum = dockService.countDockQuestion(paramMap);
- respMap.put("recordsTotal", sum);
- respMap.put("recordsFiltered", sum);
- respMap.put("data", dockService.listDockQuestion(paramMap));
- return respMap;
- }
{ "draw": 1, "recordsTotal": 57, "recordsFiltered": 57, "data": [ { }]} 是要返回的json數據格式,datatables向服務端傳的參數中兩個重要參數是我們分頁使用到的,(start +1) 是從數據庫中的哪一行開始取值,如果要去第11行的數據開始取值,start會傳入10,而length是指要取多少行數據,這對於mysql數據的分頁寫sql非常方便只需要在自己SELECT語句之后加上 LIMIT start, length 。draw是請求的序號,start是數據的偏移量,length是需要返回的最大數據條數
下面一段代碼是表格異步刷新的插件fnReloadAjax代碼
- /**
- * By default DataTables only uses the sAjaxSource variable at initialisation
- * time, however it can be useful to re-read an Ajax source and have the table
- * update. Typically you would need to use the `fnClearTable()` and
- * `fnAddData()` functions, however this wraps it all up in a single function
- * call.
- *
- * DataTables 1.10 provides the `dt-api ajax.url()` and `dt-api ajax.reload()`
- * methods, built-in, to give the same functionality as this plug-in. As such
- * this method is marked deprecated, but is available for use with legacy
- * version of DataTables. Please use the new API if you are used DataTables 1.10
- * or newer.
- *
- * @name fnReloadAjax
- * @summary Reload the table's data from the Ajax source
- * @author [Allan Jardine](http://sprymedia.co.uk)
- * @deprecated
- *
- * @param {string} [sNewSource] URL to get the data from. If not give, the
- * previously used URL is used.
- * @param {function} [fnCallback] Callback that is executed when the table has
- * redrawn with the new data
- * @param {boolean} [bStandingRedraw=false] Standing redraw (don't changing the
- * paging)
- *
- * @example
- * var table = $('#example').dataTable();
- *
- * // Example call to load a new file
- * table.fnReloadAjax( 'media/examples_support/json_source2.txt' );
- *
- * // Example call to reload from original file
- * table.fnReloadAjax();
- */
- jQuery.fn.dataTableExt.oApi.fnReloadAjax = function ( oSettings, sNewSource, fnCallback, bStandingRedraw )
- {
- // DataTables 1.10 compatibility - if 1.10 then `versionCheck` exists.
- // 1.10's API has ajax reloading built in, so we use those abilities
- // directly.
- if ( jQuery.fn.dataTable.versionCheck ) {
- var api = new jQuery.fn.dataTable.Api( oSettings );
- if ( sNewSource ) {
- api.ajax.url( sNewSource ).load( fnCallback, !bStandingRedraw );
- }
- else {
- api.ajax.reload( fnCallback, !bStandingRedraw );
- }
- return;
- }
- if ( sNewSource !== undefined && sNewSource !== null ) {
- oSettings.sAjaxSource = sNewSource;
- }
- // Server-side processing should just call fnDraw
- if ( oSettings.oFeatures.bServerSide ) {
- this.fnDraw();
- return;
- }
- this.oApi._fnProcessingDisplay( oSettings, true );
- var that = this;
- var iStart = oSettings._iDisplayStart;
- var aData = [];
- this.oApi._fnServerParams( oSettings, aData );
- oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aData, function(json) {
- /* Clear the old information from the table */
- that.oApi._fnClearTable( oSettings );
- /* Got the data - add it to the table */
- var aData = (oSettings.sAjaxDataProp !== "") ?
- that.oApi._fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ) : json;
- for ( var i=0 ; i<aData.length ; i++ )
- {
- that.oApi._fnAddData( oSettings, aData[i] );
- }
- oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
- that.fnDraw();
- if ( bStandingRedraw === true )
- {
- oSettings._iDisplayStart = iStart;
- that.oApi._fnCalculateEnd( oSettings );
- that.fnDraw( false );
- }
- that.oApi._fnProcessingDisplay( oSettings, false );
- /* Callback user function - for event handlers etc */
- if ( typeof fnCallback == 'function' && fnCallback !== null )
- {
- fnCallback( oSettings );
- }
- }, oSettings );
- };
下面的腳本是如何調用該插件來實現datatables異步刷新
- dataGrid.fnReloadAjax();