kintoneのサブテーブルの行を入れ替える技

今回は、サブテーブルの行入れ替えをするカスタマイズです。
※DOM操作をするカスタマイズです。kintoneの仕様変更などで使えなくなる可能性があります。また、サブテーブルは1つだけにしておいてください🙏


↓できあがりはこんな感じになります。

![rowswap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/f9527bb0-526a-4ac4-6f87-a3b97f7fccd7.gif)



# アプリの準備

下図のようなサブテーブルを作ります。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/01a0892c-8e6b-44e0-c013-dc254ae05cd7.png)


| フィールド種類 |フィールドコード | 備考 |
|:-:|:-:|:-:|
| テーブル  | テーブル  |   |
| ルックアップ  | ルックアップ  | ルックアップ設定をお忘れなく  |
| 文字列(1行)  | 文字  | ルックアップ設定、「他のフィールドのコピー」で指定  |
| 文字列(1行)  | メモ  |   |

※ルックアップ呼び出し元は何でも良いので適当なマスタアプリを作ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/5d991bb7-03cf-afa8-508d-a80bab6432e0.png)



# JavaScript

まず、`JavaScript / CSSでカスタマイズ`に
Cybozu CDN のページから　jQuery と jQuery UI のURLをコピペしてに追加しておきます。

https://developer.cybozu.io/hc/ja/articles/202960194-Cybozu-CDN

jQuery: `https://js.cybozu.com/jquery/3.6.0/jquery.min.js`
jQueryUI: `https://js.cybozu.com/jqueryui/1.12.1/jquery-ui.min.js`

## 自分で書くコード

行入れ替えのしくみですが、
1. 追加編集画面を開いたときにDOM操作で、サブテーブルの行<tr>タグに、上から0, 1, 2, ...となるidを付与します。
2. 並び替えは後に一旦表示上のフィールド値を保存（kintone.app.record.set(obj)）して、
3. フィールド値変更や、行の追加削除イベントでは変更した値を保存しておきます。（resultTableValues）
4. 次に並び替えが発生したときはresultTableValuesを並び替えてkintone.app.record.set(obj)します。

コレで行の入れ替えができます。
`JavaScript / CSSでカスタマイズ`に追加するのをお忘れなく！

※2012/8/12追記
動かない場合は
コメントでいただいておりますように、
11行目「st.rows.forEach((r, idx) => 」を「Array.prototype.forEach.call(st.rows, function(r, idx) {」に変えてみてくださいね👀✨✨

```js
"use strict";
(() => {
    "use strict";
    // 編集イベントが発生するたびに更新内容を入れとくもの
    let resultTableValues = [];

    // DOM操作。<tbody>と<tr>にidをつける
    const setRowNum = () => {
        let st = document.querySelector("tbody");
        st.id = "st";
        st.rows.forEach((r, idx) => {
            r.id = idx;
        });
    };

    // 追加／編集画面
    kintone.events.on(["app.record.create.show", "app.record.edit.show"], (event) => {
        setRowNum();
        // 初期値は最初のレコード情報
        resultTableValues = event.record.テーブル.value;
        // ドラッグ＆ドロップで入れ替えたら動く
        $("#st").sortable({
            update: (event, ui) => {
                const tmpRows = [];
                // 並び替え後のソート順のとおりに、resultTableValuesの行をtmpRowsにpush入れる
                $("#st").sortable("toArray").forEach((element) => {
                    // ルックアップの取得を忘れずに
                    resultTableValues[Number(element)].value.ルックアップ.lookup = true;
                    // 並び替え後のテーブル作成
                    tmpRows.push(resultTableValues[Number(element)]);
                });
                // 完成した並び替え後のテーブル（tmpRows）をresulutTableValuesに入れ直す
                resultTableValues = tmpRows;
                // 画面表示中のレコードの値を更新する
                const r = kintone.app.record.get();
                // 一回クリアしないとゴミが残る？ようなので一旦クリアする
                r.record.テーブル.value = [];
                kintone.app.record.set(r);
                // 画面表示中レコードを並び替え後のテーブルで更新する
                r.record.テーブル.value = resultTableValues;
                kintone.app.record.set(r);
                // 並び替えたらDOM操作でid振り直す
                setRowNum();
            },
        });
        return event;
    });

    // サブテーブルの行追加＆削除
    kintone.events.on(["app.record.create.change.テーブル", "app.record.edit.change.テーブル"], (event) => {
        // <tr>に番号をふりなおす
        setRowNum();
        // 行追加＆削除したテーブルでresultTableValuesを更新しておく
        resultTableValues = event.record.テーブル.value;
        return event;
    });

    // サブテーブル内フィールド値更新
    kintone.events.on([
        "app.record.create.change.メモ",
        "app.record.edit.change.メモ",
        "app.record.create.change.文字",
        "app.record.edit.change.文字",
    ], (event) => {
        // resultTableValuesをフィールド値更新後の内容にする
        resultTableValues = event.record.テーブル.value;
        return event;
    });
})();
```

# まとめ

ドラッグ＆ドロップで行の入れ替えができると色々嬉しいかも知れません。
元々ある部品をDOM操作するのでそんなにオススメできる技ではないのですが、是非試してみてね✨✨