LoginSignup
1
0

More than 1 year has passed since last update.

[jQuery][DataTable]結合したセルにてSortを行う

Last updated at Posted at 2022-07-04

概要

以下の投稿で課題としていた結合したセルにてソートが正常に動作しなくなる件について、
これまたdatatableの仕様に苦しんだので解決方法を記載します。

目次

  1. 問題事象
  2. 原因
  3. 解決方法
  4. 終わり

問題事象

以下のような表をdatatableを使用して作成した際、
datatableが行なってくれるソート処理が、rowGroupを使用しない場合と使用した場合で異なる仕様となる。
・rowGroupに指定したcolumnは先頭項目でのみソートが可能。
・rowGroupに指定していないcolumnはrowGroupにて結合された項目内でのソートとなる。

image.png

index.html
<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>
main.js
$(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.png
スクリーンショット 0004-07-04 21.18.05

rowGroup内部でのソート
・購入商品でソートをしても名前/電話/年齢項目の並び順は変更されない。
スクリーンショット 0004-07-04 21.18.40.png
スクリーンショット 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を呼び出すことで見た目上差異はない。

index.html
<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>
main.js
$(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
        }
    });
}


image.png

終わり

ここだけの話、datatableにはrowGroupって名前の機能が2つあります。
また、会おうdatatable

以上です。
ありがとうございました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0