2021年10月29日金曜日

Oracle APEX 21.2新機能(7) - スマート・フィルタ

 Oracle APEX 21.2より新しい検索のためのコンポーネントとして、スマート・フィルタが追加されました。ファセット検索と同様の仕組みで検索を行いますが、検索条件を指定するユーザー・インターフェースが異なります。スマート・フィルタでは、ファセットの代わりにフィルタというコンポーネントが使用されます。

Oracle APEXの公式のYouTubeチャンネルよりSmart Filtersの紹介動画が公開されています。10月21日14時(UTC)にAskTOMのOffice HourとしてOracle APEX 21.2 New Featuresというタイトルのオンライン・セミナーがあり、その中で開発者のJohn SnydersよりSmart Filtersの説明がありました。こちらの方は、今のところ動画が公開されていません。

スマート・フィルタについて理解するため、サンプル・データセットEMP/DEPTに含まれる表EMPソースとした、スマート・フィルタのページを作成してみます。ページを作成するアプリケーションは、サンプル・データセットのインストールと同時に作成したもの(デモ - 従業員 / 部門)を使用します。

ページ作成ウィザードを開始します。スマート・フィルタのページはレポートの一種なので、コンポーネントレポートを選択します。


スマート・フィルタを選択します。


ページ名をスマート・フィルタとします。ページ番号7になっています。今後の説明に出てくるフィルタの名前にページ番号が付けられるので、異なる番号になる場合はフィルタ名も変わります。へ進みます。


ナビゲーションのプリファレンスとして新規ナビゲーション・メニュー・エントリの作成を選択します。新規ナビゲーション・メニュー・エントリはデフォルトでページ名と同じスマート・フィルタになります。へ進みます。


レポート・ソースを指定します。表/ビューの名前としてEMPを選択します。表示形式としてレポート(クラシック・レポート)を選択します。ダイアログを広げるか表示をスクロールすると、デフォルトで作成されるフィルタが確認できます。今回の例ではページ作成ウィザードによって、列JOBMGRSALDEPTNOを対象とした4つのフィルタが作成されます。作成をクリックします。


スマート・フィルタを含んだ検索ページが作成されます。検索フィールドP7_SEARCHと4つのフィルタ、P7_DEPTNOP7_MGRP7_JOBP7_SALが含まれます。


ページを実行してみます。ページ上部に検索フィールドと4つのフィルタがあることが確認できます。


レポートの表示に適用されたフィルタは検索フィールドに表示されます。検索フィールドの下に表示されているのは、こういう条件で検索すると有効だと思われるという推奨(サジェスチョン・チップ - Suggetion Chips)でありレポートの検索には適用されていません。

 
それぞれのフィルタ条件はANDで連結されます。レポートの検索に使用されるSELECT文のイメージは以下になります(実際にはもっと複雑です)。それぞれのフィルタ条件が確定した時に、レポートのリフレッシュが実行されます。フィルタもリフレッシュされ、サジェスチョン・チップが変わります。

SELECT * FROM EMP
WHERE
    Departmentのフィルタ条件
AND
    Managerのフィルタ条件
AND
   Jobのフィルタ条件
AND
   Salaryのフィルタ条件

スマート・フィルタを実装するために、リージョン・タイプとしてスマート・フィルタが新設されています。


スマート・フィルタのリージョンは、フィルタ検索フィールドをひとつだけ含みます。今回の例ではP7_SEARCHです。検索フィールドではソース自体と、設定されたフィルタによって適用できる条件を検索します。特殊なコンポーネントで、カスタマイズの余地はほぼありません。


開発者はフィルタをカスタマイズすることにより、検索ページを使いやすくします。

選択可能なフィルタのタイプは、チェック・ボックス・グループラジオ・グループ入力値範囲の4つです。タイプとして検索がありますが、これは前記の通り特別なので追加することはありません。

フィルタのプロパティは、ほとんどファセット検索のファセットと同じです。サジェスチョンがフィルタ独自の設定になります。


