jQuery DataTables column add button checkbox
前言
本篇是jQuery DataTables系列文的最後一篇
最後一篇把之前沒提到,剩餘零散的功能統一集中在此說明
實作
1.資料行加入checkbox、超連結、button
很常見的功能,請參考:Datatables学习笔记——columns.render
在呼叫$( selector ).DataTable()初始化時,可以在columns属性中實現,也可以在columnDefs属性中實現。
jquery DataTables有很多資料行設定既可以寫在columns也可以寫在columnDefs
兩者差別為,columns要資料行一個一個設定,columnDefs則是多個資料行共用同一個設定,如下↓
/*同時設定兩個資料行禁用排序*/
columnDefs: [{
targets: [0,4],
orderable: false
}]
以加入checkbox、超連結、button的情況來說,既然在columns都已經定義好資料行繫結,如果寫在columnDefs有種分開設定的雜亂感
我個人習慣寫在columns裡
完整View代碼↓
※這次加入deferRender:true的參數,因為此DataTables代碼為Client Side模式透過Ajax取回資料到前端(有可能很多筆),但實際上DataTables預設一頁才顯示10~100筆,避免效能瓶頸
請參考:延迟渲染(deferRender)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Client Side 完整 排序、分頁、查詢(DataSource使用Ajax)
展示資料行加入checkbox、button、Hyperlink
</title>
<!--引用dataTables.css-->
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" />
</head>
<body>
@using (Html.BeginForm("", "", FormMethod.Post, new { name = "myForm" }))
{
<label>MyTitle:</label> <input type="text" value="" name="MyTitle" /><br />
<label>MyMoney:</label> <input type="text" value="" name="MyMoney" /><br />
<button type="button" id="btnQuery"> 查詢</button>
}
<table id="myDataTalbe" class="display">
<thead>
<tr>
<th>
<input type="checkbox" name="chkAll" /> <!--全選、全勾消checkbox-->
</th>
<th>#</th>
<th>MyTitle</th>
<th>MyMoney</th>
<th>操作</th>
</tr>
</thead>
</table>
<!--引用jQuery核心-->
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.js"></script>
<!--引用jquery dataTables.js-->
<script type="text/javascript" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<script type="text/javascript">
//刪除資料
function DelData(data)
{
if(confirm(data+" 是否刪除?")){
//todo ajax Delete data(自行發揮)
//todo ajax Delete callback function(自行發揮)
$("#btnQuery").click();//重新查詢更新畫面
}
}//end DelData Func
$(function () {
let table =
$("#myDataTalbe").DataTable({
searching: false, //關閉filter功能
columns: [
{
//這裡的data變數值為sysid,相等於obj.sysid
"data": "sysid", orderable: false, render: function (data, type, obj, meta)
{
return '<input type="checkbox" value="' + data + '">';
}
},
{ "data": "sysid" },//指定資料行繫結名稱
{ "data": "MyTitle" },
{ "data": "MyMoney" },
{
//這裡的data變數值為sysid,相等於row.sysid
data: "sysid",//資料行繫結屬性
orderable: false, // 禁用排序
render: function (data, type, row, meta) {
//row為後端回傳的資料列物件、data變數相等於row.sysid,row可以抓到哪些資料行取決於後端的回傳
return "<a href='" +"@Url.Action("Edit","Home")"+"?sysid=" + data + "' >Edit</a> "
+ "<input type='button' onclick='DelData(" + data + ")' value='Delete' />";
}
}
],
deferRender:true
});
//全選、全勾消
$("input[name=chkAll]").change(function () {
let checked = $(this).prop("checked");
$("#myDataTalbe > tbody input:checkbox").prop("checked", checked);
});
$("#btnQuery").click(function () {
$.ajax({
url: "@Url.Action("GetData3", "Home")",
method: "get",
data: $("form[name=myForm]").serialize(),
dataType: 'json',
success: function (result) {
//參考:https://datatables.net/reference/api/rows.add()
table.clear().rows.add(result).draw();
}
});
});
});
</script>
</body>
</html>
Controller代碼↓
/// <summary>
/// 每一筆資料Entity
/// </summary>
public class MyRecord
{
public int sysid { get; set; }
public string MyTitle { get; set; }
public int MyMoney { get; set; }
}
public class HomeController : Controller
{
/// <summary>
/// DataSource 資料集合,通常為DB裡的資料
/// </summary>
private List<MyRecord> _myRecords = new List<MyRecord>();
public HomeController()
{//在建構子裡新增資料
for (int i = 0; i < 300; i++)
{
this._myRecords.Add(new MyRecord()
{
sysid = i + 1,
MyTitle = "MyTitle" + i,
MyMoney = i * 1000
});
}//end for
}
public ActionResult GetData3()
{
//Server端即使排序,到了前端Datatables 還會再排序一次 ,所以這裡的資料無須排序
//直接回傳集合給前端
//參考:https://datatables.net/reference/api/rows.add()
return Json(this._myRecords, JsonRequestBehavior.AllowGet);
}
}
執行結果↓
※如要客製化呈現文字的話,也是在render參數設定,例如: 性別0為女生、1為男生,除非邏輯太複雜不適合寫在JS,才在Server端組好資料後回傳給DataTables做資料繫結。
2018.4.7 補充 render:function(data,type,row,meta)當中的row變數包含了Server端回傳的一筆全部資料,而不是DataTable的資料行資料
換句話說,即使沒被DataTable DataBinding到的資料,仍然可以從row變數讀取Server端的資料
如下↓ DataTable只呈現三個資料行,但實際上row變數包含了Server端回傳的一筆全部資料,官網說明:columns.render
2.設定下拉選單的每頁顯示幾筆
參考官網文件:lengthMenu
↓這是預設值
使用方式↓
官網第二個Example可看到陣列中又包含兩個陣列
那個「-1」和「All」,前者指的是下拉選單的value、後者「All」是下拉選單的文字
另外,需留意pageLength(每頁顯示幾筆),預設就會指派lengthMenu的第一個值給它,所以無須另外設定,亂給pageLength值會發生奇怪的現象
官網說明↓
2018.4.5追記,發現如果使用$.extend()為 $.fn.dataTable.defaults設定lengthMenu預設值的話,同時pageLength也要設定,否則會出現如下情況
正確代碼↓
$.extend(true, $.fn.dataTable.defaults, {
//必須同時設定pageLength和lengthMenu預設值
pageLength: 25,
lengthMenu: [25, 50, 100],//下拉選單每頁顯示幾筆
});
3.變更DataTables樣式
現在滿多網站都已使用Bootstrap框架,DataTables也支援Bootstrap樣式
可參考以下文章:
https://datatables.net/manual/styling/bootstrap (Bootstrap 3樣式)
https://datatables.net/examples/styling/bootstrap4 (Bootstrap 4樣式)
4.為DataTables設定預設值
如果覺得每次初始化$(selector).DataTable();,設定都重覆的話,例如:多國語系、關閉filter、關閉orderMulti功能
可以另行新增一支.js檔,把重覆的、共用設定都寫進入該.js,網頁再引用該.js檔來使用
參考官網文件:Setting defaults
2018.4.4 追記
Is there a way to disable initial sorting for jquery DataTables?
2018.4.6 追記
預設DataTables發出Ajax如果發生錯誤是會跳出alert() dialog
照著官網做:7. Warning: Ajax error
便可以把alert()改成錯誤訊息輸出到瀏覽器的console介面(畢竟客戶看不懂alert()的錯誤訊息XD)
還有若DataTables發出的Ajax,Server端登入逾時情況的寫法↓ (搭配我的另一篇文章使用:[ASP.MVC] 當jQuery Ajax呼叫遇上Login Timeout的處理 )
2018.4.10追記如何判斷DataTable當中是否有資料
可以在drawCallback事件裡利用 count() 方法判斷
範例↓
drawCallback: function (settings)
{
if (settings.iDraw >= 2)
{//通常執行了button click 查詢之後
let api = this.api();
if (api.data().count() >= 1)
{//查有資料
//Do Something..
} else {
//查無資料
//Do Something..
}
}//end if
}
drawCallback事件裡還有一項重要寫法需留意↓
drawCallback: function (settings)
{ //因為DataTable ServerSide 每次發Ajax會刷新DOM(thead、tbody內的),使用jQuery要重新註冊事件
//Bootstrap tooltip
$('[data-toggle="tooltip"]').tooltip();
},
2024-05-14 追記:在Server Side回傳自定義參數,從前端DataTable的Callback function取得該自定義參數的值
Asp.net MVC 片段範例如下 ※實務上請把複雜的商業邏輯寫在後端處理完畢,才把結果值回傳給前端顯示
而在前端取得該自定義參數有兩種方法(擇一即可),以個人情況比較適合寫在drawCallback function,因為我的xhr.dt(Ajax callback function)已被作為共用函式
執行結果↓
2018.4.11 追記,如何為資料行加class、資料列加class
資料行要加class,可參考:columns.className
資料列要加class(通常為了高亮某一資料列使用),前端做法:createdRow事件,Server端做法:How To Add RowId and RowClass on Datatable
前端範例Code↓
createdRow: function( row, data, dataIndex ) {
//row為html element
//data為Server端回傳的一筆物件(即使沒和資料行DataBinding的資料也可從data變數讀取)
if(data.yourProperty==="SomeString")
{
$(row).addClass('highlight');
}
}
Server端範例Code (ASP.net MVC) ↓
public ActionResult Query_Table(string yourCondition,//前端DataTable傳給Server端的查詢條件
int draw, int start, int length //→此三個為DataTables自動傳遞參數
)
{
int recordsTotal=0;
List<yourObject> pagedData = new List<yourObject>();
//回傳Json資料
var returnObj =
new
{
draw = draw,
recordsTotal = recordsTotal,//資料總筆數
recordsFiltered = recordsTotal,
data = from p in pagedData//分頁後的資料
select new
{
DT_RowClass = "testClass"//前端的tr就會加上class
}
};
return Content(JsonConvert.SerializeObject(returnObj), "application/json");
}//end DataTables
2022.1.5 追記,若遇到columns裡設定width無作用↓
解法:改成在jQuery DOM Ready事件裡設定DataTable 欄位的width,例如↓
$('thead > tr> th:nth-child(1)').css({ "min-width": "80px", "max-width": "80px" });
結語
jQuery DataTables系列文暫此告一段落,至目前為止介紹的功能,我自覺應該都很夠用XD
未來工作上如有遇到地雷、新的需求,會再不定期更新文章