はじめに
DataTables 1.10.12 (https://datatables.net/)でAjax通信を行う方法をまとめます。
以降のサンプルプログラムではDjangoを使用しています。
DataTablesの設置
まず、次のテーブルをWebページに設置します。
デザインにはBootstrapを使用しています。
table
要素の id
は mytable
とし、ヘッダのみ作成しておきます。
<table id="mytable" class="table table-striped table-bordered table-hover dataTable no-footer dtr-inline"> <thead> <tr> <th>Column1</th> <th>Column2</th> … <th>Column10</th> </tr> </thead> </table>
続けて、DataTableの初期化を行います。
$(document).ready()
で各種設定を行います。
$('#mytable').DataTable({ scrollX: true, ordering: false, displayLength: 25, deferRender: true, ajax: { "processing": true, "url": "{% url 'myapp:action' %}", "data": function( d ) { d.param1 = $('#id_param1').val(); d.param2 = $('#id_param2').val(); d.param3 = $('#id_param3').val(); }, "dataSrc": "" }, columns: [ { "data": "item1", "render": function (data, type, full, meta) { return '<a href="/link/to/another/page?param=' + full.item1 + '">' + full.item1 + '</a>'; } }, { "data": "item2" }, { "data": "item3" }, { "data": "item4" }, { "data": "item5" }, { "data": "item6" }, { "data": "item7" }, { "data": "item8" }, { "data": "item9" }, { "data": "item10" } ] });
ajax
オプション
url
ではリクエスト先のURLを指定します(例ではDjangoテンプレートの記法で記述)。
data
ではGET時のパラメータを設定しています。
columns
オプション
DataTableの各列に表示する値を設定します。
基本的な使い方として{ "data": "key" }
を列の数だけ用意しておき、
key
にJSONデータのキーを指定します。
例えば [{"key": 100}]
というデータがサーバから返却されたとき、
対象の列には100が設定されます。
単純に値を出力するだけでなく、例えばその値を用いてハイパーリンクを構成したり、
画像へのリンクを生成したい場合には、前述の例に示したように render
オプションを使用します。
deferRender
オプション
多量データを処理する場合には deferRender: true
を設定すると性能が向上します。
このオプションを有効にすることでデータテーブルは実際に画面表示に必要な要素のみを読み込むため、
数万件のレコードを受信した場合でも、ページングの都度必要な件数のみを処理することができます。
Ajax通信
クライアントサイド
myapp:action
へのGETリクエストで設定するパラメータを入力するフォームを設置します。
<form id="myform" role="form"> <div class="form-group"> <label>Param1</label> <input type="text" name="column1" class="form-control" id="id_param1"> </div> <div class="form-group"> <label>Param2</label> <input type="text" name="column2" class="form-control" id="id_param2"> </div> <div class="form-group"> <label>Param3</label> <input type="text" name="column3" class="form-control" id="id_param3"> </div> <button type="submit" class="btn btn-default">Submit</button> </form>
Submit
ボタン押下時のコールバックでは
DataTable().ajax.reload()
によってサーバとのAjax通信を開始します。
$("#myform").submit(function(event) { event.preventDefault(); $('#mytable').DataTable().ajax.reload(); return false; });
このときデータテーブルでは上記テキストボックスに入力した値を クエリストリングに設定しています。
従ってURLは /myapp/action?param1=foo¶m2=bar¶m3=baz
のような形式になります。
(再掲)
ajax: { … "data": function( d ) { d.param1 = $('#id_param1').val(); d.param2 = $('#id_param2').val(); d.param3 = $('#id_param3').val(); }, … },
サーバサイド
サーバサイドの実装は今回主題ではないため、簡単に固定のJSONを返却しておきます。
ここで param1
の設定がない場合をページロード時の通信であると判断して空のJSONを返却しています。
どうやら serverSide : true
で deferLoading : 0
にすると初回のAjax通信を抑止できるようですが試してません。
def action(request): if request.GET.get("param1"): response = '[{"item1":1, "item2":2, "item3":3, "item4":4, "item5":5, "item6":6, "item7":7, "item8":8, "item9":9, "item10":10}]' return HttpResponse(response, content_type='application/json') else: # Request on page load return HttpResponse('{}', content_type='application/json')
Ajaxリロード時のプログレス表示
processing : true
であるにも関わらず、 DataTable().ajax.reload()
で Loading...
が表示されない問題が生じたため次のコードで対処しました。
$('#mytable').on('preXhr.dt', function(e, settings, data){ $(this).DataTable().clear(); settings.iDraw = 0; $(this).DataTable().draw(); });
エラー処理
Ajax通信のエラー処理を実装する場合には、
xhr.dt
イベントでHTTPステータス xhr.status
を判定し、
サーバサイドから返却された xhr.responseJSON
内のエラーメッセージ等を表示、
DataTable().clear().draw()
で空のデータテーブルを再描画すると良さそうです。
$('#mytable').on('xhr.dt', function ( e, settings, json, xhr ) { // Receive BadRequest status if (xhr.status == '400') { // Show error message $("#err_msg").text(xhr.responseJSON.error[0].message); $("#err_msg").show(); // Redraw data table $('#mytable').DataTable().clear().draw(); // Prevent error.dt from occurring return true; } });
(2020/07/26追記) ヘッダ・ボディ間のスペース除去
scrollX: true
を設定するとヘッダとボディの間にスペースが生じます。
DataTableで scrollCollapse: true
を設定し、以下のスタイルを適用すると除去できます。
$('#mytable').DataTable({ scrollX: true, scrollCollapse: true, // 追加 // ...
<style> .dataTables_scrollBody thead { visibility: collapse !important; } .dataTables_scrollBody { margin-top: -20px; } </style>