先日(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");
以上でアプリケーションは完成です。実行すると先頭のGIF動画のように動作します。
今回作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/apextipsajax.sql
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完