2022年6月7日火曜日

対話グリッドで選択した行を引数としてプロセスを実行する

 ダイアログとして開かれた対話グリッド上で選択した列を引数にして、プロセスを実行したいという相談がありました。

元々は対話グリッドは別のページに作成し、それをモーダル・ダイアログとして開こうとしていたのですが、(できなくはないが)それだと実装が難しくなります。

代わりにインライン・ダイアログで実装してみました。Always FreeのAutonomous Databaseで動くAPEX 21.2上で、アプリケーションを作成しています。

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

最初は対話グリッド上で選択した行に含まれる従業員名を、直接ページ・アイテムに設定します。その後、対話グリッド上では従業員番号を取り出し、サーバー側に送信して従業員名に変換した上でページ・アイテムに設定します。

アプリケーションで作成するデータは、サンプル・データセットEMP/DEPTに含まれる表EMPを使用します。

アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。名前プロセス呼び出しとします。アプリケーションはホーム・ページに実装します。


ページ・デザイナホーム・ページを開きます。

Body静的コンテンツのリージョン従業員を作成します。


対話グリッド上で選択した、従業員の名前を保持するページ・アイテムの作成を行います。

識別名前P1_ENAMEタイプテキスト・フィールドラベル従業員名とします。


従業員を選択するために使用する、対話グリッドのリージョンの作成を行います。

識別タイトル従業員選択タイプ対話グリッドソース表名としてEMPを指定します。外観テンプレートInline Dialogを選択します。


行を選択するために使用するので、Attributes編集有効OFFにします。


インライン・ダイアログである従業員選択のリージョンを開く、ボタンの作成を行います。

識別ボタン名B_SELECTラベル従業員選択動作アクションとして動的アクションで定義を選択します。


ボタンに、動的アクションの作成を行います。

識別名前従業員選択をクリックとします。タイミングイベントクリック選択タイプボタンボタンB_SELECTとなります。


TRUEアクション識別リージョンを開く影響を受ける要素は、選択タイプリージョンリージョン従業員選択とします。これで、ボタンを押すと対話グリッドが開きます。


対話グリッド上で行を選択したときに実行される、動的アクションの作成を行います。

識別名前従業員の選択とします。タイミングイベント選択の変更[対話グリッド]選択タイプリージョンリージョン従業員選択とします。


最初は、従業員名を直接、ページ・アイテムP1_ENAMEに設定します。

TRUEアクション識別アクション値の設定を選択します。設定タイプの設定JavaScript ExpressionJavaScript式に以下を指定します。

this.data.selectedRecords[0][1]

選択される行は複数可であるため配列ですが、今回は常に1行です。そのため、最初の引数は常に次の引数列ENAMEの位置を表す1になります。(位置ではなく列名を指定したいときはmodelインターフェースを介す必要があります。こちらの記事では対話グリッドのmodelインターフェースを使用しています。)影響を受ける要素選択タイプアイテムアイテムP1_ENAMEになります。実行オプション初期化時に実行OFFクライアント側の条件タイプJavaScript式JavaScript式として以下を記述します。

this.data.selectedRecords.length > 0

行が選択されているときに限定して、値の設定(つまりP1_ENAMEへの値の設定)が実行されます。


対話グリッドのAttributes外観最初の行の選択OFFにします。この設定がONの場合、対話グリッドを開いた時点で最初の行が選択されます。その時点で対話グリッドのイベント選択の変更[対話グリッド]が発火し、動的アクション行の選択が実行されてしまいます。


値の設定を行った後に、対話グリッドのリージョンを閉じます。

TRUEアクションを作成し、識別アクションとしてリージョンを閉じるを選択します。影響を受ける要素選択タイプリージョンリージョン従業員選択を選びます。クライアントの条件は、値の設定と同じく、タイプJavaScript式JavaScript式は以下になります。

this.data.selectedRecords.length > 0


以上で、対話グリッド上で選択した行の従業員名が、ページ・アイテムP1_ENAMEに設定されます。

これから、今回の目的であるサーバー側のプロセスを呼び出す実装を行います。

Ajaxコールバックとして、プロセスget_enameを作成します。引数x01として従業員番号を受け取り、それより従業員名を検索します。結果をJSONフォーマットで呼び出し元に返します。

declare
   l_response varchar2(4000);
begin
   select json_object(ename) into l_response
   from emp
   where empno = apex_application.g_x01;
   htp.p(l_response);
   apex_debug.info(l_response);
exception
    when others then
        htp.p('{}');
end;

呼び出し側を変更します。

TRUEアクションの値の設定を、JavaScriptコードの実行に変更します。設定コードでは、先ほど作成したAjaxコールバックget_enameを呼び出すコードを記述します。
apex.server.process(
    "get_ename"    // Simple Echoback writen in PL/SQL is called, running inside DB server.
    , {
        x01: this.data.selectedRecords[0][0]  // The argument on the browser passed to the server process.
    }
    ,{
        success: function( data ) 
        {
            apex.items.P1_ENAME.setValue(data.ENAME);
        },
        error: function ( jqXHR, textStatus, errorThrown )
        {
            // do something here
        }
    }
);

以上で、アプリケーションは完成です。アプリケーションを実行すると、記事の最初のGIF動画の動作をします。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。

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