[jQuery] DataTablesで行が開閉するアコーディオンを作る

JavaScriptDataTables,jQuery

開閉ボタンをクリックすると、テーブルの行が開いたり、閉じたりするアオーディオンの設置方法。
行ごとに開閉ボタンがあり、さらに「全部開く」と「全部閉じる」ボタンをつけた。

ある日付や、ワードでテーブル内を検索したいが、 1 行に情報量が多すぎて見た目が悪いのでなんとかしてほしいと言われたときに作った。検索対象の情報は非表示にしてもよかったけど、アコーディオンで隠しておけば見た目の問題は解決するし、親切だろう。

テーブルにアコーディオンを作る

サンプル

1 列目にある「 + 」または「全部開く」ボタンをクリックすると、行が開き隠れたコンテンツが表示される。

See the Pen DataTables Row Accordion by AgoPeanuts (@AgoPeanuts) on CodePen.

公式ドキュメント – Child rows

公式では Ajax でデータを取ってきているが、ここでは PHP で DB からデータを取ってきて、 HTML を組み立てた。
Ajax であれば画面表示後も、アコーディオンに入れたいデータを(テーブルに出力しておかなくても)保持できるが、 PHP 側で HTML を組み立てる場合には、アコーディオンに入れたいデータを、テーブルデータとしてあらかじめ出力しておく。

なので、テーブルを作成するときに、アコーディオンに入れたいデータを非表示カラムとして作っておく。そうすると js の function format ( d ) のところでデータを取得することができる。

コード

PHP & HTML

<?php
// DB から結果取得
$sql = 'SELECT * FROM ghibuli';
$res = $mysqli->query($sql);
?>

<!-- 「全部開く」、「全部閉じる」ボタン -->
<div id='allBtn'>
  <button id="btn-show-all" type="button" class="btn-flat-border">全部開く</button>
  <button id="btn-hide-all" type="button" class="btn-flat-border">全部閉じる</button>
</div>

<!-- テーブル組み立て -->
<div class='table-responsive'>
  <table id='ghibuli-table' class='table table-bordered table-striped table-hover' style="width:100%">
    <thead>
      <tr>
        <th></th>
        <th>作品名</th>
        <th>公開日</th>
        <th>監督</th>
        <th>上映時間 (分)</th>
      </tr>
    </thead>
    <tbody>
<?php
while( $data = $res->fetch_row() ) : ?>
      <tr>
        <td class='details-control'></td>
        <td><?=$data[0]?></td>
        <td><?=$data[1]?></td>
        <td><?=$data[2]?></td>
        <td><?=$data[3]?></td>
        <td><?=$data[4]?></td>
        <td><?=$data[5]?></td>
        <td><?=$data[6]?></td>
      </tr>
<?php endwhile;?>
    </tbody>
  </table>
</div>

js

// アコーディオンに入れるデータの組み立て
function format ( d ) {
    return '<table style="width:100%;font-size:12px;">'+
        '<tr>'+
            '<td>英語タイトル</td>'+
            '<td>'+d[5]+'</td>'+
        '</tr>'+
        '<tr>'+
            '<td >原作</td>'+
            '<td>'+d[6]+'</td>'+
        '</tr>'+
        '<tr>'+
            '<td>声の出演</td>'+
            '<td>'+d[7]+'</td>'+
        '</tr>'+
    '</table>';
}

$(document).ready(function() {
  // DataTables 設置
  var ghibuliTable = $('#ghibuli-table').DataTable({
    columnDefs: [
      // 6, 7, 8 列非表示
      { targets: [5, 6, 7], visible: false }
    ]
  });

  // 開閉のマークをクリックしたとき
  $('#ghibuli-table tbody').on('click', 'td.details-control', function () {

    var tr = $(this).closest('tr');
    var row = ghibuliTable.row(tr);

    // 行の開閉イベント
    if ( row.child.isShown() ) {
      row.child.hide();
      tr.removeClass('shown');
    } else {
      row.child( format(row.data()) ).show();
      tr.addClass('shown');
    }
  });

  // "全部開く" ボタン
  $('#btn-show-all').on('click', function() {
    ghibuliTable.rows().every(function() {
      if(!this.child.isShown()) {
        this.child(format(this.data())).show();
        $(this.node()).addClass('shown');
      }
    });
  });

  // "全部閉じる" ボタン
  $('#btn-hide-all').on('click', function() {
    ghibuliTable.rows().every(function() {
      if(this.child.isShown()) {
        this.child.hide();
        $(this.node()).removeClass('shown');
      }
    });
  });
});

CSS

td.details-control {
  text-align:center;
  width:5%;
  min-width:5%;
  max-width:5%;
}
td.details-control:before {
  font-family: "Font Awesome 5 Free";
  content: "\f0fe";
  font-weight: 900;
  padding: 0px;
  color: #f67280; /*アイコンの色*/
}
tr.shown td.details-control:before {
  font-family: "Font Awesome 5 Free";
  content: "\f146";
  font-weight: 900;
  padding-left: 0px;
  color: #36b5b0; /*アイコンの色*/
}

「開く」、「閉じる」のアイコンは Font Awesome を使用。

Posted by Agopeanuts