作成するAPEXアプリケーションは以下のように動作します。
以下より作成したAPEXアプリケーションについて説明します。
最初に空のAPEXアプリケーションを作成します。名前はDynamic JET Chartとします。
機能はすべてホーム・ページに実装します。ホーム・ページをページ・デザイナで開きます。
チャート・タイプを選択するページ・アイテムとしてP1_CHART_TYPEを作成します。タイプは選択リスト、ラベルはChart Typeとします。
LOVのタイプに静的値を選択します。NULL表示値は- Select Chart Type -とします。
LOVの静的値として表示値がPie Chart、値がpieと表示値がBar Chart、値がbarのペアを設定します。
動作のアクションとして動的アクションで定義を設定します。JETチャートのHTML要素はサーバー側で生成しますが、チャートの描画はクライアント側のJavaScriptで行います。
JETチャートを描画するリージョンを作成します。識別の名前はChart、タイプは静的コンテンツとし、ソースのHTMLコードとして以下を記述します。
<div id="chart"></div>
外観のテンプレート・オプションのBody Heightを640px、Top MarginをMediumに設定しています。
JETチャートのHTML要素を生成するプロセスを、Ajaxコールバックとして実装します。
識別の名前はGET_CHART、タイプとしてコードを実行を選択します。ソースのPL/SQLコードとして以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
/* SELECT文の実行 */ | |
l_sql varchar2(32767); | |
l_cursor integer; | |
l_col_cnt integer; | |
l_desc_tab dbms_sql.desc_tab; | |
e_invalid_sql exception; | |
l_label varchar2(4000); | |
l_label_name varchar2(4000); | |
l_value number; | |
l_rows number; | |
/* JETチャートに埋め込むデータ */ | |
l_groups_arr json_array_t; | |
l_group json_object_t; | |
l_series_arr json_array_t; | |
l_series json_object_t; | |
l_items_arr json_array_t; | |
l_item json_object_t; | |
l_series_clob clob; | |
l_groups_clob clob; | |
l_items_clob clob; | |
/* JETチャートのマークアップ */ | |
l_html clob; | |
l_response_clob clob; | |
l_response json_object_t; | |
l_chart_id varchar2(40); | |
l_chart_type varchar2(8); | |
e_invalid_chart_type exception; | |
/* | |
* バーチャートのテンプレート | |
*/ | |
C_TEMPLATE_BAR_CHART constant clob := q'~ | |
<oj-chart | |
id="#CHART_ID#" | |
type="bar" | |
orientation="horizontal" | |
stack="off" | |
groups='#GROUPS#' | |
series='[ { "items": #ITEMS# } ]' | |
animation-on-display="auto" | |
animation-on-data-change="auto" | |
hover-behavior="dim"> | |
</oj-chart> | |
~'; | |
/* | |
* パイチャートのテンプレート | |
*/ | |
C_TEMPLATE_PIE_CHART constant clob := q'~ | |
<oj-chart | |
id="#CHART_ID#" | |
type="pie" | |
selection-mode="single" | |
series='#SERIES#' | |
animation-on-display="auto" | |
animation-on-data-change="auto" | |
hover-behavior="dim"> | |
</oj-chart> | |
~'; | |
begin | |
l_chart_type := :P1_CHART_TYPE; | |
/* | |
* JETチャートに与えるデータを保持する。 | |
*/ | |
l_groups_arr := json_array_t(); | |
l_series_arr := json_array_t(); | |
l_items_arr := json_array_t(); | |
/* | |
* P1_SQLには2つの列、最初にラベルとなる列と次に値となる数値列を | |
* 持つSELECT文が記載されていることを前提としている。 | |
*/ | |
-- 与えられたSQLの検証 | |
l_sql := :P1_SQL; | |
if l_sql is null or l_sql = '' then | |
raise e_invalid_sql; | |
end if; | |
-- カーソルのオープン | |
l_cursor := dbms_sql.open_cursor; | |
-- SQLのパース | |
dbms_sql.parse(l_cursor, l_sql, dbms_sql.native); | |
/* | |
* 最初のラベルとなる列の名前を取得する。ただし、今の所は使用していない。 | |
*/ | |
dbms_sql.describe_columns(l_cursor, l_col_cnt, l_desc_tab); | |
l_label_name := l_desc_tab(1).col_name; | |
-- 列の定義 | |
dbms_sql.define_column(l_cursor, 1, l_label, 4000); | |
dbms_sql.define_column(l_cursor, 2, l_value); | |
-- SELECT文の実行 | |
l_rows := dbms_sql.execute(l_cursor); | |
loop | |
exit when dbms_sql.fetch_rows(l_cursor) = 0; | |
dbms_sql.column_value(l_cursor, 1, l_label); | |
dbms_sql.column_value(l_cursor, 2, l_value); | |
/* JETチャートに含めるデータを作成する */ | |
if l_chart_type = 'bar' then | |
l_group := json_object_t(); | |
l_group.put('name', l_label); | |
l_groups_arr.append(l_group); | |
l_items_arr.append(l_value); | |
elsif l_chart_type = 'pie' then | |
l_series := json_object_t(); | |
l_series.put('name', l_label); | |
l_items_arr := json_array_t(); | |
l_items_arr.append(l_value); | |
l_series.put('items', l_items_arr); | |
l_series_arr.append(l_series); | |
else | |
raise e_invalid_chart_type; | |
end if; | |
end loop; | |
-- カーソルのクローズ | |
dbms_sql.close_cursor(l_cursor); | |
/* | |
* JETチャートのマークアップを生成する。 | |
*/ | |
l_groups_clob := l_groups_arr.to_clob(); | |
l_series_clob := l_series_arr.to_clob(); | |
l_items_clob := l_items_arr.to_clob(); | |
/* | |
* JETチャートのテンプレレートにデータを埋め込み、 | |
* マークアップを完成させる | |
*/ | |
l_chart_id := 'chart' || sys_guid(); | |
if l_chart_type = 'bar' then | |
l_html := replace(C_TEMPLATE_BAR_CHART, '#CHART_ID#', l_chart_id); | |
/* バーチャートはgroupsとseriesにデータを与える */ | |
l_html := replace(l_html, '#GROUPS#', l_groups_clob); | |
l_html := replace(l_html, '#ITEMS#', l_items_clob); | |
elsif l_chart_type = 'pie' then | |
l_html := replace(C_TEMPLATE_PIE_CHART, '#CHART_ID#', l_chart_id); | |
/* パイチャートはseriesにデータを与える */ | |
l_html := replace(l_html, '#SERIES#', l_series_clob); | |
end if; | |
/* | |
* 呼び出し元にJSON形式でJETチャートの要素を返す。 | |
* { "markup": "JETチャートの要素" } | |
*/ | |
l_response := json_object_t(); | |
l_response.put('markup', l_html); | |
l_response_clob := l_response.to_clob(); | |
htp.p(l_response_clob); | |
end; |
作成した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のアプリケーション作成の参考になれば幸いです。
完