ラベル JET の投稿を表示しています。 すべての投稿を表示
ラベル JET の投稿を表示しています。 すべての投稿を表示

2025年11月21日金曜日

Oracle JETのThematic MapをAPEXアプリケーションに組み込む

Oracle JETに含まれるコンポーネントのひとつである、Thematic MapをOracle APEXのアプリケーションに組み込んでみます。Thematic Mapでは、GeoJSONで与えられる最小限の地図を背景として、特定のテーマのデータ(降雨量など)を地図上に表示します。

Oracle JET CookbookのThematic Mapに含まれている例のうち、以下の4つをAPEXアプリケーションに組み込みます。


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


APEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/sample-oj-thematic-map-on-apex.zip

概ねOracle JET Cookbookに記載されているdemo.htmlおよびdemo.jsを少々改変しただけで、そのままAPEXのページに組み込んでいます。

いくつかのデモをAPEXアプリケーションに組み込んでいますが、手順はほとんど同じです。以下よりGenerating Mapsを例にとって、Thematic MapのAPEXアプリケーションへの組み込み手順を紹介します。

Oracle JET Cookbookより、APEXに組み込むコンポーネントのページを開きます。本記事の対象はThematic MapのGenerating Mapsです。

実装はJS - JavaScriptまたはTS - TypeScriptを選択できます。APEXのページに組み込むために、JS - JavaScriptを選択します。


実装例としてdemo.htmldemo.jsdemo.cssを参照できます。これらのコードを、APEXのページに転記します。

ページ・プロパティJavaScriptファイルURLに以下を記述します。APEXにバンドルされているJETライブラリが、ページに読み込まれます。

[require jet]

APEXにバンドルされているOracle JETライブラリは、必ずしも最新ではないことに注意が必要です。Oracle APEXにバンドルされているJavaScriptのライブラリのバージョンは、リリース・ノートの新機能(New Features)に記載されています。APEX 24.2にバンドルされているOracle JETのバージョンは、17.0.2です。

ページ・ロード時に実行に、demo.jsの内容を転記します。修正箇所については後ほど説明します。

CSSのファイルURLに以下を記載します。

#JET_CSS_DIRECTORY#redwood/oj-redwood-notag-min.css

インラインdemo.cssの内容を記載します。

ページに静的コンテンツリージョン(以下ではMap)を作成し、ソースHTMLコードdemo.htmlの内容を記載します。


Thematic Mapであるoj-thematic-map要素の部分をdemo.htmlから切り出し、静的コンテンツのリージョンのHTMLソースに記述します。

カスタム・イベントmapListenerを受けて表示するマップが切り替わるように、on-map-listener属性を追加しています。変更イベントを受けると、oj-thematic-map要素にバインドされたオブジェクトのmapListenerファンクションが呼び出されます。


JET Cookbookでは選択リストをJETのコンポーネントで実装していますが、これをAPEXの選択リストに置き換えています。ページ・アイテムの名前P5_MAPタイプ選択リストです。


LOVタイプ静的値を選択し、静的値としてAfricaAsiaAustraliaEuropeNorth AmericaSouth AmericaWorldを設定しています。


選択リストの変更イベントを受けて実行される動的アクションを作成し、以下のJavaScriptを実行しています。Thematic Mapの要素にカスタム・イベントmapListenerを発行しています。
// Thematic MapにmapListenerイベントを発行する。
document.getElementById("map1").dispatchEvent(
    new CustomEvent("mapListener", {
        detail: { value: $v(this.triggeringElement) }
    })
);

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

地図の背景となるJSONを静的アプリケーション・ファイルとして保存しているため、require句の引数ではなく、fetchファンクションでファイルを取得するように変更しています。


fetchの代わりにapex.server.processでAjaxコールバックを呼び出すことで、データベースに保存されたデータを取り出すことができます。

今回の記事は以上になります。

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

2025年5月19日月曜日

円グラフの凡例の選択とレポートの表示を連動させる

チャート・リージョンでは凡例のクリックにより、チャートからその凡例を取り除いたり、再度、チャートに含めたりすることができます。この選択された凡例をレポートの検索条件として、同時にレポートも更新します。

作成するアプリケーションは以下のように動作します。データ・ソースとしてサンプル・データセットEMP/DEPTに含まれる表EMPを使用し、従業員のジョブを凡例に表示し、円グラフにはジョブごとの給与の合計を表示します。


空のAPEXアプリケーションを作成し、ホーム・ページにすべて実装します。

チャート・リージョンのソースSQL問合せとして、以下を記述します。

select job, sal from emp


