dataTable是个非常强大的显示数据表插件。不仅如此,它还可以结合TableTools导出数据,可以导出的类型有 csv,excel,pdf.而且还可以copy,print.
我在项目中用到了这个插件,折腾了好久。遂记录之。
需求描述:需要从sAjaxSource这个属性指定的url获取json数据,然后在显示出来。
部分页面:
<table id="example"> <thead> <tr> <th>教师编号</th> <th>教师姓名</th> <th>所属学院</th> <th>管理对象</th> <th>电话</th> <th>邮箱</th> <th>操作</th> </tr> </thead> <tbody> </tbody> <tfoot> <tr> <th>教师编号</th> <th>教师姓名</th> <th>所属学院</th> <th>管理对象</th> <th>电话</th> <th>邮箱</th> <th>操作</th> </tr> </tfoot> </table>
该页面的部分js:
$(document).ready(function () { dt = $('#example').dataTable({ "bProcessing": true, "bServerSide": true, "bSort": false, "sAjaxSource": "xxxx",//这是要请求json数据的url "oLanguage": { "sLengthMenu": "每页显示 _MENU_ 条记录", "sZeroRecords": "对不起,查询不到任何相关数据", "sInfo": "当前显示 _START_ 到 _END_ 条,共 _TOTAL_ 条记录", "sInfoEmtpy": "找不到相关数据", //"sInfoFiltered": "数据表中共为 _MAX_ 条记录", "sProcessing": "正在加载中...", "sSearch": "搜索", "sInfoEmpty": "显示 0 至 0 共 0 项", "oPaginate": { "sFirst": "第一页", "sPrevious": "上一页 ", "sNext": "下一页 ", "sLast": "末页 " } }, "aoColumns": [ { "mData": "teacher_id", "sClass": "center" }, { "mData": "teacher_name", "sClass": "center" }, { "mData": "organization_name", "sClass": "center" }, { "mData": "manageOrganization_name", "sClass": "center" }, { "mData": "teacher_phone", "sClass": "center" }, { "mData": "teacher_email", "sClass": "center" }, { "mData": "admin_id", "sClass": "center" } ], "aoColumnDefs": [ { "aTargets": [6], "mData": "操作", "mRender": function (data, type, full) { return '<a href="javascript:void(0);" class="delete" tag=' + data + '>删除</a>'; } } ], "fnServerData": fnDataTablesPipeline });
用红色显示的aoColumns 是说明请求的json数据是如何对应于表中的单元格。在没指定之前,遇到了各种各样的问题,比如有
Datatables warning(table id = 'example'): cannot reinitialise data table
DataTables warning (table id = 'xxxx'): Requested unknown parameter 'xx' from the data source for row 0
不过上段的js要依赖于另一个js文件。该js文件是我从网上获取并自己做了些修改。它的作用有两个:第一,请求的数据可以加倍,第二,加倍的数据是缓存的,因此达到了预加载的功能。
贴上 DataTableServerSideData.js:

//前台与后台交互数据,并实现分页的功能 var oCache = { iCacheLower: -1, bNeedServer: false, //为true则开启缓存模式 iPipe: 1, //加载数据的倍数 }; function isNeedServer(flag) { oCache.bNeedServer = flag; } function setIpipe(pipe) { if ("/^\d&/".test(pipe)) { oCache.iPipe = pipe; } } function fnSetKey(aoData, sKey, mValue) { for (var i = 0, iLen = aoData.length ; i < iLen ; i++) { if (aoData[i].name == sKey) { aoData[i].value = mValue; } } } function fnGetKey(aoData, sKey) { for (var i = 0, iLen = aoData.length ; i < iLen ; i++) { if (aoData[i].name == sKey) { return aoData[i].value; } } return null; } function fnDataTablesPipeline(sSource, aoData, fnCallback, oSettings) { //var iPipe = 2; /* Ajust the pipe size */ // var bNeedServer = false; var sEcho = fnGetKey(aoData, "sEcho"); var iRequestStart = fnGetKey(aoData, "iDisplayStart"); var iRequestLength = fnGetKey(aoData, "iDisplayLength"); var iRequestEnd = iRequestStart + iRequestLength; oCache.iDisplayStart = iRequestStart; /* outside pipeline? */ if (oCache.iCacheLower < 0 || iRequestStart < oCache.iCacheLower || iRequestEnd > oCache.iCacheUpper) { oCache.bNeedServer = true; } /* sorting etc changed? */ if (oCache.lastRequest && !oCache.bNeedServer) { for (var i = 0, iLen = aoData.length ; i < iLen ; i++) { if (aoData[i].name != "iDisplayStart" && aoData[i].name != "iDisplayLength" && aoData[i].name != "sEcho") { if (aoData[i].value != oCache.lastRequest[i].value) { oCache.bNeedServer = true; break; } } } } /* Store the request for checking next time around */ oCache.lastRequest = aoData.slice(); //bNeedServer = true; if (oCache.bNeedServer) { if (iRequestStart < oCache.iCacheLower) { iRequestStart = iRequestStart - (iRequestLength * (oCache.iPipe - 1)); if (iRequestStart < 0) { iRequestStart = 0; } } oCache.iCacheLower = iRequestStart; oCache.iCacheUpper = iRequestStart + (iRequestLength * oCache.iPipe); oCache.iDisplayLength = fnGetKey(aoData, "iDisplayLength"); fnSetKey(aoData, "iDisplayStart", iRequestStart); fnSetKey(aoData, "iDisplayLength", iRequestLength * oCache.iPipe); oSettings.jqXHR = $.getJSON(sSource, aoData, function (json) { /* Callback processing */ oCache.lastJson = jQuery.extend(true, {}, json); if (oCache.iCacheLower != oCache.iDisplayStart) { json.aaData.splice(0, oCache.iDisplayStart - oCache.iCacheLower); } json.aaData.splice(oCache.iDisplayLength, json.aaData.length); fnCallback(json); }); } else { json = jQuery.extend(true, {}, oCache.lastJson); json.sEcho = sEcho; /* Update the echo for each response */ json.aaData.splice(0, iRequestStart - oCache.iCacheLower); json.aaData.splice(iRequestLength, json.aaData.length); fnCallback(json); return; } }
至此,使用sAjaxSource请求数据完成了。
有些时候,需要删除表中的某行数据。如果想像删除普通表一样删除tr,我试了貌似不得行。只能利用dataTable提供的方法fnDeleteRow删除才行。
贴上小段代码:
//回调函数 function ProcessJson(data) { if (data == "false") { alert("程序错误!"); } else { //提交成功 /* delete row which has been checked */ var anSelected = dt.$('tr.row_selected'); if (anSelected.length !== 0) { dt.fnDeleteRow(anSelected[0]); } } }
注意,红色标识的是获取class为row_selected一行。如果想试着通过$(this).parent().parent()获取点击的tr,那得传入点击的this作用域才行。不然怎么获取得到呢?因为若想删除,首先得通过后台将数据表中的某条记录删除,删除成功了才能删除表中的数据吧。所以后来我在处理点击删除按钮时为tr加上一个class,所以在回调函数中就能通过dt.$('tr.row_selected')获取当时选中的行了。
之前说过,dataTable可以结合TableTools导出excel,csv,pdf格式的文件,不过可惜的是,当导出pdf时会出现中文乱码,查了很多资料,pdf不支持utf8格式。。如果你知道,希望能告诉我呀~
若要导出数据呢,可以在datatable()中添加:
"oTableTools": { "sSwfPath": "/CSS/swf/copy_csv_xls_pdf.swf", "aButtons": [ { "sExtends": "xls", "sButtonText": "导出excel格式", "mColumns": [1,2,3,4,5,6,7] }, { "sExtends": "csv", "sButtonText": "导出csv格式", "mColumns": [1, 2, 3, 4, 5, 6, 7] }, ] }
那么在页面中就会出现按钮了,点击按钮,就会出来弹出框,这样就可以保存文件了。不过需要注意的是:第一,sSwfPath的地址需要正确,如果不正确是不会成功的哦~。第二,你需要引入的js文件有:
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.dataTables.min.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/TableTools.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Scripts/ZeroClipboard.js")"></script>
第三,需要引入css文件:<link rel="stylesheet" href="@Url.Content("~/CSS/TableTools.css")"/>.你不引入试试,你会像我一样花了一个多小时google做无用功-_-!!
最后,附上官网地址:
TableTools example地址:http://datatables.net/extras/tabletools/examples
需要注意的是:在官网上的TableTools example中操作导出,是能够成功的。但是,,如果下载到本地,然后通过浏览器打开html文件进行操作(也就是浏览器地址栏出现E://xxx/xxx/),是不会成功的。外国一个很牛的人Allen说是flash setting的安全问题T_T~