Datatables 在asp.net mvc中的使用

前言

最近使用ABP(ASP.NET Boilerplate)作新項目,之前都是本身擴展一個HtmlHelper來完成同步/異步分頁,可是有個地方一直不滿意,排序太費勁。
之前接觸過一點點的Datatables,知道它的排序很是方便,點擊表頭便可排序,還支持多列排序,而後就把Datatables集成到項目裏了。javascript

Datatables簡介

Datatables(如下簡稱dt)是一款jquery表格插件。它是一個高度靈活的工具,能夠將任何HTML表格添加高級的交互功能。 點擊進入Datatables中文網css

  • 分頁,即時搜索和排序html

  • 幾乎支持任何數據源:DOM, javascript, Ajax 和 服務器處理java

  • 支持不一樣主題 DataTables, jQuery UI, Bootstrap, Foundationjquery

  • 各式各樣的擴展: Editor, TableTools, FixedColumns ……git

  • 豐富多樣的option和強大的APIgithub

  • 支持國際化web

  • 超過2900+個單元測試ajax

  • 免費開源 ( MIT license )!正則表達式

  • 更多特性請到Datatables中文網查看看

與Asp.Net Mvc(如下簡稱mvc)結合使用

本文重點講解dt在mvc(此處應該吐槽webform)中的使用。其餘語言也是差很少的用法。

初始化Datatables

引入js和css

//bootstrap的css
<link href="~/Content/bootstrap.min.css" rel="stylesheet"/>
//這裏咱們使用bootstrap的主題,其餘的請對號入座
<link href="~/Scripts/DataTables-1.10.10/media/css/dataTables.bootstrap.min.css" rel="stylesheet" />

//jquery
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
//bootstrap主題的js
<script src="~/Scripts/DataTables-1.10.10/media/js/jquery.dataTables.min.js"></script>
//核心js
<script src="~/Scripts/DataTables-1.10.10/media/js/dataTables.bootstrap.js"></script>
//自定義的js,修改dt默認的一些配置(如中文提示)
<script src="~/Scripts/DataTables.js"></script>
//DataTables.js  這是Datatables的相關知識,具體做用請求官網查看
$.extend($.fn.dataTable.defaults, {
    "dom": "<'row'<'col-sm-12'tr>>" +
            "<'row'<'col-sm-12 text-center'i>>" +
            "<'row'<'col-sm-5'l><'col-sm-7'p>>",//默認是lfrtip
    "processing": true,//加載中
    "serverSide": true,//服務器模式(★★★★★重要,本文主要介紹服務器模式)
    "searching": false,//datatables自帶的搜索
    "scrollX": true,//X滑動條
    "pagingType": "full_numbers",//分頁模式
    "ajax": {
        "type": "POST",//(★★★★★重要)
        "contentType": "application/json; charset=utf-8"
    },
    "language": {
        "processing": "加載中...",
        "lengthMenu": "每頁顯示 _MENU_ 條數據",
        "zeroRecords": "沒有匹配結果",
        "info": "顯示第 _START_ 至 _END_ 項結果,共 _TOTAL_ 項",
        "infoEmpty": "顯示第 0 至 0 項結果,共 0 項",
        "infoFiltered": "(由 _MAX_ 項結果過濾)",
        "infoPostFix": "",
        "search": "搜索:",
        "url": "",
        "emptyTable": "沒有匹配結果",
        "loadingRecords": "載入中...",
        "thousands": ",",
        "paginate": {
            "first": "首頁",
            "previous": "上一頁",
            "next": "下一頁",
            "last": "末頁"
        },
        "aria": {
            "sortAscending": ": 以升序排列此列",
            "sortDescending": ": 以降序排列此列"
        }
    }
});

初始化dt

dt支持多種數據源,在此咱們只說「服務器處理」。
服務器處理的代碼以下(有些默認配置已經在上面的DataTables.js中配置,如開啓服務器模式"serverSide": true):

<table id="area" class="table" data-order="[[0,&quot;desc&quot;]]" width="100%">
    <thead>
        <tr>
            <th data-data="Id" data-visible="false">Id</th>
            <th data-data="Name">名稱</th>
            <th data-data="Description" data-orderable="false">描述</th>
            <th data-data="PointX">X座標</th>
            <th data-data="PointY">Y座標</th>
        </tr>
    </thead>
