2022年3月23日水曜日

Developer Tips from the APEX Team #2で紹介されたAJAXを使ったアプリを実装してみる

 先日(2022年3月17日)のAPEX Office Hour - Developer Tips from the APEX Team Part IIでVincent Morneauさんが紹介していたAJAXを使ったアプリを、Autonomous DatabaseのAPEX 21.1で作ってみました。

その作業の紹介です。

元のアプリはAPEX 21.2から導入された記法(主にJavaScript API)を使っていて、そのままではAPEX 21.1に実装できません。あと、私はJavaScriptは苦手なので、勉強のために写経をします。

色々と見た目を調整すると手順を書ききれなくなるため、見た目の調整は最低限にします。作成するアプリは以下になります。

最初にサンプル・データセットからをロードします。

SQLワークショップユーティリティよりサンプル・データセットを開きます。

名前のデータセットをインストールします。

データセットの説明が表示されます。言語Englishしかなく、スキーマもデフォルトのままとします。

へ進みます。

データセットのインストールを実行します。今回のアプリが使用するのはビューEBA_COUNTRIES_Vです。

データセットのインストール結果を確認し、終了をクリックします。ここではアプリケーションの作成は行いません。

データセットの準備ができたら、アプリケーションを作成します。

アプリケーション作成ウィザードを起動し、アプリケーションの名前APEX Tipsとします。それ以外は何も設定せず、アプリケーションの作成を実行します。

アプリケーションが作成されます。今回のアプリケーションは、すべてホーム・ページに実装します。

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

イメージを表示するページ・アイテムと首都、国名、人口を表示するためのページ・アイテムを作成します。

最初にそれらを配置するリージョン行き先を作成します。

Content Bodyの上でコンテキスト・メニューを表示させ、リージョンの作成を実行します。

作成したリージョンの識別タイトル行き先タイプとして静的コンテンツを選択します。

作成したリージョンにページ・アイテムを4つ作成します。

最初に画像を表示するページ・アイテムP1_IMAGEを作成します。リージョン行き先の上でコンテキスト・メニューを表示させ、ページ・アイテムの作成を実行します。

識別名前P1_IMAGEタイプとしてイメージの表示を選択します。ラベルを指定すると画像に重なって表示されるため、空白にします。設定基準としてImage URL stored in Page Item Valueを選択します。

無指定だと表示される画像が大きすぎ、また、サイズもまちまちになるため、詳細カスタム属性として以下を設定し、画像の高さを230pxに固定します。

style="max-height:230px;"

デフォルトタイプ静的にします。静的値として以下を指定します。選択された首都の画像は、images.unsplash.comより取得し表示します。

https://images.unsplash.com/photo-1616593437252-0631aeb95590?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80

アプリケーションの実行直後に表示される画像になります。この後、首都や国が選択されると、このURLを画面上で置き換え、表示する画像を変更します。この設定によりプレースホルダが作られるため、デフォルトの設定は必須です。

首都を保持するページ・アイテムを作成します。

識別名前P1_CAPITALタイプテキスト・フィルードとします。ラベル首都にします。


国名を保持するページ・アイテムを作成します。

識別名前P1_COUNTRY_NAMEタイプテキスト・フィールドとします。ラベル国名にします。


人口を保持するページ・アイテムを作成します。

識別名前P1_POPULATIONタイプ数値フィールドとします。ラベル人口にします。


首都、国名、人口を、ビューEBA_COUNTRIES_Vより取り出すAJAXプロセスを作成します。

左ペインでプロセス・ビューを表示させます。

Ajaxコールバックのノード上でコンテキスト・メニューを表示させ、プロセスの作成を実行します。

作成したプロセスの識別名前random_placeとします。タイプとしてコードを実行を選択します。ソースPL/SQLコードに以下を記載します。

declare
l_result varchar2(4000);
begin
select
json_object(
'success' value 'true' format json
, 'capital' value capital
, 'name' value name
, 'population' value population
returning varchar2(4000)
)
into
l_result
from eba_countries_v
order by sys.dbms_random.random
fetch first 1 rows only;
sys.htp.p(l_result);
end;

元々の実装ではパッケージAPEX_JSONを使用しています。上記ではオラクル・データベースのJSONの実装を使用しています。どちらでも結果は変わりません。


作成したAjaxコールバックを呼び出し、首都、国名、人口や画像を更新するボタンを作成します。

リージョン行き先上でコンテキスト・メニューを表示させ、ボタンの作成を実行します。

識別ボタン名FEELING_LUCKYラベルFeeling Luckyとします。動作アクションとして、動的アクションで定義を選択します。


Ajaxコールバックrandom_placeを呼び出し、取得した情報をページ・アイテムに反映させる処理は、動的アクションに直接記述せずページのプロパティに記述します。

ホーム・ページのプロパティのJavaScriptファンクションおよびグローバル変数の宣言に以下を記述します。ページ・アイテムの値の設定と取得で、APEX 21.2以前でも利用可能なsetValue、getValueを使うように変更しています。

// Function that finds a random place in the world
const feelingLucky = async () => {
// 1. Invoke AJAX process random_place to fetch data
const result = await apex.server.process("random_place");
console.log(result);

// 2. Set display only items on the page with AJAX data
apex.item("P1_COUNTRY_NAME").setValue(result.name);
apex.item("P1_CAPITAL").setValue(result.capital);
apex.item("P1_POPULATION").setValue(result.population);

// 3. Refresh image with a random photo from unsplash
let image_url = `https://source.unsplash.com/random/?${encodeURIComponent(apex.item("P1_CAPITAL").getValue())}`;
console.log(image_url);
const spinner$ = apex.util.showSpinner( apex.jQuery("#P1_IMAGE_CONTAINER") );
apex.item("P1_IMAGE").node.onload = () => {
spinner$.remove();
};
apex.item("P1_IMAGE").node.src = image_url;
};


ボタンFEELING_LUCKYに、動的アクションを作成します。ボタン上でコンテキスト・メニューを開き、動的アクションの作成を実行します。

動的アクションの識別名前onClick FEELING_LUCKYとします。ボタンに対して動的アクションを作成すると、タイミングイベントクリック選択タイプボタンボタンはFEELING_LUCKYとなり、デフォルトがそのまま使えます。


TRUEアクションを選択し、識別アクションとしてJavaScriptコードの実行を選択します。設定コードには以下を記述します。ページ・プロパティに記載したファンクションfeelingLuckyを呼び出します。

feelingLucky();


最後にキーボード・ショートカットを登録します。

ページ・プロパティのJavaScriptページ・ロード時に実行に以下を記述します。

// 1. Add new action on the page that invokes a JavaScript function
apex.actions.add({
name: "feeling-lucky",
action: feelingLucky
});

// 2. Attach action to Ctrl+L
apex.actions.addShortcut("Ctrl+L", "feeling-lucky");

JavaScript APIのapex.actions.addを呼び出して、ファンクションfeelingLuckyをAPEXのアクション(apex.action)として登録します。その後にapex.actions.addShortcutを呼び出して、CTRL+Lにアクションを割り当てています。


以上でアプリケーションは完成です。実行すると先頭のGIF動画のように動作します。

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

この他にも色々と有用な技が紹介されているので、Office Hourの動画の視聴をお勧めします。

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