🚀

業務画面のグリッド列設定をテーブルで管理する設計パターン

に公開

はじめに

この記事では、業務画面でグリッドの列幅と列順を記憶する機能がなぜ効くのかを整理します。

一覧画面の改善というと検索速度や SQL 改善に目が向きがちですが、利用者が毎日触る画面では列幅と列順の記憶もかなり効きます。

特に jqGrid や SlickGrid のような表中心 UI では、この機能があるだけで体感が大きく変わります。

今回は、列設定をブラウザ保存ではなくバックエンド側のテーブルに保存し、さらに列順や列幅を初期状態へ戻すリセット処理も用意していたケースを前提に整理します。

結論から言うと、これは単なる便利機能ではなく、業務画面におけるユーザー設定管理の設計パターンとして扱った方が価値が出ます。

どういう実装か

考え方は単純です。

  • 利用者が列幅や列順を変える
  • その情報を API 経由で保存する
  • 次回表示時に保存内容を元に colModelcolumns を復元する
  • 必要に応じて保存済み設定を削除し、初期状態へ戻せるようにする

たとえば jqGrid 側では、保存済みの列情報を columnId ごとのマップにして、列幅と並び順を戻しています。

保存先はフロント側の localStorage ではなく、バックエンドのテーブルです。イメージとしては次のようなデータです。

user_id
screen_id
grid_id
column_id
col_width
col_order

このような構造なら、主キーや一意制約も素直に置きやすくなります。

  • user_id
  • screen_id
  • grid_id
  • column_id

たとえばこの4つを複合キーにすると、1ユーザーが1画面の1グリッドに対して1カラム1設定だけ持つ、という制約を表現できます。

参照時は user_id + screen_id + grid_id で取ることが多いため、この観点で index を考えると扱いやすくなります。

なぜこの機能が重要なのか

1. 一覧画面は毎日使う

業務システムの一覧画面は、たいてい毎日使います。

そのたびに利用者が次をやり直していると、地味に負担が積み上がります。

  • よく見る列を左へ寄せる
  • 不要な列を後ろへ送る
  • 長い項目だけ幅を広げる

1回の操作は小さくても、毎日繰り返されると無視できません。

一覧画面の UX は、1回の短縮時間よりも、利用頻度との掛け算で効きます。

たとえば列調整に毎回 10 秒かかる画面を、1日 20 回開くとします。これだけで 200 秒です。1回だけ見ると小さな差でも、毎日の業務では無視しにくくなります。

検索性能改善のような大きな改善ももちろん重要です。ただ、一覧画面では「何度もやる小さな操作」を消す方が体感改善につながることがあります。

2. 利用者ごとに見たい列が違う

同じ画面でも、現場担当、管理者、サポート担当では見たい列が違います。

そのため、固定レイアウトだけでは最適化しきれません。

ユーザー単位で記憶できると、画面を個人最適化できます。

3. UX 改善の割に実装コストが低い

検索ロジックや DB を触る改善に比べると、列幅・列順記憶は導入コストが低いことがあります。

それでも利用者の体感は大きく変わります。

これはユーザー設定テーブルの設計パターンでもある

この機能を単なる UI 改善として終わらせるのは少しもったいないです。

実際には、次のようなユーザー設定管理のパターンとして見た方が再利用しやすくなります。

  • ユーザー単位で持ちたい設定を保存する
  • 画面単位で設定対象を分ける
  • システム初期値と個別設定を重ねる
  • 必要に応じて組織単位のデフォルト設定も入れる

列幅・列順の記憶は、その典型例です。

このパターンは、次の設定にも応用できます。

  • ページサイズ
  • 一覧の初期ソート
  • 表示カラムの ON/OFF
  • 既定タブ
  • 検索フォームの初期値

サーバー保存にする理由

ブラウザ保存でも動きますが、業務システムではバックエンドのテーブルに保存する方が扱いやすいことがあります。

  • 別端末でも復元したい
  • 共用端末を使う
  • ユーザー単位で設定を持ちたい
  • 画面 ID とグリッド ID で一意に管理したい

この用途では、サーバー保存の方が自然です。

特に一覧画面が多いシステムでは、列設定をテーブルで持つと管理しやすくなります。どのユーザーが、どの画面の、どのグリッドに対して何を保存しているかを明確に表現できるためです。

もう1つ大きいのは、会社全体や部門全体のデフォルト表示を後から変えやすいことです。

たとえば次のような要望です。

  • この会社ではこの列を先頭にしたい
  • この部門ではこの列は広めに表示したい
  • この一覧では最初からこの順番で見せたい

こうした要望は、フロントコードに並び順を埋め込むより、テーブル側でデフォルト設定として持っておく方が対応しやすくなります。

実装によっては、次のような優先順位にできます。

  1. ユーザー個別設定
  2. 会社や部門のデフォルト設定
  3. システム初期値