</table>
<script>
    $(function(){
        var userTable = $('#area').DataTable({
            "ajax": {
                "url": "@Url.Action("GetDatas")",
                "data": function(data) {
                    data.Name = $("#name").val();;//此處是添加額外的請求參數
                    return JSON.stringify(data);
                }
            }
        });
    });
</script>

dataTable和DataTable的區別

1.10.x版本後,有兩種初始化的寫法, $().dataTable() 返回的是一個jQuery實例, $().DataTable() 返回的是Datatables的api實例, 若是在使用過程當中出現某某方法不存在不支持之類的,通常都是因爲是用第一種方法初始化dt,用返回的對象去調用api的方法,因此報錯誤。
dt的api實例和jquery能夠互轉 ,jquery轉api:dt.api();api轉jquery:dt.to$(); 詳細參考 api手冊

服務器端獲取Datatables的請求參數

當使用服務器處理時,dt會發送以下數據給服務器

名稱 類型 描述
draw integerJS 請求次數計數器,每次發送給服務器後又原封返回.
start integerJS 第一條數據的起始位置,好比0表明第一條數據
length integerJS 每頁顯示的條數.
search[value] stringJS 全局的搜索條件,針對於每一列( searchable須要設置爲 true )
search[regex] booleanJS 若是爲 true表明全局搜索的值是做爲正則表達式處理,爲 false則不是。
orderi integerJS i是一個數組索引,對應的是 columns,從0開始,次參數表示那一列須要排序
orderi stringJS 上面肯定了是那一列,這個肯定對應的列是什麼樣的排序方式 desc 是降序 asc升序
columnsi stringJS columns 綁定的數據源,由 columns.data 定義
columnsi stringJS columns.name 裏定義的名稱
columnsi booleanJS 標記列是否能被搜索 爲 true表明能夠,不然不能夠,這個是由 columns.searchable 控制
columnsi booleanJS 標記列是否能排序 爲 true表明能夠,不然不能夠,這個是由 columns.orderabl 控制
columnsi[value] stringJS 特定列的搜索條件
columnsi[regex] booleanJS 特定列的搜索條件是否視爲正則表達式

能夠看到,請求的參數仍是很規則的。
咱們可使用Request.Form(post方式),Request.QueryString(get方式)或者Request.Params/Request獲取請求參數,可是若是這麼作就太low了,每一個方法都要寫一大堆的Request那還不如不用呢。
幸虧,咱們有ModelBinder

使用asp.net mvc的ModelBinder(模型綁定)自定綁定請求的參數

上文講到若是使用Request的方式咱們還不如不用,那麼咱們這裏就用到了ModelBinder(其實也是對Request進行了封裝),咱們能夠用一個類還接收全部的請求參數,以下所示:

public JsonResult GetDatas(DataTablesParameters query)
{
}

下面咱們開始編寫這個類。
此處的排序只實現了單列排序,如需多列排序請自行修改

/// <summary>
    ///     DataTables參數
    /// </summary>
    public class DataTablesParameters
    {
        /// <summary>
        ///     請求次數計數器
        /// </summary>
        public int Draw { get; set; }

        /// <summary>
        ///     第一條數據的起始位置
        /// </summary>
        public int Start { get; set; }

        /// <summary>
        ///     每頁顯示的數據條數
        /// </summary>
        public int Length { get; set; }

        /// <summary>
        ///     數據列
        /// </summary>
        public List<DataTablesColumns> Columns { get; set; }

        /// <summary>
        ///     排序
        /// </summary>
        public List<DataTablesOrder> Order { get; set; }

        /// <summary>
        ///     搜索
        /// </summary>
        public DataTablesSearch Search { get; set; }

        /// <summary>
        ///     排序字段
        /// </summary>
        public string OrderBy
        {
            get
            {
                return Columns != null && Columns.Any() && Order != null && Order.Any()
                    ? Columns[Order[0].Column].Data
                    : string.Empty;
            }
        }

        /// <summary>
        ///     排序模式
        /// </summary>
        public DataTablesOrderDir OrderDir
        {
            get
            {
                return Order != null && Order.Any()
                    ? Order[0].Dir
                    : DataTablesOrderDir.Desc;
            }
        }
    }

    /// <summary>
    ///     排序
    /// </summary>
    public class DataTablesOrder
    {
        /// <summary>
        ///     排序的列的索引
        /// </summary>
        public int Column { get; set; }

        /// <summary>
        ///     排序模式
        /// </summary>
        public DataTablesOrderDir Dir { get; set; }
    }

    /// <summary>
    ///     排序模式
    /// </summary>
    public enum DataTablesOrderDir
    {
        /// <summary>
        ///     正序
        /// </summary>
        Asc,

        /// <summary>
        ///     倒序
        /// </summary>
        Desc
    }

    /// <summary>
    ///     數據列
    /// </summary>
    public class DataTablesColumns
    {
        /// <summary>
        ///     數據源
        /// </summary>
        public string Data { get; set; }

        /// <summary>
        ///     名稱
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        ///     是否能夠被搜索
        /// </summary>
        public bool Searchable { get; set; }

        /// <summary>
        ///     是否能夠排序
        /// </summary>
        public bool Orderable { get; set; }

        /// <summary>
        ///     搜索
        /// </summary>
        public DataTablesSearch Search { get; set; }
    }

    /// <summary>
    ///     搜索
    /// </summary>
    public class DataTablesSearch
    {
        /// <summary>
        ///     全局的搜索條件的值
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        ///     是否爲正則表達式處理
        /// </summary>
        public bool Regex { get; set; }
    }