フィルタP7_DEPTNOを調整します。タイプチェック・ボックス・グループ外観アイコンとしてfa-building-oサジェスチョンタイプ動的とし、ラベル表示OFFにします。


ページを実行してフィルタを確認します。サジェスチョンラベルの表示OFFとしたので、ラベルの表示が無くなっています。ラベルの表示が無くてもフィルタの条件が明らかな場合にOFFにします。


Departmentのサジェスチョンはセールスになっています。サジェスチョンタイプ動的であると、フィルタのリスト・エントリの先頭がサジェスチョンとして選択されます。フィルタのリスト・エントリのプロパティ上位件数でソートONであれば、件数の一番多いエントリがリストの先頭になります。結果として、その値がサジェスチョンとして選択されます。
サジェスチョンセールスをクリックすると、Departmentセールスの従業員だけがリストされます。


検索結果が少ない場合、サジェスチョン・チップが表示されなくなります。この条件についての記載は見つかりませんでしたが、操作した感じでは検索結果が10行を切ると表示されなくなるようです。サジェスチョン・チップが表示されないだけで、検索フィールドよりフィルタを設定することはできます。


チェック・ボックス・グループのフィルタで選択したエントリはOR条件になります。つまり、以下の画面の場合、Departmentがセールスまたは研究開発である従業員が検索されます。


設定したアイコンは検索フィールドからフィルタの一覧を表示したときに現れます。


サジェスチョンタイプには動的の他に、なし静的SQL問合せがあります。サジェスチョンタイプとして静的値を選択し、静的値として10(会計)を指定します。


サジェスチョン・チップの表示がDEPTNO10である会計に変わります。静的値はサジェスチョンを固定する場合に使用できます。SQL問合せでは、状況に応じたサジェスチョンを指定することができます。


サジェスチョンのタイプのヘルプには、サジェスチョンの値としてカンマ区切りのリストを受け付けるとの記載がありますが、常にリストの先頭の値が有効に見受けられます。複数の値を指定した場合にどのようなサジェスチョンになるかも不明なので、静的値として指定する値はひとつにした方が良いでしょう。

続いてフィルタP7_MGRを調整します。識別タイプラジオ・グループに変更します。ラジオ・グループで選択できるエントリはひとつだけになります。外観アイコンfa-userとし、リスト・エントリゼロ件のエントリ非表示上位件数でソートONにします。


フィルタP7_MGRの表示は以下のようになり、誰の上司でもない従業員はリストされず、また、選択できる従業員はひとりだけになっています。


フィルタP7_SAL識別タイプ範囲になっています。フィルタは以下のように表示されます。


LOVタイプとして静的値が選択され、静的値には複数の範囲が設定されています。


範囲の設定です。


COMMを対象としたフィルタを作成します。フィルタの作成を実行します。識別名前P7_COMMタイプには入力フィールドを選択します。ラベルCommとします。

設定比較演算子Less Than or Equalsを選択し、現行ラベルコミッションは%0以下接頭辞テキスト$接尾辞テキストドルとします。一般的にはこういった冗長な設定はしませんが、これらの文字が画面上のどこに表示されるか確認するために使います。外観アイコンfa-dollarソースデータベース列としてCOMMデータ型NUMBERを選択します。列COMMに定義された型を参照せずVARCHAR2がデフォルトとなるようなので、必ずNUMBER型に変更します。


以上の設定でフィルタP7_COMMを呼び出すと以下になります。入力フィールドの前に接頭辞テキスト、後ろに接尾辞テキストが表示されています。入力フィールド100を入力します。


現行テキストに含まれる%0が入力値に置き換わり、コミッションが100以下と表示されます。


フィルタはファセットと同様に複数の値(マルチ・バリュー)をサポートします。以前の記事で紹介したスキルを検索対象に追加して、複数の値に対応したフィルタを作成します。レポート・リージョン検索結果ソースタイプSQL問合せに変更し、SQL問合せとして以下を記述します。
select 
    e.EMPNO,
    e.ENAME,
    e.JOB JOB,
    e.MGR,
    e.HIREDATE,
    e.SAL,
    e.COMM,
    e.DEPTNO,
    s.SKILLS