チャートの属性を開き、タイプにします。また、今回の実装では凡例をクリックするため、凡例表示オンにします。


シリーズ名前Salaryとします。ソース位置リージョン・ソースを選択し、列のマッピングラベルに列JOB値集計合計に列SALを設定します。


チャートの凡例をクリックして非表示に設定した凡例を保存するページ・アイテムをP1_HIDDENとして作成します。タイプ非表示です。JavaScriptのコードから値を設定するため、設定保護された値オフにします。今回の例ではページを送信することはないため違いはありませんが、セッション・ステートストレージリクエストごと(メモリーのみ)にします。


円グラフに連動して従業員を一覧するクラシック・レポートを作成します。

ソース表名EMPWHERE句に以下を記述します。送信するページ・アイテムとしてP1_HIDDENを設定します。
:P1_HIDDEN is null
or
job not in (
    select column_value from apex_string.split(:P1_HIDDEN,',')
)

チャートとレポートを連動させる動的アクションを作成します。

円グラフのチャートのリフレッシュ後JavaScriptコードを実行します。


TRUEアクションとして実行するJavaScriptのコードとして以下を記述します。チャート・ウィジェットに対してonoptionchangeイベントで実行されるハンドラを設定しています。チャート・ウィジェットに対するイベント・ハンドラの設定方法やonoptionchangeイベントについては、Oracle Forumや海外のパートナーのブログ記事で取り上げられているケースがありますが、公式なドキュメントからは見つけることができませんでした。



ページ・アイテムP1_HIDDENの値が変更されたときにクラシック・レポートの一覧を更新するため、ページ・アイテムP1_HIDDEN動的アクションを作成します。

タイミングイベント変更になります。


TRUEアクションリフレッシュ影響を受ける要素選択タイプリージョンとし、リージョンクラシック・レポートのリージョンを選択します。


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

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

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

2025年5月8日木曜日

チャートのY軸のラベルに任意のフォーマットを適用する

バー・チャートのY軸のラベルに任意のフォーマットを適用します。以下のように主要目盛が300K毎に表示されているチャートで、ラベルを300K、600K、900K、そして1Mを超えると1.2M、1.5Mと略記記号を変えます。


確認に使用しているチャート・リージョンのソースSQL問合せとして、以下を設定しています。
SELECT 1000 + (LEVEL - 1) * 80000 AS val, level l
FROM dual
CONNECT BY 1000 + (LEVEL - 1) * 80000 <= 2000000;

チャートのシリーズの列のマッピングとして、ラベルLVALを割り当てています。


Y軸のラベルのフォーマットですが、主に書式および書式スケールで決定されます。


書式が- 選択 -(つまり無指定)で書式スケール自動とすると、Y軸のラベルは以下のように表示されます。APEXアプリケーションの言語が日本語の場合、30.0万、60.0万、...のように単位が万になっています。


APEXアプリケーションのアプリケーション言語が日本語の場合、書式スケールは万、億、兆は選べますが、K、M、G、Tといった記号を選ぶことはできません。これらの書式スケールを選ぶには、アプリケーション言語を英語に切り替える必要があります。チャートやY軸ラベルに限定してロケールを英語に切り替える方法は見つかりませんでした


アプリケーション言語が日本語でも数値の表記はK、M、G、Tといった略記にしたい場合は多いと思います。

チャートの初期化JavaScriptファンクションで設定できるのは、基本的にConverterOptionsなので、Converterインターフェースを実装したクラスが持つformatファンクションは定義できません。そのため、数値ラベルを変換するIntlNumberConverterのインスタンスを生成し、formatファンクションを置き換えた上で、チャートのY軸ラベルのConverterとして使用します。

Converterの置き換えはチャートのリフレッシュ後に実施します。

Y軸ラベルを置き換えるチャートに動的アクションを作成します。タイミングイベントリフレッシュ後です。


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


IntlNumberConverterのインスタンスを生成しformatファンクションを置き換えた後、チャートのyAxis.tickLabel.converterに設定しています。


JavaScriptからチャートを参照するために、詳細静的IDとしてtestを設定しています。


また、チャートのY軸の書式少数を選択します。yAxis.tickLabel.converterに設定したIntlNumberConverterのインスタンスは、書式が少数のときに限り有効になるようです。


以上の設定で、アプリケーションが日本語でもY軸のラベルにK、Mといった略記が表示されます。

今回の記事は以上になります。

作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/sample-y-axis-ticklabel-format.zip

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

2025年5月2日金曜日

任意のSELECT文をデータ・ソースとしたOracle JETの表を動的に生成する

