2022年5月31日火曜日

モーダル・ダイアログに重ねてモーダル・ダイアログを開く

 モーダル・ダイアログとして開いているページから、さらにモーダル・ダイアログを開く方法について質問を受けたので実装してみました。大まかに2通りの実装方法があります。また、標準のポップアップLOVのテンプレートを変更することで、要件を満たす場合もあるでしょう。

  1. インライン・ダイアログを使う。ダイアログは同じページに実装します。
  2. モーダル・ダイアログのページを使う。ダイアログは別のページとして実装します。
  3. ポップアップLOVのテンプレートを変更する。
サンプル・データセットの表EMPを使った対話モード・レポートとフォームのページを作成し、上記の3通りの実装を紹介します。

作成したアプリケーションは、以下のように動作します。



準備



アプリケーション作成ウィザードを起動します。アプリケーションの名前Dialog on Dialogとします。

ページの追加をクリックし、対話モード・レポートとフォームのページを追加します。

対話モード・レポートを選択します。

ページ名インライン・ダイアログとします。表またはビュー対話モード・レポートを選択し、表またはビューとして表EMPを選択します。フォームを含めるチェックを入れ、表EMPを編集するフォームのページを作成します。

このフォームのページを、親となるモーダル・ダイアログのページとします。このフォームのページから、さらにモーダル・ダイアログを開く実装を行います。

ページの追加を実行します。

ページ名モーダル・ダイアログとして、同じページを追加します。さらにページ名ポップアップLOVとして、同じページを追加します。

インライン・ダイアログモーダル・ダイアログ(別ページ)、ポップアップLOVを使った実装を試すページがそれぞれ追加されました。

アプリケーションの作成を実行します。

アプリケーションが作成されます。インライン・ダイアログを使った実装はページ番号3、モーダル・ダイアログを使った実装はページ番号5、ポップアップLOVはページ番号7のページに実施します。



インライン・ダイアログによる実装


ページ・デザイナにて、ページ番号のページを開きます。

Content Body上でコンテキスト・メニューを開き、リージョンの作成を実行します。このリージョンをダイアログにします。

作成したリージョンの識別タイトルジョブの選択とします。タイプ静的コンテンツとします。外観テンプレートInline Dialogを選択すると、このリージョンがダイアログとして扱われます。

テンプレート・オプションをクリックし、Auto Heightチェックを入れます。これ以外にも見かけを調整するオプションがあるので、必要に応じて調整します。

OKをクリックして、変更を確定します。

リージョンジョブの選択に、ジョブを選択するページ・アイテムP3_JOB_SELECTIONを作成します。

識別名前P3_JOB_SELECTIONタイプ選択リストとします。ラベルジョブとします。LOVSQL問合せとして、以下のSELECT文を記述します。

select job d, job r from emp group by job

追加値の表示OFFNULL値の表示ONNULL表示値として- ジョブを選択 -を記述します。

インライン・ダイアログの操作は、すべて動的アクションで実装します。この処理にはインライン・ダイアログのリージョンを開く、閉じる、値の設定が含まれます。

ページ・アイテムP3_JOBクリックしたときにリージョンジョブの選択を開きます。ページ・アイテムP3_JOBの内容を、ダイアログを開くと表示されるページ・アイテムP3_JOB_SELECTIONを使って選択できるようにします。

ページ・アイテムP3_JOBにたいして、動的アクションを作成します。

識別名前P3_JOBをクリックとします。タイミングイベントクリック選択タイプアイテムアイテムP3_JOBになります。

すでにページ・アイテムP3_JOBに設定されている値を、ページ・アイテムP3_JOB_SELECTIONにコピーします。

TRUEアクション識別アクションとして値の設定を選択します。設定タイプの設定JavaScript Expressionを選び、JavaScript式として以下を記述します。ページ・アイテムP3_JOBの内容になります。

apex.items.P3_JOB.value

影響を受ける要素選択タイプアイテムアイテムP3_JOB_SELECTIONを選びます。これで、P3_JOBの値がページ・アイテムP3_JOB_SELECTIONに設定されます。

P3_JOBをクリックしたときにのみ実行させるため、初期化時に実行OFFにします。