完成,這樣,當咱們要使用Datatables的時候,咱們使用這個類(或這個類的派生類)來接收請求參數。

返回Datatables規定的Json

Datatables要求返回的數據Json

名稱 類型 描述
draw integerJS 請求次數計數器,每次發送給服務器後又原封返回.
recordsTotal integerJS 即沒有過濾的記錄數(數據庫裏總共記錄數)
recordsFiltered integerJS 過濾後的記錄數
data arrayJS 表中中須要顯示的數據。
error stringJS 可選。你能夠定義一個錯誤來描述服務器出了問題後的友好提示

處理返回的數據

當咱們把包含第n頁的m數據放在一個List的時候,咱們就須要封裝如下Datatables想要的數據格式了。

public class DataTablesResult<TEntity>
    { 
        public DataTablesResult(int drawParam, int recordsTotalParam, int recordsFilteredParam, IReadOnlyList<TEntity> dataParam)
        {
            draw = drawParam;
            recordsTotal = recordsTotalParam;
            recordsFiltered = recordsFilteredParam;
            data = dataParam;
        }
        public DataTablesResult(string errorParam)
        {
            error = errorParam;
        }
        public int draw { get; set; }
        public int recordsTotal { get; set; }
        public int recordsFiltered { get; set; }
        public IReadOnlyList<TEntity> data { get; set; }
        public string error { get; set; }

調用

var data = new Area().GetData();
if (!string.IsNullOrEmpty(query.Name))
    data = data.Where(n => n.Name.Contains(query.Name));
data = data.OrderBy(n=>n.Id);
var count = data.Count();
var result = data.Skip(query.Start).Take(query.Length).ToList();
var resultJson = new DataTablesResult<Area>(draw, recordsFiltered, recordsFiltered, result);
return Json(resultJson);

渲染Table,展現數據

服務器已經返回了咱們想要的Json數據,這時候咱們就要開始渲染Table,讓它將數據顯示正常了。

dt的渲染方式主要有js渲染和html的data-屬性來渲染,我選擇使用data-屬性來渲染(即初始化的時候的table)。

Table的data-data屬性要和返回的實體類的屬性對應,不然渲染不上

添加行操做

咱們須要在每行的後面加上諸如「修改」,「審覈」,「刪除」等等的操做按鈕,在dt裏怎麼操做呢?
其實很簡單。

table的表頭最後一行加以下代碼:

<th data-orderable="false">操做</th>

在dt初始化的時候添加以下代碼:

"columnDefs": [
            {
                "targets": -1,//-1表示最後一行
                "width": "100px",
                render: function (data, type, full, meta) {
                    return '<a class="btn btn-sm btn-info" href="javascript:;">設置<i class="fa fa-cogs"></i></a>  ' +
                        '<a class="btn btn-sm btn-info" href="javascript:;">刪除<i class="fa fa-trash"></i></a>';
                }
            }]

效果圖

效果圖

源碼

源碼

具體位置在項目MvcDemo的Controller裏

相關文章
相關標籤/搜索