以前の記事「任意のSELECT文をデータ・ソースとしたJETチャートを動的に生成する」では、Oracle JETのoj-chart要素を動的に生成してチャートを表示しました。本記事ではoj-chartの代わりにoj-table要素を動的に生成することにより、任意のSELECT文をソースとした表を表示します。

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


アプリケーション自体はチャートの記事で作成したものとほぼ同じです。oj-chart要素は表示するデータを静的に割り当てることができましたが、oj-table要素はDataProviderとして割り当てる必要があります。そのため、アプリケーションの作り方が少し変わります。

このアプリケーションのエクスポートは以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/dynamic-jet-table.zip

以下よりチャートを表示するアプリケーションとの差分について説明します。

ページ・プロパティJavaScriptページ・ロード時に実行は以下になります。ojs/ojchartの代わりにojs/ojtableをロードします。

require(['ojs/ojtable'], function() {});


任意のSELECT文を渡して実行結果を得るAjaxコールバックGET_TABLEとして作成します。ソースPL/SQLコードとして以下を記述します。チャートのときはAjaxコールバックでHTMLを生成しましたが、oj-table要素はデータをHTMLの記述に含めることはできないため、列情報をcolumns属性、データをdata属性として持つJSONドキュメントを返すようにしています。



表の出力先となるDIV要素のIDをchartからtableに変更しています。

<div id="table"></div>


oj-table要素を生成するJavaScriptのコードは以下になります。ボタンGENERATEをクリックしたときに実行されるTRUEアクション設定コードを置き換えます。


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

Oracle JETのoj-tableのリファレンスは以下になります。今回はoj-tableを表示するために最低限必要な属性であるcolumnsとdataのみを設定しています。他の属性を設定することにより、より使い勝手を向上させることも可能でしょう。

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

チャートのタイトルを動的に変更する

Oracle APEXのチャートのタイトルを動的に変更する方法について調べてみました。設定を確認するために、以下のように動作するAPEXアプリケーションを作成しています。

表EMPをソースとしたバー・チャートを作成しています。選択リストのページ・アイテムで、バー・チャートの表示条件となるJOBを選択し、チャートを更新します。同時にチャートのタイトルを選択したJOBに変更しています。


このアプリケーションのエクスポートは以下に置いてあります。
https://github.com/ujnak/apexapps/blob/master/exports/update-chart-title.zip

チャートのタイトルの変更自体は簡単ですが、その実装方法はOracle APEXの公式なドキュメントに記載されていません。ただし、ChatGPTに聞くと大体教えてくれます。

ChatGPTに「Oracle APEXでJavaScriptでchart widgetを取得する手順を教えて」と聞いたところ、以下のコードを教えてくれました。
var chartWidget = apex.region("myChart").widget();
最後にChatGPTから「何を操作したいか(例:データ更新、再描画、ハイライトなど)も教えていただけますか?」と聞かれたので、「ChartのTitleを更新したい」と伝えたところ、以下のコードを教えてくれました。
var chart = apex.region("myChart").widget();
var currentOptions = chart.ojChart("option");

// タイトルを変更する
chart.ojChart("option", "title.text", "新しいタイトル");

// 必要に応じて再描画(通常は自動で反映されます)
Oracle JETのチャートのリファレンスは以下ですが、Oracle APEXのojChartインターフェース経由でどう使えるのかについては説明されていません。

カード・リージョン、ファセット・リージョン、対話グリッド、マップ・リージョンおよびテンプレート・コンポーネントといったJavaScriptの部分をOracle APEXの開発チームが実装しているコンポーネントについては、APIリファレンスにMethodsの説明があり、それを参照することによりJavaScriptで操作できます。

チャート・リージョンはOracle JETを使用しているため、Oracle APEXの開発チームにオーナーシップがありません。そのため、チャート・リージョンについてはページ・デザイナによる宣言的な設定がサポート範囲で、コードによる操作はサポートされません。そもそも、Oracle JETはOracle Corporationが保守しているオープンソース・プロジェクトであり、Oracle JET自体に一般的な製品サポートは提供されていません。

そういう意味ではコードで操作する場合、チャート・コンポーネントは他のオープンソースのフロントエンドのコンポーネントと同じ扱いになります。メンテナンス性を優先する場合は、使用は避けた方が良い、という点でも同じです。

以下より、今回作成したアプリケーションの実装を紹介します。

アプリケーションはすべてホーム・ページに実装しています。

チャートの表示条件となるページ・アイテムP1_JOB選択リストとして作成しています。LOVタイプSQL問合せを選択し、SQL問合せとして以下を記述しています。LOV表示値戻り値ともに表EMPの列JOBに含まれる個別値となります。