from EMP e left outer join 
(
    select empno, 
        json_arrayagg(skill order by id returning varchar2(400)) skills
    from skills group by empno
) s
on e.empno = s.empno
理由は不明ですが、列e.JOBに別名としてJOBを付けないと検索が正常に行われませんでした。そのためe.JOB JOBとしています。


追加された列SKILLSを対象としたフィルタを作成します。

識別名前P7_SKILLSタイプチェック・ボックス・グループを選択します。ラベルSkillsとします。LOVタイプ個別値です。


サジェスチョンデフォルトタイプ動的ラベルを表示ONになっています。ソースデータベース列SKILLSデータ型VARCHAR2です。複数の値タイプJSON配列を選択し、フィルタの結合AND(論理積)を指定します。


フィルタの結合としてAND(論理積)を選んでいるため、日本語英語を選択したときにSkillsに両方が含まれている列だけがレポートに表示されます。


最後にサジェスチョン・チップが表示される数を調整します。スマート・フィルタのリージョンのAttributesを開きます。設定最大サジェスチョン・チップその他のフィルタ・サジェスチョン・チップONに変更します。最大サジェスチョン・チップが未指定の場合は、5として扱われます。


サジェスチョン・チップは以下のように表示されます。


この他にもキーボードによる操作ができるといった機能もあります。

以上でスマート・フィルタの紹介は終了です。

今回実装した内容のエスクポートを以下に置きました。ページ番号7にスマート・フィルタのページを作成しています。
https://github.com/ujnak/apexapps/blob/master/exports/new212-smartfilters.sql

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

追記

スマート・フィルタを開発したJohn Snydersさんによる解説が、Oracle APEXのOffice HourのOracle APEX 21.2 New Featuresとして公開されています。元々、今回の記事はリアルタイムでこのセッションを見て書いているのですが、録画を視聴して気づいた機能を2つ追記します。

ページ作成ウィザードでスマート・フィルタのページを作る際にブレッドクラムをつけると、スマート・フィルタはブレッドクラムの位置に作成されます。

ページ作成ウィザードでのブレッドクラムの選択は以下になります。


作成されたスマート・フィルタのページは以下の構成になります。検索親リージョンブレッドクラムになっています。


作成されたページは以下になり、スマート・フィルタがブレッドクラムに配置されます。


スマート・フィルタは検索のUIとして領域が小さいというのが利点ですが、検索フィールドのプロパティ縮小された検索フィールドONにすると、初期状態で検索フィールドを非表示にすることができます。


検索フィールドを開くには虫メガネのアイコンをクリックします。クリックすると検索フィールドが現れ、2つまえの画面ショットになります。


2021年10月28日木曜日

Oracle APEX 21.2新機能(6) - 環境バナー

 Oracle APEXの開発環境の画面に環境バナーを表示できるようになりました。ワークスペース毎に設定できます。環境バナーを設定すると、Oracle APEXのアプリケーション開発環境に以下のように表示されます。

環境バナーは、管理メニューのサービスの管理に含まれる環境バナーの定義より設定します。

バナーの有効化位置ラベルを設定し、変更の適用をクリックします。

以上でアプリケーション・ビルダーやその他の開発ツールの画面の指定した位置に、常時設定したバナーが表示されます。

実際にAPEXによるアプリケーションの開発を行っていて、複数のワークスペースに同時にサインインして作業をするといったことはあります。さらには同じワークスペース名でデータベースが異なる場合と言った場合もあります。そのため、このように直感的にワークスペースを見分けることができるのは大変便利です。

Oracle APEX 21.2新機能(5) - ダイアログを取り消した時のイベント

 ダイアログを単にクローズしたときのイベントによって、動的アクションが起動できるようになりました。ダイアログをクローズしたときのイベントは以前からあったのですが、このイベントは画面上のボタンを押した時に発生し、単にダイアログをクローズした場合(右上にある✖️をクリックしたときなど)には発生しませんでした。

