2022年6月7日火曜日

スマート・フィルタを複数のリージョンの検索条件に適用する

 複数のカード・リージョンの検索にスマート・フィルタを適用する方法について、Oracle APEXの開発チームのシニア・アーキテクトのSteve Muenchさんが、実装方法を個人の記事で紹介していたので試してみました。

スマート・フィルタを使って従業員を検索し、左のカード・リージョンに一覧しています。右のカード・リージョンには、検索された従業員が所属している部門を一覧しています。

アプリケーションの実装にはAlways FreeのAutonomous DatabaseのAPEX 21.2を使用しています。サンプル・データセットのEMP/DEPTに含まれる表EMP(左のカード・リージョンのソース)および表DEPT(右のカード・リージョンのソース)を、データとして使用しています。

では、アプリケーションの作成手順を紹介します。

アプリケーション作成ウィザードを起動します。アプリケーションの名前を複数リージョン・スマート・フィルタとします。

ホーム・ページを削除し、代わりにスマート・フィルタのページを追加します。

ページの追加で、スマート・フィルタを選択します。


ページ名を従業員検索とし、検索結果はレポートとして表示されるようレポートを選択します。ソースとなる表として、EMPを選択します。

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


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

スマート・フィルタが実装されたページを含んだ、アプリケーションが作成されます。


これからの作業は、ページ番号1の従業員検索のページに実施します。


作成したアプリケーションを実行してみます。デフォルトで作成されたスマート・フィルタは、そのまま使用します。


ページ・デザイナを開いて、従業員を一覧するカード・リージョンを作成します。

識別のタイトルは従業員とします。タイプはカードを選択します。ソースの表名にEMPを選択します。


カード・リージョン従業員のAttributesを開き、カードに表示される内容を設定します。カードの主キー列1としてEMPNOを選択します。タイトルの列としてENAME、サブタイトルの列としてJOBを選択します。


もう一つカード・リージョンを作成します。検索された従業員が所属している部門の一覧を、カードとして一覧します。

識別のタイトルは部門とします。タイプはカードです。ソースの表名にDEPTを選択します。リージョン従業員の右横に配置するため、レイアウトの新規行の開始をOFFにします。


カード・リージョン部門のAttributesを開き、カードに表示される内容を設定します。カードの主キー列1としてDEPTNOを選択します。タイトルの列としてDNAME、サブタイトルの列としてLOCを選択します。


新たに追加したリージョン従業員と部門の検索条件は、リージョン検索結果に表示される結果から作成されます。そのためにパイプライン表関数empno_empを作成します。表関数の引数としてリージョン検索結果が必要になるため、詳細の静的IDとしてEmployeesを設定します。


スマート・フィルタが適用された結果より、従業員番号を取り出す表関数emono_empの定義は以下です。APEX_REGION.OPEN_QUERY_CONTEXTを呼び出しています。


SQLワークショップのSQLスクリプトを呼び出して実行し、ファンクションempno_empおよび、このファンクションが使用するタイプt_empno_emp_row、t_empno_emp_tabを作成します。


カード・リージョンに、このパイプライン表関数を使った条件を設定します。

リージョン従業員のソースのWHERE句は、以下になります。
empno in (
    select empno from table(
        empno_emp(
            p_app_id => :APP_ID
            , p_page_id => :APP_PAGE_ID
            , p_region => 'Employees'
        )
    )
)


リージョン部門のソースのWHERE句は、以下になります。
deptno in (
    select deptno from emp where empno in (
        select empno from table(
            empno_emp(
                p_app_id => :APP_ID
                , p_page_id => :APP_PAGE_ID
                , p_region => 'Employees'
            )
        )
    )
)

スマート・フィルタが適用され、リージョン検索結果が更新された後に、カード・リージョンの従業員と部門を更新します。

リージョン検索結果で、動的アクションの作成を行います。

作成された動的アクションの識別の名前を従属リージョンの更新とします。タイミングはイベントがリフレッシュ後、選択タイプはリージョン、リージョンとして検索結果を選択します。


TRUEアクションの識別のアクションとして、リフレッシュを選択します。影響を受ける要素の選択タイプはリージョン、リージョンはカード・リージョンである従業員です。


同様に、リージョン部門をリフレッシュするTRUEアクションも作成します。作成済みのアクションを重複させ、リージョンを部門に変更すると良いでしょう。


この時点でアプリケーションを実行すると、カード・リージョン従業員と部門の検索結果を確認することができます。


動作が確認できたら、最後にクラシック・レポートのリージョン検索結果を非表示にします。カード・リージョン従業員と部門は、このリージョンに依存しているためサーバー側の条件で非表示にすることはできません。

リージョン検索結果を非表示にするため、ページ・プロパティのCSSのインラインに以下を記述します。
#Employees {
    display: none
}


 この状態でアプリケーションを実行すると、記事の先頭のGIF動画の動作をします。

ただし、リージョン検索結果は画面上は表示されないだけで、HTMLとしては生成されています。


そのため、リージョン検索結果のAttributesの設定を調整し、無駄な処理を極力行わないようにします。

リージョン検索結果のAtrributesを開き、レイアウトの行数を0、ページ区切りのタイプをページ区切りなし(すべての行を表示)、部分ページ・リフレッシュをONとします。


以上でアプリケーションは完成です。

今回はカード・リージョンを使用しましたが、リフレッシュをサポートしているリージョンは同様に使用できます。例えばチャートです。また、スマート・フィルタとファセット検索は同じ仕組みを使っています。そのため、ファセット検索のページでも、同様の実装が可能です。

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

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

完