select job d, job r from emp group by job

P1_JOBで選択された戻り値をチャートのタイトルとして設定します。

ページ・アイテムが変更されたときに、チャートをリフレッシュする動的アクションを作成します。


チャート・リージョン識別名前給与として作成しています。

ソース表名EMPを指定し、WHERE句:P1_JOB is null or JOB = :P1_JOBを記述しています。送信するページ・アイテムP1_JOBを設定します。この設定により、リージョンのリフレッシュを実行した際に、P1_JOBが空であれば全従業員の給与がバーチャートに表示され、P1_JOBに値があれば、そのJOBを持つ従業員のみがバー・チャートに表示されます。

チャートをJavaScriptから操作するために、詳細静的IDmyChartを設定します。


チャートの属性タイトルとして&P1_JOB.を設定します。これはチャート、つまりOracle JETのチャート・コンポーネントが表示するタイトルになります。


基本的な設定は以上になります。

これから、チャートのタイトルを描画する処理について考えていきます。

最初にページがロードされると、ページに含まれる置換文字列&P1_JOB.が、ページ・アイテムP1_JOBの値で置き換えられます。

ページ・アイテムP1_JOBセッション・ステートストレージセッションごと(永続)としているため、ページ・ロード時にセッション・ステートに保存されている値が反映されます。これがリクエストごと(メモリーのみ)であれば、(デフォルト計算が未設定であれば)つねにページ・アイテムの値は空白になります。

ページ・アイテムP1_JOBの選択を変更したときに、動的アクションでチャートをリフレッシュしています。リージョンの送信するページ・アイテムP1_JOBが設定されていて、そしてセッション・ステートストレージセッションごと(永続)であるため、送信された値がセッション・ステートに保存されます。結果として、ページ・ロード時のP1_JOBの値は、直近のチャートのリフレッシュ時に送信されたP1_JOBの値になります。


置換文字列&P1_JOB.の置き換えはページ・ロード時にのみ行われます。チャートの属性タイトルに設定した&P1_JOB.は、ページ・ロード後はページ・アイテムP1_JOBの値が変わっても、その値が反映されることはありません。


次にチャート・リージョンの属性詳細初期化JavaScriptファンクションが実行されます。初期化JavaScriptファンクションでは、属性に設定項目が存在しない設定もできます。

今回のアプリケーションでは以下のように記述しています。ページ・デザイナで設定した値が引数optionsとして渡され、必要な変更をoptionsに適用して戻します。
function( options ) {
    apex.debug.info(options);
    const job = apex.items.P1_JOB.value ? apex.items.P1_JOB.value : "すべてのJOB";
    // const job = apex.items.P1_JOB.value;
    if ( options.title ) {
        // titleが初期化済みであれば、textのみを更新する。
        options.title.text = job;
        apex.debug.info("INIT: title.text is replaced, ", job);
    }
    else
    {
        // そうでない場合は中央揃えも含めてtitleを初期化する
        options.title = {
            "halign": "center",
            "text": job
        };
        apex.debug.info("INIT: title.text is created, ", job);
    };
    return options;
}
optionsにどのような値が設定されているか、または、どのような値が設定可能かについては、ドキュメント化されていないため、JavaScriptコンソールにoptionsを印刷するか、または、チャート・ウィジェットからoptionを取り出して確認します。

apex.region("myChart").widget().ojChart("option")

例えば、JavaScriptコンソールなどから実行します。


初期化JavaScriptファンクションに渡されるoptionsは、ページ・デザイナで設定している内容に限定されます。リージョンの属性タイトルに値がない場合は、title自体がnullになるため、options.title.textを設定することはできません。そのため初期化JavaScriptファンクションでは、options.titleに設定がない場合は、水平アラインメント(halign)の設定も含めてoptions.titleを設定しています。

初期化JavaScriptファンクションはページ・ロード時に実行されます。リージョンのリフレッシュ時には実行されません。そのため、ページ・アイテムP1_JOBの値が変更されたときは、動的アクションとして同等の処理を実行する必要があります。動的アクションには引数optionsが渡されないため、apex.region("myChart").widget().ojChart()を呼び出して設定を更新します。