続いて、リージョンジョブの選択を開きます。

TRUEアクションを作成します。識別アクションリージョンを開くを選択します。影響を受ける要素選択タイプリージョンリージョンとしてジョブの選択を設定します。

以上で、インライン・ダイアログを開く動的アクションが実装できました。

今度はインライン・ダイアログを閉じる処理を追加します。

ページ・アイテムP3_JOB_SELECTIONで値を選択した時点で、インライン・ダイアログを閉じるようにします。

ページ・アイテムP3_JOB_SELECTIONにたいして、動的アクションを作成します。

識別名前ジョブの選択完了とします。タイミングイベント変更選択タイプアイテムアイテムP3_JOB_SELECTIONとなります。

TRUEアクションは、ダイアログを開けた時とは反対に、ページ・アイテムP3_JOB_SELECTIONの値をページ・アイテムP3_JOBに設定します。

識別アクションとして、値の設定を選択します。設定タイプの設定JavaScript ExrepssionJavaScript式として、以下を記述します。

apex.items.P3_JOB_SELECTION.value

影響を受ける要素選択タイプアイテムアイテムとしてP3_JOBを選択します。このTRUEアクションでも、初期化時に実行OFFにします。

TRUEアクションを作成して、値の設定の次に配置します。

識別アクションとして、リージョンを閉じるを選択します。影響を受ける要素選択タイプリージョンリージョンとしてジョブの選択を選びます。

以上で、インライン・ダイアログを使った実装は完了です。

アプリケーションを実行すると、記事の先頭にあるGIF動画のような動作になります。


モーダル・ダイアログによる実装


ジョブの選択を異なるページに実装します。ページは、モーダル・ダイアログとします。

ページの作成を実行します。

空白ページを選択します。

ページ番号名前ジョブの選択ページ・モードモーダル・ダイアログとします。オプション静的コンテンツ・リージョンを開き、リージョン1ジョブの選択と入力します。

へ進みます。

モーダル・ダイアログなので、ナビゲーションのプリファレンスは、このページとナビゲーション・メニュー・エントリを関連付けないから変更しません。

へ進みます。

終了をクリックし、ページの作成を完了します。

ページが作成されます。

あらかじめ作成されているリージョンジョブの選択の、外観テンプレートBlank with Attributesへ変更します。外観のテンプレートがStandardの場合、ページのタイトルとリージョンのタイトルの両方が画面に表示されます。Black with Attributesに変更することにより、リージョンのタイトルは表示されなくなり、ページのタイトルのみが表示されます。

ジョブを選択するページ・アイテムP8_JOB_SELECTIONを作成します。これは、インライン・ダイアログの際に作成したP3_JOB_SELECTIONとまったく同じ設定です。

ページ・アイテムP8_JOB_SELECTIONの値が変更されたときに、ページの送信を行います。

P8_JOB_SELECTIONに動的アクションを作成します。

識別名前ジョブの確定とします。タイミングイベント変更選択タイプアイテムアイテムP8_JOB_SELECTIONです。

TRUEアクション識別アクションとして、ページの送信を選択します。

動的アクションでページの送信を行なう代わりに、ボタンを作成してページの送信を行なうこともできます。

ページが送信されたら、モーダル・ダイアログを閉じます。

左ペインでプロセス・ビューを開き、プロセスを作成します。

識別名前ダイアログを閉じるタイプとしてダイアログを閉じるを選択します。設定戻すアイテムP8_JOB_SELECTIONを指定します。

ページ・プロパティのダイアログチェーンOFFにします。(レポートと同時にフォームを作成したときはチェーンのデフォルトはOFFですが、単体のページでモーダル・ダイアログを作成した場合はONがデフォルトのようです。)

チェーンがONの場合、このモーダル・ダイアログのページは親のモーダル・ダイアログの画面を置き換えます。(同じiframeを使用する)チェーンがOFFの場合は、親のモーダル・ダイアログの中で、モーダル・ダイアログが開かれます。

子となるモーダル・ダイアログは、以上で出来上がりです。

親のページから呼び出す設定を行います。

ページ・デザイナにて、ページ番号のフォームのページを開きます。

