サブテーブルの並び替え

にメンテナンス済み

kintone のサブテーブル機能を使用すると、レコード内で 1:n の関係を表現できます。

便利な機能ですが、行数が増えると見づらくなります。例えば、日付と内容のフィールドを持つサブテーブルでタスクを管理している場合、行を追加し続けるだけでは、最新のタスクを探しにくくなります。

この記事では、サブテーブルの行を指定したフィールドの値で並び替え、保存する JavaScript カスタマイズを紹介します。

2 つの行を比較する関数を作成

まず、2 つの行の大小を比較する関数を作成します。

引数と返り値は、Array.prototype.sort() の比較関数に合わせます。

以下は、サブテーブル内の日付フィールドを降順(新しい順)に並び替える例です。

const compareRows = (rowA, rowB) => {
  const timeA = new Date(rowA.value['日付フィールド'].value).getTime();
  const timeB = new Date(rowB.value['日付フィールド'].value).getTime();

  return timeB - timeA;
};

昇順(古い順)にする場合は、timeA - timeB を返します(未入力の行の扱いは次の注意を参照)。

未入力の行に注意

日付フィールドが未入力の行は値が空文字列になり、new Date('').getTime() は NaN を返します。NaN を含む比較は結果が不定になり、並び順が崩れる原因になります。未入力の行を末尾にまとめたい場合は、NaN を -Infinity に置き換えるなどの処理を加えてください。

const toTime = (value) => {
  const time = new Date(value).getTime();
  return Number.isNaN(time) ? -Infinity : time;
};

const compareRows = (rowA, rowB) => {
  const timeA = toTime(rowA.value['日付フィールド'].value);
  const timeB = toTime(rowB.value['日付フィールド'].value);

  if (timeA === timeB) {
    return 0;
  }
  return timeA < timeB ? 1 : -1; // 降順。未入力の行は末尾になる(昇順にする場合は 1 と -1 を入れ替える。未入力の行は先頭になる)
};

なお、-Infinity - -Infinity は NaN になるため、上記のように引き算ではなく大小比較で書いています。

ソート処理を実装

続いて、サブテーブルを並び替える処理を記述します。sort() は配列を直接書き換えるため、戻り値を受け取る必要はありません。

サブテーブルの行は event.record['フィールドコード'].value に配列として格納されています。ここで指定するのは、フィールドIDではなくフィールドコードです。

kintone.events.on のコールバック関数内で実行する場合

レコードの保存時に自動で並び替えるには、保存実行前イベントを利用します。

kintone.events.on(['app.record.create.submit', 'app.record.edit.submit'], (event) => {
  event.record['サブテーブルのフィールドコード'].value.sort(compareRows);

  return event;
});

return event を忘れると、変更がレコードに反映されません。

独自のタイミングで実行する場合

ボタンのクリック時など、イベントのコールバック関数の外で実行する場合は、event オブジェクトを使えません。kintone.app.record.get() でレコード情報を取得し、並び替えたあとに kintone.app.record.set() で画面に反映します。

/** 実行時のレコード情報 */
const { record } = kintone.app.record.get();

// サブテーブルの行を並び替え
record['サブテーブルのフィールドコード'].value.sort(compareRows);

// レコード情報をセット
kintone.app.record.set({ record });
利用できる画面

kintone.app.record.set() は、レコードの追加・編集画面でのみ利用できます(get() は詳細画面でも利用できます)。set() は画面上の値を書き換えるだけで、保存は行いません。変更を確定するには、ユーザーがレコードを保存する必要があります。

#JavaScript #kintone