実装については、Philipp Hartenfellerさんによる以下の記事を参考にしています。
Oracle APEX anchored inline popups for data input
https://hartenfeller.dev/blog/apex-anchored-inline-popups
https://hartenfeller.dev/blog/apex-anchored-inline-popups
作成したサンプルは以下のように動作します。
ページ・デザイナで対話モード・レポートを含むページを開きます。
対話モード・レポートに静的IDとしてEMPを設定します。
インライン・ポップアップの表示位置を決める際に、仮の親エレメントとして対話モード・レポートのリージョンを使います。そのために対話モード・レポートに静的IDを設定します。
給与の更新に失敗することがあります。表示するエラー・メッセージを保持するページ・アイテムとして、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 Height、Display Popup Calloutにチェックを入れます。サイズはNone、Callout PositionはDefaultとします。
Remove Page Overlayのチェックを外します。
Remove Page Overlayのチェックを外すと、インライン・ポップアップが開いたときにバックグラウンドがグレーに変わり、給与のリンクを含むバックグラウンドのどの位置をクリックしても、一旦ポップアップが閉じます。
Remove Page Overlayにチェックが入っていると、バックグラウンドはグレーアウトせず、給与のリンクをクリックすると、すでに開いているポップアップが閉じて新たにポップアップが開きます。
この操作を行うと、インライン・ポップアップの表示位置がずれます。位置のずれが気になる場合は、Remove Page Overlayのチェックを外します。
Display Popup Calloutのチェックが入っていると、ポップアップに親エレメントを指す山が表示されます。
識別のタイプは非表示、設定の保護された値はオフにします。外観の書式マスクには、対話モード・レポートの列SALに設定されている書式マスクと同じ値を設定します。セッション・ステートのストレージは、リクエストごと(メモリーのみ)です。
動的アクションの識別の名前はUpdate Salaryとします。ボタンのクリックで実行します。
この下線はポップアップのminHeightの設定が表示されているみたいなので、ポップアップの表示前に以下の一行を入れることにより、表示されないようにできます。
更新する給与を入力するページ・アイテムとしてP1_SALを作成します。
タイプは数値フィールド、ラベルはSalaryとします。外観の書式マスクはP1_SAL_OLDと同様に、対話モード・レポートの列SALに合わせます。セッション・ステートのストレージはリクエストごと(メモリーのみ)です。
給与の更新を実行するボタンUPDATE_SALARYを作成します。動作のアクションに、動的アクションとして定義を選びます。
最初のTRUEアクションでPL/SQLコードを実行し、給与を更新します。アクションとしてサーバー側のコードを実行を選択し、設定のPL/SQLコードとして以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_empno emp.empno%type; | |
e_sal_was_changed exception; | |
l_sal_current emp.sal%type; | |
l_sal_old emp.sal%type; | |
l_sal emp.sal%type; | |
begin | |
:P1_ERROR := ''; | |
begin | |
select empno, sal into l_empno, l_sal_current from emp where empno = :P1_EMPNO for update nowait; | |
exception | |
when others then | |
/* ほぼ ORA-00054 resource busy */ | |
:P1_ERROR := '行が更新中です。'; | |
return; | |
end; | |
/* | |
* 変更前の値がl_sal_old、変更後の値がl_sal。 | |
*/ | |
l_sal_old := to_number(:P1_SAL_OLD,'999G999G999G999G999G999G999G999G999G990'); | |
l_sal := to_number(:P1_SAL,'999G999G999G999G999G999G999G999G999G990'); | |
if l_sal_current = l_sal then | |
/* | |
* 現在の給与と変更しようとしてる給与が同じ。 | |
*/ | |
null; | |
elsif l_sal_current <> l_sal_old then | |
/* | |
* 他のセッションにより更新済み。 | |
*/ | |
:P1_ERROR := '他のセッションで更新されています。'; | |
else | |
/* | |
* 給与を更新する。 | |
*/ | |
update emp set sal = l_sal where empno = l_empno; | |
commit; | |
end if; | |
rollback; | |
return; | |
end; |
送信するアイテムとして、P1_EMPNO、P1_SAL_OLD、P1_SAL、戻すアイテムとしてP1_ERRORを設定します。実行の初期化時に実行はオフです。
PL/SQLの実行でエラーが発生すると、表示すべきエラー・メッセージがP1_ERRORに戻されます。続くアクションを作成し、識別の名前をエラーの表示、タイプとしてJavaScriptコードの実行を選択します。クライアント側の条件のタイプにアイテムはnullではない、アイテムとしてP1_ERRORを指定することで、エラー・メッセージが返された場合に限り、エラー・メッセージを表示します。
設定のコードに以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apex.message.clearErrors(); | |
apex.message.showErrors( [ | |
{ | |
type: "error", | |
location: "page", | |
message: apex.items.P1_ERROR.value, | |
unsafe: false | |
} | |
] ); |
給与の更新に成功した場合(エラー・メッセージのアイテムP1_ERRORがnullの場合)、インライン・ポップアップのリージョンを閉じます。
最後に給与の更新の有無に関わらず、対話モード・レポートをリフレッシュします。
対話モード・レポートの列SALをクリックしたときに、インライン・ポップアップを開くAPEXアクションを実行します。
列SALの列の書式のHTML式に以下を記述します。カスタム属性のdata-actionに、APEXアクションopen-update-salaryを呼び出す指定をします。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<button type="button" class="t-Button t-Button--link" | |
id="EMP-SAL-#EMPNO#" | |
data-action="open-update-salary?empno=#EMPNO#&sal=#SAL#"> | |
<span class="t-Button-label">#SAL#</span> | |
</button> |
SALのセルをクリックしたときに呼び出されるAPEXアクションを設定します。
ページ・プロパティのJavaScriptのページ・ロード時に実行に、以下を記述します。Popup Calloutの表示が不要であれば、親エレメントの指定は若干簡単になります。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apex.actions.add( | |
[ | |
{ | |
/* | |
* Ref: | |
* Oracle APEX anchored inline popups for data input, Philipp Hartenfeller | |
* https://hartenfeller.dev/blog/apex-anchored-inline-popups | |
*/ | |
name: "open-update-salary", | |
action: (event, element, args) => { | |
// | |
apex.items.P1_EMPNO.setValue(args.empno); | |
apex.items.P1_SAL.setValue(args.sal); | |
apex.items.P1_SAL_OLD.setValue(args.sal); | |
const $popupAnchor = $(`#EMP-SAL-${args.empno}`); | |
let popup = $('#UPDATE_SALARY').data('apexPopup'); | |
popup.positionTo$ = $popupAnchor; | |
popup.options.parentElement = `#EMP-SAL-${args.empno}`; | |
popup.options.position.of = $popupAnchor; | |
// console.log(popup); | |
/* | |
* setTimeoutの呼び出しが必要かどうか不明。 | |
* apex.theme.openRegionではなくpopup.openであれば | |
* 待たなくてもよいように思う。 | |
*/ | |
popup.open(); | |
} | |
}, | |
{ | |
/* | |
* calloutを表示しなければ、parentElementに関する指定が緩くなり簡単。 | |
*/ | |
name: "open-update-salary-nocallout", | |
action: (event, element, args) => { | |
apex.items.P1_EMPNO.setValue(args.empno); | |
apex.items.P1_SAL.setValue(args.sal); | |
apex.items.P1_SAL_OLD.setValue(args.sal); | |
let popup = $('#UPDATE_SALARY').data('apexPopup'); | |
popup.options.position = { my: "left top", at: "left bottom", of: `#EMP-SAL-${args.empno}`}; | |
popup.options.minHeight = null; | |
popup.options.minWidth = null; | |
popup.options.height = 140; | |
popup.options.width = 300; | |
// console.log(popup); | |
popup.open(); | |
} | |
} | |
] | |
); |
表示されているインライン・ポップアップをよく見ると、余計な下線が見つかります。
popup.options.minHeight = null;
以上で実装は完了です。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/locating-inline-popup.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完