以前からあったイベントの名前はダイアログのクローズ(英語ではDialog Closed)、新設されたイベントの名前は閉じられたか取り消されたダイアログ(英語ではDialog Closed or Canceled)です。

モーダル・ダイアログのページに動的アクションを設定するなどして、ダイアログを開いたままデータの更新を行うような実装をした場合、そのダイアログをキャンセル・ボタンのクリックで閉じたときに更新済みの変更を元に戻したい、といった要件はあるかと思います。その際にキャンセル・ボタンのクリックで元に戻す処理を実装すると、ダイアログの✖️をクリックしてダイアログを閉じられると元に戻す処理が実行されません

✖️をクリックさせないようにダイアログから消してしまう、という手段が取られることがあります。

サンプル・データセットのEMP/DEPTより作成されるアプリケーションを例にとって、実装について説明します。

ダイアログを開くベースとなるレポート(今回の例では表EMPのファセット検索)のページ・プロパティCSSインラインに以下の記述を加えます。

.no-close .ui-dialog-titlebar-close {display: none;}


従業員の情報を編集するフォームを含む、モーダル・ダイアログのページのダイアログCSSクラスとしてno-closeを指定します。


以上の設定を行いフォームを開くと、✖️が消えていることが確認できます。


✖️がなくなったので、ダイアログをクローズするには取消削除変更の適用または(上記のフォームでは表示されていませんが)作成のボタンを押す以外に方法がないように見えます。実際にはキーボードのEscを押すと、ダイアログをクローズすることができます。

Oracle APEX 21.2より、このような状況で閉じられたか取り消されたダイアログのイベントが発生するようになりました。

イベントの発生を確認してみます。(モーダル・ダイアログではなく)レポートのページを開き、左ペインに動的アクション・ビューを開きます。


イベント閉じられたか取り消されたダイアログで実行される動的アクションを作成します。

動的アクションの作成を実行します。識別名前閉じられたか取り消されたダイアログとします。タイミングイベントとして閉じられたか取り消されたダイアログ選択タイプリージョンリージョンとしてEmployees(モーダル・ダイアログを開くレポートのリージョン名)を選択します。


アクションとして、以下のJavaScriptを実行します。JavaScriptコンソールにEvent - 閉じられたか取り消されたダイアログと出力します。

console.log("Event - 閉じられたか取り消されたダイアログ - " + this.data.closeAction);

識別アクションとしてJavaScriptコードの実行を選択し、設定コードに上記を記述します。


アプリケーションを実行して、イベントの発生を確認します。

ブラウザのJavaScriptコンソールを開き、従業員のファセット検索のページより、任意の従業員の編集フォームを開きます。


キーボードのEscをクリックし、従業員の編集フォームを閉じます。JavaScriptのコンソールにEvent - 閉じられたか取り消されたダイアログ - cancelと出力されていることが確認できます。


取消ボタンを含むすべてのボタンをクリックによっても従業員の編集フォームは閉じるため、イベント閉じられたか取り消されたダイアログが発生します。

Esc取消ボタンを押してモーダル・ダイアログのページ(従業員のフォーム)が閉じられる時はthis.data.closeActionの値がcancelになっています。作成変更の適用および削除ボタンのクリックの結果、モーダル・ダイアログのページが閉じられるときはthis.data.closeActioncloseになっています。この値は補償となる処理の実行が必要かどうかの判別条件に使用できるでしょう。

取消もしくはキャンセル・ボタンのクリックで実行される処理は、フォームが存在するモーダル・ダイアログのページに実装しています。同様の処理を閉じられたか取り消されたダイアログで実行する場合、モーダル・ダイアログの呼び出し側であるレポートのページに実装することになります。処理を実装し直す場合、参照できるページ・アイテムが違うことに注意が必要です。


新たに追加されたイベント閉じられたか取り消されたダイアログの説明は以上です。

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