2017 年 3 月 31 日星期五

Ajax 載入的列詳細資訊

顯示 DataTable 中某列的詳細資訊是一項很受歡迎的功能。它允許使用者輕鬆存取和處理主表格視圖,同時也能以結構化的方式深入查看更詳細的資料。

DataTables 提供子列 API 方法 (row().child()row().child().show() 等),讓您可以輕鬆顯示此類詳細資訊列。甚至在本網站上也有一個簡單的範例

這篇文章的主題是建立在該範例之上,描述如何處理一個簡單但常見的要求擴充:透過 Ajax 非同步載入子列的資料,而不是僅使用表格中已有的資料。

範例

下表顯示了我們將在本文中建立的範例。點擊顯示圖示將顯示「載入中」訊息,然後由從伺服器以 Ajax 載入的資料取代。在這個演示中,伺服器端腳本中添加了人工的兩秒延遲,以便您可以看到載入訊息,然後被載入的資訊取代。

姓名 職位 辦公室 薪水
姓名 職位 辦公室 薪水

設定

這篇文章的大部分內容實際上是關於 DataTable 的基本設定,因為最終的實作可能出乎意料的簡單。如果您已經熟悉建立 DataTable,請跳到「Ajax 請求」部分。

基本 DataTable

讓我們從頭開始,建立一個具有 Ajax 來源資料且使用 物件作為資料來源的 DataTable

var table = $('#myTable').DataTable( {
    ajax: '/api/staff',
    columns: [
        {
            className:      'details-control',
            orderable:      false,
            data:           null,
            defaultContent: ''
        },
        { data: "name" },
        { data: "position" },
        { data: "office" },
        { data: "salary" }
    ],
    order: [[1, 'asc']]
} );

請注意,表格中的第一欄被指定了一個類別,並且僅顯示一個空字串(即什麼都沒有!)作為其資料值。這是為了我們可以將該儲存格用於開啟/關閉圖示,讓使用者點擊它來顯示詳細資訊列。

事件處理程式

我們可以附加以下事件監聽器來執行開啟/關閉操作

$('#myTable tbody').on('click', 'td.details-control', function () {
    var tr = $(this).closest('tr');
    var row = table.row( tr );

    if ( row.child.isShown() ) {
        row.child.hide();
        tr.removeClass('shown');
    }
    else {
        row.child( format(row.data()) ).show();
        tr.addClass('shown');
    }
} );

在上面的程式碼中,我們使用 row().child.isShown() 來檢查該列是否已顯示子列。如果是,則使用 row().child.hide() 隱藏它;如果不是,則使用 row().child().show() 建立它。

這正是整篇文章圍繞的後者函數!在最簡單的情況下,您可以將字串傳遞給 row().child(),它會在子列中顯示該字串,但重要的是,您也可以傳遞一個節點(或包含節點的 jQuery 物件),它將顯示在表格中。這使得一旦 Ajax 請求完成後更新文件變得非常容易,只要我們保留對該節點的參考。

Ajax 請求

我們的目標是建立一個 Ajax 請求,其回應將決定在詳細資訊列中顯示的內容。在載入資料時,我們希望向使用者顯示「載入中」訊息,以便他們知道正在發生某些事情。我們可以透過使用 Javascript 的一個非常強大的功能來做到這一點,我們經常將其用作 Javascript 開發人員,但並非總是賦予其名稱:閉包

您會在事件處理程式程式碼的第 10 行注意到我們呼叫了一個自定義定義的函數,稱為 format(使用您想要的任何函數名稱!),並傳入列資料 - 我們想要做的是讓它返回一個包含載入訊息的元素給 DataTables,以便立即顯示,但同時建立一個 Ajax 請求,該請求會在資料載入後更新該元素。

function format ( rowData ) {
    var div = $('<div/>')
        .addClass( 'loading' )
        .text( 'Loading...' );

    $.ajax( {
        url: '/api/staff/details',
        data: {
            name: rowData.name
        },
        dataType: 'json',
        success: function ( json ) {
            div
                .html( json.html )
                .removeClass( 'loading' );
        } 
    } );

    return div;
}

基本上就是這樣!子列中顯示的內容完全取決於您自己,因為它只是一個 div 容器元素。您可以使用動畫來顯示它,插入另一個 DataTable,任何您喜歡的內容!這裡的關鍵是返回 div 以由子列呈現,同時也使用 Ajax 和閉包來非同步填充該 div