kintoneでテーブルの行をドラッグ&ドロップで並び替える (パート2)

こんにちは! 私の名前はチュンです。
株式会社メディアフュージョンでkintone関連製品の開発を担当しているベトナム出身のエンジニアです。
kintoneに興味のある方、kintoneを使っている方に私の蓄積した経験を共有したいと思います。
前回は、Excelのようにkintoneのテーブル行をドラッグ&ドロップで並び替える方法をご紹介しました。ただし、これはあくまで画面上の操作であり、並び替えた順番は保存されません。
前回記事; kintoneでテーブルの行をドラッグ&ドロップで並び替える(パート1)
今回の記事では、ドラッグ&ドロップで並び替えた行の順番をレコードに保存する方法をご紹介します。

プログラムの処理手順
- jQuery UIのsortableを使って、テーブルの行をドラッグ&ドロップ可能にする。
- 行を移動する前と後のインデックス(oldIndex と newIndex)を記録する。
- kintone.app.record.get() を使って、現在のレコードのデータを取得する。
- oldIndex → newIndex に従って、レコード内の行の順番を入れ替える。
- kintone.app.record.set() を使って、変更後のデータをレコードに保存する。
ソースコード
(() => {
'use strict';
// フォームデータの取得
let FORM_DATA = cybozu.data.page['FORM_DATA'];
let ELEMENT_FIELD_ID = {};
let fieldList = FORM_DATA.schema.table.fieldList;
for (let fieldId of Object.keys(fieldList)) {
ELEMENT_FIELD_ID[fieldList[fieldId].var] = fieldId;
}
for (const subTableId of Object.keys(FORM_DATA.schema.subTable)) {
ELEMENT_FIELD_ID[FORM_DATA.schema.subTable[subTableId].var] = subTableId;
}
// レコード作成・編集画面を表示したときに発火するイベント
kintone.events.on([
'app.record.create.show', 'app.record.edit.show'
], (event) => {
let tableHTML = $(`.subtable-${ELEMENT_FIELD_ID['注文一覧']}`);
let oldIndex; // ドラッグ開始時の行インデックスを記録するための変数
// jQuery UIのsortable機能を適用(ドラッグ&ドロップ可能にする)
tableHTML.sortable({
items: "tr", // 各テーブル行を対象に
cursor: "move", // カーソルを移動アイコンに
axis: "y", // 縦方向のみ移動可能
// ドラッグ開始時の処理
start: function(event, ui) {
// 選択行にスタイル適用(視覚的にわかりやすくする)
ui.item.css({
"background-color": "#fff9c4",
"box-shadow": "0 4px 10px rgba(0, 0, 0, 0.2)"
});
// 移動前のインデックスを記録
oldIndex = ui.item.index();
},
// ドラッグ終了時の処理
stop: function(event, ui) {
const newIndex = ui.item.index(); // 移動後のインデックス
// スタイルをリセット
ui.item.css({
"background-color": "",
"box-shadow": ""
});
// kintoneレコードデータの取得
let record = kintone.app.record.get().record;
// サブテーブルのデータをロジック上で並び替え
let movedItem = record["注文一覧"].value.splice(oldIndex, 1)[0]; // 移動対象を一旦削除
record["注文一覧"].value.splice(newIndex, 0, movedItem); // 新しい位置に挿入
// 並び替えた内容をkintoneレコードに反映
kintone.app.record.set({record: record});
}
});
return event;
});
})();
最初の結果

データの保存には成功しましたが、ドラッグ&ドロップの動作が正しくありませんでした。
調査の結果、原因は kintone.app.record.set() がデータを更新すると同時に、画面にもその変更を反映するため、jQuery UI の sortable 機能と競合してしまうことにあると判明しました。
解決策
jQuery UI の sortable 機能によるドラッグ&ドロップの操作は、行の新しい位置(インデックス)を記録する目的でのみ使用し、DOM 上の HTML 要素の順番は実際には変更しないようにします。
そのために、sortableのstopイベント内で $(this).sortable('cancel'); を追加し、HTML要素の並び替えを無効化します。
stop: function(event, ui) {
const newIndex = ui.item.index();
ui.item.css({
"background-color": "",
"box-shadow": ""
});
// 実際のDOM移動をキャンセル(表示上のみドラッグ)
$(this).sortable('cancel');
let record = kintone.app.record.get().record;
let movedItem = record["注文一覧"].value.splice(oldIndex, 1)[0];
record["注文一覧"].value.splice(newIndex, 0, movedItem);
kintone.app.record.set({record: record});
}
最終結果

次回の記事では、kintoneの画面をExcelのようにシートで分割する方法をご紹介します。どうぞお楽しみに!