Excel風グリッドライブラリのhandsontableを使って一覧表示をできるようにします。rails tutorialでも一覧表示はできましたが、handsontableを使うと後々一括登録もできるようになります。また、一覧表示にしても並べ替え(行も列も)ができるようになります。
準備(インストール作業)
詳細は公式サイトを見てください。React, Vue, Angularなどに対応したライブラリもありますが、ピュアなjavascriptライブラリ版もあります。私の場合はピュアjavascriptでやります。
なお、バージョンは2019年11月時点で7.2.2が最新ですが、無料版は6.2.2です。7以上は基本的に有料です。非営利などであれば無料でも使えるようですが、google Adsenceなどを考えているなら、6.2.2にしておいたほうが無難だと考えます。
https://github.com/handsontable/handsontable/tree/6.2.2
インストールは単純です。min.jsやmin.cssをvendor/assetsの下に配置し、application.jsやcssに下記のようにパスを追加します。なお、moment.min.jsは、日付関係の演算を行うためのライブラリで、handsontableには関係ありません。
//= require_tree ../../../vendor/assets/javascripts
*= require_tree ../../../vendor/assets/stylesheets

jqueryやjquery-uiについては、面倒であればgoogleでもどこでもよいのでCDNを使ったほうが楽かもしれません。CDNを使う場合はapplication.htmlなどのアセットにscript srcを通せばOKです。
一覧表示をする

handsontableは大きく分けると下記のように構成されています。
- データ
- ヘッダ(見出し)
- ヘッダ(型定義)
ヘッダは、見出しの部分と、型定義で構成されています。型定義にはidがありますが、この値は、データ上の「キー」と一致することになります。データの設定方法には、ajaxから受け取ったレスポンスこともできますし、初期表示時にグリッド表示をする場合には、hiddenなエレメントを経由して表示することもできます。
var initHours = function(){
var data = eval($('#man_hours_hidden').data('json'));
var grid = document.getElementById('man_hours_grid');
var hot = new Handsontable(grid, {
data: data,
colHeaders: ['', '' ,'', '削除', '工数名', '工数確定回数', '開始日', '終了日'],
columns: [
{
data: "id",
type: 'numeric',
readOnly: true
}, {
data: '_status',
type: 'text',
readOnly: true
}, {
data: 'status',
type: 'text',
readOnly: true
}, {
data: "select",
type: 'checkbox'
}, {
data: "man_hour_name",
type: 'text',
validator: function (value, callback) {
callback(true);
},
maxLength: 50,
editor: 'maxlength'
}, {
data: "results",
type: 'numeric',
readOnly: true
}, {
data: "valid_from",
type: 'time',
validator: function (value, callback) {
callback(true);
},
editor: 'ymd'
}, {
data: "valid_to",
type: 'time',
validator: function (value, callback) {
callback(true);
},
editor: 'ymd'
}
],
width: 710,
height: 120,
colWidths: [1, 1, 30, 50, 200,100, 150,150],
enterMoves: { row: 1, col: 0 },
outsideClickDeselects: true,
manualColumnResize: true,
manualColumnMove: true,
columnSorting: true
});
};
<div id="man_hours_hidden" data-json="<%= @form.man_hours.to_json %>">
</div>
つまるところdataとは、マップの配列
下記はcontroller側に書いたレスポンスに組み立て処理です。つまるところhandsontableのdataとして表示するデータは、1エレメントがマップの、配列です。先ほどのヘッダ(型定義)のidと一致する構成になるようにします。
man_hours = []
man_hours_tmp = man_hours(user)
man_hours_tmp.each do |m|
valid_from = toYMD(m["valid_from"])
valid_to = toYMD(m["valid_to"])
man_hours.push(FormManHour.new(
id: m["id"] ,man_hour_name: m["name"],results: m["results_cnt"] ,
valid_from: valid_from ,valid_to: valid_to
))
end
//中略
@form = FormSettings.new(
user_name: user.name
, email: user.account.email
, man_hours: man_hours
, man_hour_results: man_hour_results
, public_id: public_id
)
次回→追加、削除、反映ボタンを作る
次回は追加や削除をできるようにします。