LoginSignup
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

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

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
What you can do with signing up
0