Skip to content

一覧のページネーション(ページ切り替え) ​

第1版作成 最終更新 (日本時間)
確認バージョン1.5.8.1

一覧画面は、スクロールで次の件数を読み足す方式(無限スクロール)です。これを「前へ・次へ・ページ番号」で切り替える方式に変える場合の設計メモです。本体の標準機能ではありません。

現行の仕組み(1.5.8.1)は 内部で動く SQL 文 > 画面側の追加読み込み にまとめています。改修に関係する点だけ挙げます。

  • 1 回に読む件数はサイト設定の GridPageSize(テーブルの管理 > 一覧の「ページ当たりの表示件数」、既定 20、10〜200)で、設定画面はすでにある。ページネーション後は「1 ページの件数」としてそのまま使える
  • GridData はすでに offset・pageSize を受け取り、全件数(TotalCount)も数えている。SQL(OFFSET ... FETCH NEXT、MySQL は LIMIT ... OFFSET)は変えなくてよい
  • 変える中心は、応答の Append(末尾に足す)を「入れ替え」にすることと、スクロール検知をやめてページ切り替えの UI を足すこと

改修の方針 ​

text
┌──────────────────────────────────────────┐
│ 一覧(1 ページ分)                         │
└──────────────────────────────────────────┘
  ◀ 前へ  [1] [2] [3] … [10]  次へ ▶   全 200 件(20 件/ページ)

ページ番号 page から offset = (page - 1) × GridPageSize を作って、今と同じ GridOffset で GridRows に送ります。サーバー側は GridOffset の受け取り方を変えなくて済みます。

改修箇所 ​

フロントエンド ​

ファイルは Implem.PleasanterFrontend/wwwroot/src/scripts/generals/ 配下です。

ファイル改修内容
scroll.js$p.paging()・$p.dashboardPaging() のスクロール判定をやめる
observer.js$p.pageObserve() の IntersectionObserver をやめる
grid.js$p.setGrid() から $p.pageObserve('Grid') を外す。ダッシュボードの scroll resize も同様
scrollevents.js、responsive.jsダッシュボードとレスポンシブ表示のスクロール読み込みをやめる
_dispatch.jsPaging 応答の処理を、ページ切り替え UI の更新に変える
新規 pagination.jsページ番号・前へ・次へのクリックで #GridOffset を設定して $p.send() する
新規のスタイル現在のページの強調、押せないボタンの表示
js
$p.gridPagination = function (page, suffix) {
    suffix = suffix || '';
    var pageSize = parseInt($('#GridPageSize' + suffix).val());
    var $offset = $('#GridOffset' + suffix);
    $offset.val((page - 1) * pageSize);
    $p.setData($offset);
    $p.send($('#Grid' + suffix));
};

#GridPageSize は現行の一覧画面には無いので、ページ切り替えの HTML と一緒に出す必要があります。

サーバー側 ​

対象改修内容
各モデルの GridRows()(Issues・Results・Sites・Users・Groups・Depts・SysLogs・Registrations・Dashboards など)Remove(".grid tr", _using: offset == 0) と Append("#Grid", …) を、ページ単位の入れ替え(ReplaceAll や Html)にする。Paging("#Grid") をやめ、ページ切り替えの HTML を返す
同上Val("#GridOffset", …) は残し、現在のページと総ページ数も返す
ResponseCollectionページ切り替えの更新用のメソッドを足すか、既存の Html() で領域を入れ替える
SiteSettings.GridNextOffset()任意のページへ飛ぶので「次の値」ではなく、ページから計算した値を使う
HtmlGrids.cs または各モデルの Grid()一覧の下にページ切り替えの領域(例: <div id="GridPagination">)を出す。初回は 1 ページ目、総ページ数は ceil(TotalCount / GridPageSize)
DashboardUtilitiesダッシュボードの一覧パーツにもサフィックス付き(#GridPagination_{サフィックス})で同じものを出す
PublishesController.GridRows公開テーブルの一覧も同じ改修が要る

1.5.8.1 の IssueUtilities.GridRows() の応答は IssueUtilities.cs です。GridRows アクションは ItemsController のほか、UsersController・GroupsController・DeptsController・SysLogsController・RegistrationsController・PublishesController・BackgroundJobsController・McpLogsController にもあります。

CodeDefiner の生成対象

Models/ 配下の *Utilities.cs や ItemModel.cs は CodeDefiner のテンプレートから生成されるコードを含みます。生成コードだけを直すと再生成で消えるので、テンプレート側も直してください。

ソート・フィルタとの関係 ​

ソートやフィルタを変えたら 1 ページ目に戻します。現行でも GridOffset が 0(送られない場合も含む)のときは先頭から描き直すので、この動きはそのまま使えます。

ページ番号をどこで持つか ​

現行の一覧は、ソートやフィルタの状態をサーバーのセッション(Views.GetBySession())に持ち、URL には入れていません。GridRows へは /items/{siteId}/gridrows への POST で、GridOffset はフォームの値として送ります。ビューモードの切り替えなどではすでに history.pushState を使っていて、popstate のハンドラもあります。

方式 A: URL のクエリ(pushState で ?page=N) ​

図を読み込み中…

改修箇所は、ページ切り替え時の pushState、navigationevents.js の popstate でのページ復元、ItemsController.Index と ItemModel での初回表示時の ?page=N の読み取り、各モデルの初回表示を 0 以外の offset で作れるようにすることです。

方式 B: Ajax の POST だけ(URL は変えない) ​

#GridOffset を設定して $p.send() するだけで、URL・セッション・popstate には触りません。改修は最小ですが、ページの位置は共有・ブックマークできず、戻るボタンでは一覧から離れます。

方式 C: セッションに保存(View にページを持たせる) ​

View に GridPage を足してセッションに保存します。再読み込みや「一覧 → 編集 → 一覧」で同じページに戻れます。View.SetByForm・Views.GetBySession / SetSession・各モデルの IndexHtml() と GridRows() を直し、フィルタ変更時に GridPage を 1 に戻す処理が要ります。ビューの定義として保存する必要はないので、RecordingData の対象からは外します。

比較 ​

観点A: URLB: Ajax のみC: セッション
URL 共有・ブックマーク◎✕✕
戻る・進む◎✕✕
再読み込みでページを保つ◎✕◎
編集画面から戻ったとき△(URL が変わると失われる)✕◎
改修の規模大小中
ソート・フィルタとの整合△(URL とセッションの二重管理)◎○

最小の改修なら B、画面から戻ったときにページを保ちたいなら C、URL の共有を重視するなら A です。A と C を組み合わせ、初回表示は ?page=N を優先し、無ければセッションから戻す方法もあります(改修は最大)。

関連ページ ​

変更履歴

第1版リンク項目の列指定と JOIN の組み立て、一覧のスクロール読み込みの解説と、一覧・カレンダー・サイトメニューまわりの改修・設計メモを追加