概要
以下の投稿で課題としていた結合したセルにてソートが正常に動作しなくなる件について、
これまたdatatableの仕様に苦しんだので解決方法を記載します。
目次
問題事象
以下のような表をdatatableを使用して作成した際、
datatableが行なってくれるソート処理が、rowGroupを使用しない場合と使用した場合で異なる仕様となる。
・rowGroupに指定したcolumnは先頭項目でのみソートが可能。
・rowGroupに指定していないcolumnはrowGroupにて結合された項目内でのソートとなる。
<html>
<head>
<meta charset="UTF-8">
<!-- !-- for DataTables --> -->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.10.24/datatables.min.css" />
</head>
<body>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script type="text/javascript"
src="https://cdn.rawgit.com/ashl1/datatables-rowsgroup/fbd569b8768155c7a9a62568e66a64115887d7d0/dataTables.rowsGroup.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.10.24/datatables.min.js"></script>
<script type="text/javascript"
src="https://cdn.rawgit.com/ashl1/datatables-rowsgroup/fbd569b8768155c7a9a62568e66a64115887d7d0/dataTables.rowsGroup.js"></script>
<table id="example" class="stripe hover cell-border order-column table table-bordered" cellspacing="0" width="100%">
<thead>
<tr>
<th>名前</th>
<th>電話</th>
<th>年齢</th>
<th>購入商品</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script src="main.js"></script>
</body>
</html>
$(document).ready(function (){
var table = $('#example').DataTable({
'language': {
"url": "//cdn.datatables.net/plug-ins/1.10.21/i18n/Japanese.json"
},
'data': [
["山田","0000000","30","マンが"],
["山田","0000000","30","肉"],
["山田","0000000","30","魚"],
["山田","0000000","30","タバコ"],
["山田","0000000","30","皿"],
["山田","0000000","30","人形"],
["山田","0000000","30","ゲーム"],
["佐藤","1111111","21","骨"],
["佐藤","1111111","21","パッド"],
["佐藤","1111111","21","ボール"],
["マイケル","2222222","10","バッド"],
["マイケル","2222222","10","刀"],
["ヨーコ","3333333","40","お花"],
],
'columnDefs': [
{
'targets': [0,1, 2, 3],
'orderable': true,
'searchable': false
}
],
'rowsGroup':[0,1,2],
"pageLength": 100
});
});
ソート時の動作は以下
先頭項目でのソート
・電話/年齢でのソートが動作しない。
スクリーンショット 0004-07-04 21.18.05
rowGroup内部でのソート
・購入商品でソートをしても名前/電話/年齢項目の並び順は変更されない。
スクリーンショット 0004-07-04 21.18.40
原因
以下2点から、rowGroupでのソートは、rowGroupにした複数項目にてソートを行う仕様だと考えられる。
・orderClasses機能が動作していること
・sorting_1/2/3がDOM要素に付与されていた
https://datatables.net/reference/option/orderClasses
・名前/電話/年齢項目ヘッダーの操作時の動作
・並び替え無し状態とならない
・常にrowGroupに含まれる複数項目でのソートを行なっているように見える。
https://datatables.net/examples/basic_init/multi_col_sort
解決方法
datatableの仕様の問題で、プロパティ変更などでは解決しなかった。
datatable側のソート処理を無効化、呼び出し側でソート機能を実装した。
datatableのcssを呼び出すことで見た目上差異はない。
<html>
<head>
<meta charset="UTF-8">
<!-- !-- for DataTables --> -->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.10.24/datatables.min.css" />
crossorigin="anonymous">
</head>
<body>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script type="text/javascript"
src="https://cdn.rawgit.com/ashl1/datatables-rowsgroup/fbd569b8768155c7a9a62568e66a64115887d7d0/dataTables.rowsGroup.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.10.24/datatables.min.js"></script>
<script type="text/javascript"
src="https://cdn.rawgit.com/ashl1/datatables-rowsgroup/fbd569b8768155c7a9a62568e66a64115887d7d0/dataTables.rowsGroup.js"></script>
<table id="example" class="stripe hover cell-border order-column table table-bordered" cellspacing="0" width="100%">
<thead>
<tr id="tablehead">
<th class="sorting" onclick="sortTask(event)" id="name">名前</th>
<th class="sorting" onclick="sortTask(event)" id="tel">電話</th>
<th class="sorting" onclick="sortTask(event)" id="age">年齢</th>
<th class="sorting" onclick="sortTask(event)" id="item">購入商品</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script src="main.js"></script>
</body>
</html>
$(document).ready(function (){
table = $('#example').DataTable({
'language': {
"url": "//cdn.datatables.net/plug-ins/1.10.21/i18n/Japanese.json"
},
'data': [
["山田","0000000","30","マンが"],
["山田","0000000","30","肉"],
["山田","0000000","30","魚"],
["山田","0000000","30","タバコ"],
["山田","0000000","30","皿"],
["山田","0000000","30","人形"],
["山田","0000000","30","ゲーム"],
["佐藤","1111111","21","骨"],
["佐藤","1111111","21","パッド"],
["佐藤","1111111","21","ボール"],
["マイケル","2222222","10","バッド"],
["マイケル","2222222","10","刀"],
["ヨーコ","3333333","40","お花"],
],
'columnDefs': [
{
'targets': [0,1, 2, 3],
'searchable': false
}
],
"ordering": false,
'rowsGroup':[0,1,2],
"pageLength": 100
});
});
function sortTask(event)
{
let buf = table.data();
table.clear();
// ソート初期状態を解除
$(event.target).removeClass('sorting');
let sortPattern = "";
if($(event.target).hasClass('sorting_asc'))
{
// 昇順であれば、降順
$(event.target).removeClass('sorting_asc');
$(event.target).addClass('sorting_desc');
sortPattern = 'sorting_desc';
}
else
{
// 降順であれば、昇順
$(event.target).removeClass('sorting_desc');
$(event.target).addClass('sorting_asc');
sortPattern = 'sorting_asc';
}
$.each(document.getElementById('tablehead').childNodes, function (index, element)
{
// 他ヘッダーのソート状態をソートなしに変更
if(element.id != "" && event.target.id != element.id)
{
// 操作したヘッダーは対象外
$(element).removeClass('sorting_asc');
$(element).removeClass('sorting_desc');
$(element).addClass('sorting');
}
});
sorttest(buf, event.target.id, sortPattern);
table.rows.add(buf).draw();
}
function sorttest(table, sortId, sortPattern)
{
table.sort(function (a,b)
{
switch (sortId)
{
case "name":
if(sortPattern === "sorting_asc")
{
if (a[0] > b[0]) return 1;
if (a[0] < b[0]) return -1;
}
else if(sortPattern === "sorting_desc")
{
if (a[0] < b[0]) return 1;
if (a[0] > b[0]) return -1;
}
break;
case "tel":
if(sortPattern === "sorting_asc")
{
if (a[1] > b[1]) return 1;
if (a[1] < b[1]) return -1;
}
else if(sortPattern === "sorting_desc")
{
if (a[1] < b[1]) return 1;
if (a[1] > b[1]) return -1;
}
break;
case "age":
if(sortPattern === "sorting_asc")
{
if (a[2] > b[2]) return 1;
if (a[2] < b[2]) return -1;
}
else if(sortPattern === "sorting_desc")
{
if (a[2] < b[2]) return 1;
if (a[2] > b[2]) return -1;
}
break;
case "item":
if(sortPattern === "sorting_asc")
{
if (a[3] > b[3]) return 1;
if (a[3] < b[3]) return -1;
}
else if(sortPattern === "sorting_desc")
{
if (a[3] < b[3]) return 1;
if (a[3] > b[3]) return -1;
}
break;
default:
break
}
});
}
終わり
ここだけの話、datatableにはrowGroupって名前の機能が2つあります。
また、会おうdatatable
以上です。
ありがとうございました。