この構造を取れるのは、設定をバックエンドで管理している利点です。

こうしておくと、たとえば新しい会社を導入したときに「この会社だけ初期列順を変える」といった要望にも対応しやすくなります。

JSON で持つか、正規化して持つか

ここは設計判断が分かれるところです。

正規化して持つ場合

今回のように column_id / col_width / col_order 単位で持つ方法です。

良い点は次のとおりです。

  • 一部の列だけ更新しやすい
  • 差分確認がしやすい
  • 一意制約を張りやすい

弱い点は次のとおりです。

  • レコード数が増える
  • 保存処理が少し冗長になる

JSON でまとめて持つ場合

1画面1グリッドぶんを JSON でまとめて持つ方法もあります。

良い点は次のとおりです。

  • 1件で保存できる
  • 取得処理が単純になる

弱い点は次のとおりです。

  • 一部変更がしにくい
  • 列追加時の差分管理が雑になりやすい
  • DB 制約を活かしにくい

列記憶のように「列単位」で扱うことがはっきりしているなら、正規化して持つ方が後で困りにくいです。

実装でハマりやすい点

1. 列追加や列名変更に弱い

保存は columnId ベースで行うことが多いため、列名変更や削除が入ると復元処理が壊れやすくなります。

そのため、未保存の列は末尾に回す、存在しない列は無視する、といったフォールバックが必要です。

2. jqGrid と SlickGrid で形が違う

同じ「列記憶」でも、jqGrid と SlickGrid では持っている構造が違います。

そのため、保存 API は共通でも、フロント側の復元処理は別実装になりやすいです。

3. リセット手段が必要

記憶機能だけ入れても、壊れた設定を戻せないと運用がつらくなります。

初期状態へ戻すボタンや、サーバー側の削除 API はセットで必要です。

実際に運用すると、次のような場面でリセットが必要になります。

  • 列を入れ替えすぎて見づらくなった
  • 列追加後に並びが崩れた
  • 画面改修後に昔の保存内容が合わなくなった

このとき、保存テーブルのデータを削除して初期状態へ戻せると運用がかなり楽になります。

たとえば画面側では、次のように「削除 API を呼ぶ -> 完了ダイアログを出す -> 初期順へ戻す」という流れを作れます。

function setupJqGridColumnWidthResetButton(buttonId, gridId, screenId, originalOrder) {
    $(`#${buttonId}`).click(async () => {
        await deleteGridColumnMemory(screenId, gridId);
        await showDialog(dictWords['column_width_reset_completed']);

        let currentColModel = getJqGridColumnModel(gridId);
        let nameToColIndex = createJqGridColumnIndexMap(currentColModel);
        let columnMap = getJqGridColumnOrderMap(originalOrder, nameToColIndex);

        resetJqGridColumnOrder(gridId, columnMap);
    });
}

このように、記憶機能は保存処理だけで完結しません。削除と初期化まで含めて設計した方が壊れにくくなります。

ここは業務運用上かなり重要です。利用者ごとの設定を持つ以上、壊れたときに戻せることまで含めて初めて運用可能になります。

記憶する価値が高いもの

列幅・列順のほかにも、一覧画面では次を記憶すると効果があります。

  • ソート条件
  • ページサイズ
  • フィルタ条件
  • 表示中のタブ

ただし、何でも記憶すると逆に分かりにくくなります。まずは列幅・列順のように、利用者が手で毎回調整しているものから始めるのが安全です。

まとめ

グリッドの列幅と列順の記憶は地味ですが、業務画面ではかなり効く改善です。

特に次の点で価値があります。

  1. 毎日の微調整を減らせる
  2. 利用者ごとの見やすさに合わせられる
  3. バックエンドのテーブルで管理すると端末をまたいで復元できる
  4. リセット機能まで入れると運用しやすい

一覧画面の改善は、派手な新機能よりも「毎日やっている小さな面倒を消す」方が効くことがあります。列記憶はその代表例です。

そして実務では、保存できること以上に、壊れたときに戻せることが重要です。列幅と列順の記憶は、保存と復元だけでなく、削除と初期化まで含めて設計すると運用しやすくなります。

さらに、設定をテーブルで持っていれば、個人最適化だけでなく、会社や部門ごとのデフォルト表示を後から調整しやすくなります。ここまで含めると、列記憶は単なる UI 便利機能ではなく、業務運用を支える設定機構として価値が出ます。

列幅と列順の記憶は、見た目の小さな改善に見えますが、実際には「頻度の高い一覧画面の操作コストを減らす」「ユーザー設定をバックエンドで管理する」「組織単位の初期値まで扱える」という複数の価値を持っています。

そのため、この機能はフロントの小ネタではなく、ユーザー設定テーブル設計の実践例として捉えた方が再利用しやすくなります。

Discussion