インライン・ダイアログのようにページ・アイテムをクリックしたときに、別のページを開く実装は簡単ではないです(JavaScriptでapex.navigation.dialogを呼び出す)。今回は別ページを開くボタンを作成します。

識別ボタン名B_SELECT_JOBとします。ラベルジョブの選択とします。動作アクションとして、このアプリケーションのページにリダイレクトを選びます。

ターゲットをクリックし、リンク・ビルダー・ターゲットを開きます。

ターゲットページアイテム設定名前P8_JOB_SELECTIONには&P5_JOB.を指定します。値に&P5_JOB.が設定されいている影響について、後述しています。

OKをクリックして、変更を保存します。


ダイアログがクローズしたときに返される値(P8_JOB_SELECTIONの値)を、ページ・アイテムP5_JOBに設定する動的アクションを作成します。

左ペインで動的アクション・ビューを開き、ダイアログのクローズで動的アクションを作成します。

識別名前ジョブの設定とします。タイミングイベントダイアログのクローズ選択タイプリージョンリージョンとしてEmployeesを選びます。


TRUEアクションの識別アクションとして、値の設定を選択します。設定タイプの設定Dialog Retrun Item戻りアイテムP8_JOB_SELECTIONになります。戻りアイテムは異なるページに存在するため、選択リストから選ぶことはできません。キーボードから入力します。影響を受ける要素選択タイプアイテムアイテムとしてP5_JOBを指定します。

ページ番号8のモーダル・ダイアログが閉じるときに戻すアイテムとして指定したP8_JOB_SELECTIONの値を受け取って、ページ・アイテムP5_JOBに設定しています。

このアクションも、初期化時に実行OFFです。


以上で、別ページのモーダル・ダイアログによる実装は完了です。

インライン・ダイアログの実装とあまり違わないように見えますが、ボタンジョブの選択をクリックしたときに、HTTPのGETリクエストが発行されています。インライン・ダイアログはページ上のJavaScriptの処理で、HTTPのリクエストは発生していません。

わかりやすい違いとして、以下に例を挙げます。

親のモーダル・ダイアログが開いた直後にジョブの選択をクリックします。


開いたモーダル・ダイアログの値は店員です。


ページ・アイテムP8_JOB_SELECTIONセールスを選択しダイアログを閉じると、ジョブはセールスに変わります。

再度、ジョブの選択をクリックします。


ページ・アイテムP8_JOB_SELECTIONの初期値は店員のまま、変わりません。


ボタンジョブの選択のターゲットとして設定した引数&P5_JOB.の値は、親のモーダル・ダイアログのページが開いたときに初期化されます。それ以降にページ・アイテムP5_JOBの値が変更されても、ボタンのターゲットには反映されません。


ポップアップLOVのテンプレート変更



ポップアップLOVのテンプレートを変更する方法については、Louis Moreauxさんの以下の記事を参考にしています。

Popup LOV custom template

ページ・デザイナでページ番号のページを開きます。

ジョブのページ・アイテムP7_JOBタイプポップアップLOVに変更し、設定表示形式Modal Dialogにします。


ページ・アイテムP7_JOBLOVの設定は、今までにP3_JOB_SELECTIONP8_JOB_SELECTIONに設定した内容と同じです。

タイプSQL問合せSQL問合せとして以下を記述します。

select job d, job r from emp group by job

検索された列名はDRです。これはテンプレート内の置換文字列として使用します。

追加値の表示OFFNULL値の表示ONNULL表示値として- ジョブを選択 -を記述します。


ポップアップLOVに一覧されるジョブを、太字、赤、センタリングして表示するよう、テンプレートを変更します。

以下のJavaScriptコードを、ページ・アイテムP7_JOB詳細JavaScript初期化コードに記述します。



ポップアップLOVへのカスタム・テンプレートの適用は以上です。

アプリケーションを実行して、ページ・アイテムP7_JOBをポップアップさせると、以下のように表示されます。


元記事では、画像を含んだもっと見栄えのよいカスタム・テンプレートを用意しています。より詳しく知りたい場合は、英語ですが元記事の参照をお勧めします。

以上になります。

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

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