はじめに
RailsアプリケーションでDataTablesを使っている記事を見かけなかったので、まとめることにしました。
やり方がわかっていないと細かい仕様を変更するのに時間がかかってしまいますが、やり方さえ覚えてしまえばとても使いやすい強力なツールです。
Bootstrap や jQuery UI を使うことによって、時間をかけずに多機能&良いレイアウトを提供してくれるため、爆速で開発できるRailsととても相性がいいと個人的には思っています。
関連リンク
関連リンクを下記に載せておくので、必要であれば参考にしてください。。
- 【Rails】 DataTables 動的にカラムを変更する方法
- 【Rails】 DataTables 検索結果の保持方法
DataTables
DataTables は、HTMLのテーブルに、ページ切り替え、ページ当たりの件数設定、ソート、フィルタなどの機能を簡単に追加できるjQuery プラグインのライブラリ。
使い方
設定
# ページネーションにはkaminariを使用するため
gem 'kaminari'
gem 'jquery-datatables-rails'
$ bundle install
$ rails g jquery:datatables:install
$ rails g jquery:datatables:install bootstrap3
//= require dataTables/jquery.dataTables
//= require dataTables/bootstrap/3/jquery.dataTables.bootstrap
*= require dataTables/jquery.dataTables
*= require dataTables/bootstrap/3/jquery.dataTables.bootstrap
- Bootstrap
※ version3系をダウンロードする。(GitHubにBootstrap4の記載がないため念のため。。)
4系でも使えると知っている方がいればコメントください。。
# 下記のようにファイルを配置する
app/assets/javascripts/bootstrap.min.js
app/assets/stylesheets/bootstrap.min.css
アプリケーション実装
前提条件
Userモデルを scaffold で作成していること。
全体像
厳密には異なるところもありますが、ざっくりと全体像を示すとこんな感じになります。
① id が users の要素を持った table を作成(table#users)し、CoffeeScript にて読み込み
② ajax で CoffeeScript から Rails 側へ、データの算出を要求する
③ コントローラーにて ajax を受け取り、 UserDatatable モデルへデータの算出を要求する
④ 要求を満たすデータを返す
⑤ ④のデータを json ファイルにして返す
⑥ CoffeeScript にて実装したテーブルを HTML にて表示する
ビュー
slim だと本当にシンプルに書くことができます。
// 検索項目
button#search_btn type="button"
|詳細検索
button#search_exec_btn type="button"
|検索
button#search_clear_btn type="button"
|クリア
table
tr
td = label :user, :id
td = text_field_tag :id, '', id: "search_id"
td = label :user, :username
td = text_field_tag :username, '', id: "search_username"
td = label :user, :name
td = text_field_tag :name, '', id: "search_name"
// DataTables のテーブル表示
table#incidents
ルーティング
jsonファイルを dataTables 側に渡すときに使用するルーティング。
のちほど、Javascriptにて使用する。
resources :users do
collection do
post 'ajax_data'
end
end
コントローラー
UserDatatableのインスタンスをjsonファイルとして返す。
def ajax_data
respond_to do |format|
format.html
format.json {render json: UsersDatatable.new(params) }
end
end
UserDatatableはパラメーターを受け取って、SQL を実行し JSON 形式に変換するクラス。
テーブルに表示させたい項目や検索結果などをこちらのファイルにて割り出している。
class UsersDatatable
attr_accessor :params
def initialize(params)
@params = params
end
# jQuery DataTables へ渡すためのハッシュを作る
# 補足:コントローラーの render json: で指定したオブジェクトに対して as_json が呼び出される
def as_json(options = {})
{
recordsTotal: User.count, # 取得件数
recordsFiltered: users.total_count, # フィルター前の全件数
data: users, # 表データ
}
end
def users
@users ||= fetch_users
end
# 検索条件や件数を指定してデータを取得
def fetch_users
User.where(search_sql).page(page).per(per)
end
# カラム情報を配列にする
def columns
return [] if params["columns"].blank?
params["columns"].to_unsafe_h.map{|_,v| v["data"]}
end
# 検索ワードが指定されたとき
def search_sql
search_sql = []
for column, search_params in params["columns"] do
search_sql.push("#{search_params["data"]} like '%#{search_params["search"]["value"]}%'") if search_params["search"]["value"].present?
end
search_sql.join(" and ")
end
# ソート順
def order_sql
return "" if params["order"]["0"].blank?
order_data = params["order"]["0"]
order_column = columns[order_data["column"].to_i]
# "id desc" のようにSQLの一部を作る
"#{order_column} #{order_data["dir"]}"
end
# kaminari 向け、ページ数
def page
params["start"].to_i / per + 1
end
# kaminari 向け、1ページで取得する件数
def per
params["length"].to_i > 0 ? params["length"].to_i : 10
end
end
Javascript
$ ->
# DataTables オブジェクト作成(ここではhtmlのid=users)
user_table = new DataTables($('#users'))
# ajax にて、 json ファイルを読み込み。作成したルーティングを引数に入れる。
user_table.setAjax("/users/ajax_data")
# user_table へカラムを追加する
user_table.setColumns([
{ data: 'id', title: 'ユーザID', width: '5%' },
{ data: 'username', title: 'ユーザ名', width: '25%' },
{ data: 'name', title: '名前', width: '30%' },
{ data: 'created_at', title: '登録日時', width: '20%' },
{ data: 'updated_at', title: '更新日時', width: '20%' },
])
user_table.setOption(false, true, true)
# 表示順番を0番目のカラムを昇順で表示(ここではidを昇順で表示)
user_table.setOrders([[0,'asc']])
# #users へ user_table を描写する。
user_table.drawTable()
# 各行をクリックすると詳細画面へ遷移するように設定
$('#users tbody').on 'click', 'tr', ->
data = $('#users').dataTable().fnGetData(this);
document.location = "/users/#{data.id}"
# 詳細検索ボタンを押すと、検索ボタンおよびカラムが表示されるように設定
$('#search_btn').on 'click', ->
$('.search-body').slideToggle(200)
$('#search_exec_btn').slideToggle(200)
$('#search_clear_btn').slideToggle(200)
# 検索ボタンを押すと、表示されているテーブルのカラムが検索条件に合致したものだけを表示するように設定。
$('#search_exec_btn').on 'click', ->
# dataTable の API を利用する。
user_table_api = $('#users').dataTable().api()
# 各検索カラムの値を読み込み
search_id = $('#search_id').val()
search_username = $('#search_username').val()
search_name = $('#search_name').val()
# 検索結果をテーブルに描画する
user_table_api.columns(0).search(search_id).draw()
user_table_api.columns(1).search(search_username).draw()
user_table_api.columns(2).search(search_name).draw()
$('#search_clear_btn').on 'click', ->
# 検索欄 入力内容 初期化
tmp_array = ["id", "username", "name"]
tmp_array.forEach (key) ->
$("#search_#{key}").val('').trigger('change')
まとめ
少し複雑な実装でしたので、Keynoteで作った全体像を用いての説明でした。
いかがでしたでしょうか。少しでも理解の助けになれればなと思います。
また、DataTables は高機能なライブラリですので、他にもできることを紹介していきたいと思います。
参考
- DataTables(公式ページ)
- GitHub(rweng/jquery-datatables-rails)
- Rails | Ajax で動的な検索・ソート機能付きページネーションを実装する(jQuery DataTablesプラグイン連動)
- DataTablesの使い方
- DataTablesでページが切り替わっても、ソートやページャや検索結果を保持しておくようにしたい。
- javascript でテキストをクリップボードにコピーする2つの方法