チャート・リージョンに必ずタイトルが設定されている場合は、以下のコードでタイトルだけを変更できます。
const job = this.triggeringElement.value ? this.triggeringElement.value : "すべてのJOB";
// const job = this.triggeringElement.value;
apex.region("myChart").widget().ojChart(
    "option",
    "title.text",
    job
);
タイトルが未設定のときがあれば、以下のコードでタイトルを設定できます。
const job = this.triggeringElement.value ? this.triggeringElement.value : "すべてのJOB";
// const job = this.triggeringElement.value;
apex.region("myChart").widget().ojChart(
    "option",
    "title",
    {
        "halign": "center",
        "text": job
    }
);
同じ変更ですが、引数optionを除いて、以下のように呼び出せるようです。
const job = this.triggeringElement.value ? this.triggeringElement.value : "すべてのJOB";
// const job = this.triggeringElement.value;
apex.region("myChart").widget().ojChart(
    { 
        "title": {
            "halign": "center",
            "text": job
        }
    }
);
今回の記事は以上になります。

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

2025年3月14日金曜日

任意のSELECT文をデータ・ソースとしたJETチャートを動的に生成する

チャートのタイプ(バーまたはパイ・チャート)を選択し、任意のSELECT文をデータ・ソースとしたJETチャートを動的に生成するAPEXアプリケーションを作成します。

作成するAPEXアプリケーションは以下のように動作します。


以下より作成したAPEXアプリケーションについて説明します。

最初に空のAPEXアプリケーションを作成します。名前Dynamic JET Chartとします。


機能はすべてホーム・ページに実装します。ホーム・ページページ・デザイナで開きます。


チャート・タイプを選択するページ・アイテムとしてP1_CHART_TYPEを作成します。タイプ選択リストラベルChart Typeとします。

LOVタイプ静的値を選択します。NULL表示値- Select Chart Type -とします。


LOV静的値として表示値Pie Chartpie表示値Bar Chartbarのペアを設定します。


データ・ソースとなるSELECT文を記述するページ・アイテムとしてP1_SQLを作成します。タイプテキスト・フィールドラベルSource SQL Statementとします。


チャートを生成するボタンとしてGENERATEを作成します。外観ホットオンテンプレート・オプションWidthStretchにします。

動作アクションとして動的アクションで定義を設定します。JETチャートのHTML要素はサーバー側で生成しますが、チャートの描画はクライアント側のJavaScriptで行います。


JETチャートを描画するリージョンを作成します。識別名前Chartタイプ静的コンテンツとし、ソースHTMLコードとして以下を記述します。

<div id="chart"></div>

外観テンプレート・オプションBody Height640pxTop MarginMediumに設定しています。


JETチャートのHTML要素を生成するプロセスを、Ajaxコールバックとして実装します。

識別名前GET_CHARTタイプとしてコードを実行を選択します。ソースPL/SQLコードとして以下を記述します。



作成したAjaxコールバックGET_CHARTをボタンGENERATEをクリックしたときに呼び出すように、動的アクションを作成します。

ボタンGENERATE動的アクションを作成します。識別名前onClick GENERATEとします。タイミングイベントはデフォルトのクリックです。


TRUEアクションとして以下のJavaScriptコードを実行します。JETチャートのHTML要素はデータベース・サーバーで生成しますがページの再ロードを避けるため、画面への描画はブラウザ上で実施します。
apex.server.process( "GET_CHART", {
    pageItems: "#P1_CHART_TYPE,#P1_SQL"
}, {
    success: function( data )  {
        apex.debug.info(data.markup);
        const elem = document.getElementById("chart");
        elem.insertAdjacentHTML('afterbegin', data.markup);
    }
} );

最後にページ・プロパティに、JETのライブラリをロードするために必要な設定を追加します。ページにチャート・リージョンが含まれる場合は、Oracle APEXがJETライブラリをロードするためのコードを生成します。しかし、今回作成しているアプリにはJETを必要としているコンポーネントがページにないため、JETライブラリがロードされません。

ページ・プロパティJavaScriptファイルURLに以下を記述します。

[require jet]

ページ・ロード時に実行に以下を記述します。

require(["ojs/ojchart"], function() {});

CSSファイルURLに以下を記述します。

#JET_CSS_DIRECTORY#redwood/oj-redwood-notag-min.css


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

Oracle JETのドキュメントへのリンクは以下になります。
https://www.oracle.com/webfolder/technetwork/jet/index.html

主にCookbookとAPI Documentを参照することになりますが、わかりやすいとはいえないです。
https://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html
https://docs.oracle.com/en/middleware/developer-tools/jet/18/reference-api/index.html

Oracle JETはサンプルも少なく扱いにくい印象がありましたが、Claude 3.7 Sonnetに聞くとそれなりの回答が返されます。ドキュメントにあたる前に生成AIに聞くと時短になります。


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

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