2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

プリザンターの拡張機能だけで一覧画面に選択件数カウンターを実装してみる

2
Posted at

はじめに

プリザンターの一覧画面では、チェックボックスでレコードを選択して一括削除や一括更新などの操作を行うことができます。しかし、現在何件のレコードが選択されているかはチェックボックスを一つ一つ数えてみないと分かりません。特にレコード数が多い一覧画面をスクロールした場合、選択状況を把握しにくくなります。

今回は拡張スクリプトと拡張スタイルだけで「○件選択中」というメッセージをリアルタイムに表示する機能を実装してみます。

バージョン 1.5.1.0 以降を対象にしています

チェックボックスの仕組みを見てみる

まず、一覧画面のチェックボックスがどのような HTML 要素で構成されているかを確認してみましょう。

ヘッダーの全選択チェックボックス

<th>
  <input id="GridCheckAll" type="checkbox">
</th>

ヘッダー行には id="GridCheckAll" のチェックボックスがあり、クリックすると表示中の全行の選択・解除が切り替わります。

各行のチェックボックス

<tr class="grid-row" data-id="123">
  <td>
    <input class="grid-check" data-id="123" type="checkbox">
  </td>
  <!-- 他の列 -->
</tr>

各データ行には class="grid-check" のチェックボックスがあり、data-id 属性にレコード ID が格納されています。

イベントの流れ

プリザンターの組み込みスクリプト(gridevents.js)を見ると、チェックボックスのイベント処理は次のように動作しています。

操作 発生するイベント 備考
個別チェック .grid-checkchange チェックボックスを直接クリックした場合
行クリック .grid-checkchange セルをクリックするとチェックが切り替わり change が発火する
全選択チェック #GridCheckAllclick .grid-checkchange発火しない

全選択チェックボックスをクリックした場合、各行の .grid-check に対しては prop('checked', ...) で直接状態が設定されるため、change イベントは発火しません。この点は実装時に注意が必要です。

表示方法を考えてみる

表示位置

選択件数の表示にはプリザンター組み込みの $p.setMessage を使い、画面上部のメッセージ領域(#Message)に表示します。保存時の「更新しました」などと同じ領域なので、ユーザーにとって見慣れた場所に自然に表示されます。

表示スタイル

$p.setMessage の第 2 引数に渡す JSON で CSS クラスを指定できます。今回は alert-information(青色の情報メッセージ)を使用します。

CSS クラス 用途
alert-success 成功通知
alert-information 情報メッセージ
alert-warning 警告
alert-error エラー

拡張機能で実装してみよう

組み込みの $p.setMessage を使うため、拡張スクリプト(JS ファイル)だけで実装できます。拡張スタイルは不要です。

拡張スクリプト

チェックボックスの状態変化を検知し、$p.setMessage でカウンターメッセージを表示するスクリプトです。

ExtendedScripts/SelectionCounter.js
(function () {
  /**
   * チェック済みの件数を数えてメッセージの表示を更新する。
   */
  function updateCounter() {
    var count = document.querySelectorAll('.grid-check:checked').length;
    if (count > 0) {
      $p.clearMessage();
      $p.setMessage('#Message', JSON.stringify({
        Css: 'alert-information',
        Text: count + '件選択中'
      }));
    } else {
      $p.clearMessage();
    }
  }

  // 個別チェックボックスの変更
  $(document).on('change', '.grid-check', updateCounter);

  // 全選択チェックボックスのクリック
  // (組み込みの click ハンドラで .grid-check の状態が更新された後にカウントするため遅延)
  $(document).on('click', '#GridCheckAll', function () {
    setTimeout(updateCounter, 0);
  });

  // Ajax によるグリッド再描画(ソート・フィルタ・ページ移動など)
  // (DOM の更新完了後にカウントするため遅延)
  $(document).ajaxComplete(function () {
    setTimeout(updateCounter, 0);
  });

  // 初期表示
  updateCounter();
})();

各処理のポイント

$p.setMessage による表示

$p.setMessage は第 1 引数に表示先のセレクタ、第 2 引数に CssText を含む JSON 文字列を渡します。組み込みのメッセージ表示と同じ仕組みなので、DOM 要素の生成や挿入を自前で行う必要がありません。選択が 0 件になったときは $p.clearMessage() でメッセージを消去しています。

$p.setMessage はメッセージ領域の内容を上書きするため、保存直後の「更新しました」などの組み込みメッセージもチェックボックス操作時に置き換わります。実用上は一覧操作中に保存メッセージが残り続けることは少ないため、大きな問題にはなりにくいでしょう。

#GridCheckAll のハンドリング

全選択チェックボックスの組み込み処理では、.grid-check に対して prop('checked', ...) で直接チェック状態を変更しています。これにより個別のチェックボックスでは change イベントが発火しないため、#GridCheckAllclick イベントを別途監視しています。

setTimeout(updateCounter, 0) を使用しているのは、組み込みの click ハンドラが先に実行されて .grid-check の状態が更新された後にカウントを取得するためです。

ajaxComplete のハンドリング

一覧画面ではソート、フィルタ、ページ移動などの操作で Ajax によるグリッドの再描画が行われます。再描画後はチェックボックスの状態がリセットされるため、ajaxComplete でカウンターを更新しています。

$p.selectedIds() を使わない理由

プリザンターには選択中のレコード ID を取得する $p.selectedIds() 関数がありますが、この関数は内部で同期的な Ajax 通信を行っています。チェックボックスの変更のたびにサーバーへリクエストを送信すると不要な負荷がかかるため、今回は DOM のチェックボックス要素を直接カウントする方法を採用しています。

まとめ

プリザンターの拡張スクリプトと拡張スタイルだけで、一覧画面の選択件数をリアルタイムに表示する機能を実装しました。

  • 組み込みの $p.setMessagealert-information スタイルを使うことで、拡張スクリプトだけで実装でき、拡張スタイルが不要です
  • チェックボックスの change イベントと全選択の click イベントの両方を監視することで、すべての操作に対応しています
  • Ajax による再描画にも ajaxComplete で対応しているため、ソートやフィルタ操作後も正しく動作します
  • $p.selectedIds() ではなく DOM を直接参照することで、サーバーへの不要なリクエストを避けています

組み込みのイベント処理の仕組みを理解しておくことで、チェックボックスと連携したカスタマイズをスムーズに行うことができます。皆さんも是非試してみてください。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?