2024年7月16日火曜日

インライン・ポップアップの表示位置を動的に変更する

対話モード・レポートのセルの位置に合わせて、インライン・ポップアップを表示させてみます。実装例として、サンプル・データセットEMP/DEPTの表EMPに含まれる列SALの値を、インライン・ポップアップを開いて変更できるようにします。

実装については、Philipp Hartenfellerさんによる以下の記事を参考にしています。
Oracle APEX anchored inline popups for data input
https://hartenfeller.dev/blog/apex-anchored-inline-popups

作成したサンプルは以下のように動作します。


表EMPをソースとした対話モード・レポートのページをひとつだけ含むAPEXアプリケーションを作成し、そのページにインライン・ポップアップを実装します。


ページ・デザイナで対話モード・レポートを含むページを開きます。

対話モード・レポートに静的IDとしてEMPを設定します。

インライン・ポップアップの表示位置を決める際に、仮の親エレメントとして対話モード・レポートのリージョンを使います。そのために対話モード・レポートに静的IDを設定します。


インライン・ポップアップを開く際に渡す従業員番号を保持するページ・アイテムとして、P1_EMPNOを作成します。タイプ非表示とします。動的アクションから設定するため、設定保護された値オフにします。画面上に保持されていればよいので、セッション・ステートストレージリクエストごと(メモリーのみ)を選択します。


給与の更新に失敗することがあります。表示するエラー・メッセージを保持するページ・アイテムとして、P1_ERRORを作成します。


更新する給与を指定する、インライン・ポップアップのリージョンを作成します。

識別名前Update Salaryタイプ静的コンテンツとします。レイアウトスロットDialogs, Drawers and Popupsを選択します。外観テンプレートとしてInline Popupを選択します。

JavaScriptのコード(APEXアクション)からインライン・ポップアップのリージョンを開くため、詳細静的IDとしてUPDATE_SALARYを設定します。

カスタム属性としてdata-parent-emelemt="#EMP"を指定します。インライン・ポップアップの表示位置は#EMP、つまり対話モード・レポートのリージョンではありませんが、data-parent-element評価はページ・ロード時に行われるため、ページ・ロード時に必ず存在しているHTML要素をdata-parent-elementに指定することにより、Popup Calloutの表示が適切に行われるように初期化します。


テンプレート・オプションを設定します。

Auto HeightDisplay Popup Calloutにチェックを入れます。サイズNoneCallout PositionDefaultとします。


Remove Page Overlayのチェックを外します。

Remove Page Overlayチェックを外すと、インライン・ポップアップが開いたときにバックグラウンドがグレーに変わり、給与のリンクを含むバックグラウンドのどの位置をクリックしても、一旦ポップアップが閉じます。


Remove Page Overlayチェックが入っていると、バックグラウンドはグレーアウトせず、給与のリンクをクリックすると、すでに開いているポップアップが閉じて新たにポップアップが開きます。


この操作を行うと、インライン・ポップアップの表示位置がずれます。位置のずれが気になる場合は、Remove Page Overlayのチェックを外します。


Display Popup Calloutチェックが入っていると、ポップアップに親エレメントを指す山が表示されます。


別セッションで給与が更新されている場合に上書き更新を避けるため、変更前の給与を保持するページ・アイテムP1_SAL_OLDを作成します。

識別タイプ非表示設定保護された値オフにします。外観書式マスクには、対話モード・レポートの列SALに設定されている書式マスクと同じ値を設定します。セッション・ステートストレージは、リクエストごと(メモリーのみ)です。


更新する給与を入力するページ・アイテムとしてP1_SALを作成します。

タイプ数値フィールドラベルSalaryとします。外観書式マスクP1_SAL_OLDと同様に、対話モード・レポートの列SALに合わせます。セッション・ステートストレージリクエストごと(メモリーのみ)です。


給与の更新を実行するボタンUPDATE_SALARYを作成します。動作アクションに、動的アクションとして定義を選びます。


動的アクション識別名前Update Salaryとします。ボタンのクリックで実行します。


最初のTRUEアクションでPL/SQLコードを実行し、給与を更新します。アクションとしてサーバー側のコードを実行を選択し、設定PL/SQLコードとして以下を記述します。

送信するアイテムとして、P1_EMPNOP1_SAL_OLDP1_SAL戻すアイテムとしてP1_ERRORを設定します。実行初期化時に実行オフです。


PL/SQLの実行でエラーが発生すると、表示すべきエラー・メッセージがP1_ERRORに戻されます。続くアクションを作成し、識別名前エラーの表示タイプとしてJavaScriptコードの実行を選択します。クライアント側の条件タイプアイテムはnullではないアイテムとしてP1_ERRORを指定することで、エラー・メッセージが返された場合に限り、エラー・メッセージを表示します。

設定コードに以下を記述します。



給与の更新に成功した場合(エラー・メッセージのアイテムP1_ERRORがnullの場合)、インライン・ポップアップのリージョンを閉じます


最後に給与の更新の有無に関わらず、対話モード・レポートをリフレッシュします。


対話モード・レポートの列SALをクリックしたときに、インライン・ポップアップを開くAPEXアクションを実行します。

SAL列の書式HTML式に以下を記述します。カスタム属性のdata-actionに、APEXアクションopen-update-salaryを呼び出す指定をします。


SALのセルをクリックしたときに呼び出されるAPEXアクションを設定します。

ページ・プロパティJavaScriptページ・ロード時に実行に、以下を記述します。Popup Calloutの表示が不要であれば、親エレメントの指定は若干簡単になります。


表示されているインライン・ポップアップをよく見ると、余計な下線が見つかります。


この下線はポップアップのminHeightの設定が表示されているみたいなので、ポップアップの表示前に以下の一行を入れることにより、表示されないようにできます。

popup.options.minHeight = null;

以上で実装は完了です。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/locating-inline-popup.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。