2025年11月26日水曜日

LeafletのQuick Start GuideをAPEXアプリケーションに実装してみる

2Dのマップ表示の用途で人気の高いLeafletによるマップを、Oracle APEXのアプリケーションに組み込んでみます。組み込む機能はLeafletのQuick Start Guideで紹介されている、以下を対象とします。
  • ラスタタイルの表示(国土地理院タイルを使用します)
  • マーカーの表示/非表示、およびポップアップの表示/非表示
  • サークルの表示/非表示、およびポップアップの表示/非表示
  • ポリゴンの表示/非表示、およびポップアップの表示/非表示
  • スタンドアロンのポップアップ表示/非表示
  • マップ上のクリックによるポップアップの表示
上記を実装したAPEXアプリケーションは、以下のように動作します。渋谷のスクランブル交差点を中心に地図を表示し、マーカー、サークルおよびポリゴン(道玄坂)などを表示しています。


Leaflet Quick Start Guideに沿って、APEXアプリケーションの組み込みを実施します。

空のアプリケーションを作成します。名前Leafletとします。


APEXアプリケーションが作成されます。今回はデフォルトで作成されるホーム・ページに、すべての機能を実装します。


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

ホーム・ページに、Quick Start GuideのPreparing your pageに記載されている設定を加えます。

Oracle APEXには、ページにロードするJavaScriptファイルを指定するプロパティとして、JavaScriptファイルURLCSSファイルを指定するプロパティとして、CSSファイルURLがあります。

LeafletのQuick Start Guideでは、ロードするCSSファイルおよびJavaScriptファイルに属性integritycrossoriginの指定が含まれています。これらは、APEXのプロパティでは設定できません。また、必ずCSSファイルをJavaScriptファイルの前にロードするように指示されています。こちらについては、ページ・プロパティのCSSファイルURL(link要素)は、必ずJavaScriptファイルURL(script要素)よりも先にHTMLとして出力されます。

integritycrossoriginの設定を残すために、ページ・プロパティHTMLヘッダーに、Quick Start Guideに記載されている内容をそのまま転記します。
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
    integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
    crossorigin=""/>
<!-- Make sure you put this AFTER Leaflet's CSS -->
 <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
     integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
     crossorigin=""></script>
CSSインラインでマップの高さを指定します。Quick Start Guideでは180pxとなっていますが、それよりも高い640pxを設定します。

#map { height: 640px; }


Leafletを初期化するdiv要素を含むリージョンを作成します。

識別名前Mapタイプ静的コンテンツソースHTMLコードに以下を記述します。

<div id="map"></div>


以上で、Preparing your pageに記載されている内容をホーム・ページに設定できました。

Leafletの初期化から、マーカーの表示/非表示、サークルの表示/非表示など、JavaScriptによる実装はすべて、静的アプリケーション・ファイルに記述します。以下のファイルを、静的アプリケーション・ファイルとして保存します。名前はapp.jsとします。



LeafletのQuick Start Guideでは、マーカー、サークルおよびポリゴンを表示するコードは紹介されていますが、それを非表示にするコードはありません。上記のapp.jsには、非表示にするコードも追加しています。

マーカーなどの表示/非表示はAPEXアクションとして定義し、ページ上のボタンとカスタム属性data-actionによって紐付けています。

ページ・ロード時に静的アプケーション・ファイルapp.jsがロードされるように、ページ・プロパティJavaScriptファイルURLに以下を設定します。

#APP_FILES#app#MIN#.js


静的アプリケーション・ファイルに記述したAPEXアクションを呼び出すボタンを、ページ上に作成します。

ボタンを一列で配置するために、静的コンテンツのリージョンを作成します。外観テンプレートButtons Containerを選択します。


APEXアクションを呼び出すボタンを作成します。

ボタンの詳細カスタム属性に記述するdata-actionで、APEXアクションに紐付けます。

data-action="TOGGLE_MARKER"

ボタンのクリックでページの送信などが動作しないように、動作アクション動的アクションで定義を設定します。

識別ラベルは、data-actionで紐づけられたAPEXアクションのlabel属性の値に置き換わります。そのため、ページでの設定値は画面に表示されません。


同様にTOGGLE_CIRCLETOGGLE_POLYGONTOGGLE_MARKER_POPUPTOGGLE_CIRCLE_POPUPTOGGLE_POLYGON_POPUPTOGGLE_STANALONE_POPUPのボタンを作成します。

これらのボタンは、TOGGLE_MARKERと横一列に並べるため、レイアウト新規行の開始オフにします。それ以外はdata-actionに、それぞれに紐づけるAPEXアクション名を設定します。


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

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

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

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年11月20日木曜日

JSON Regionプラグインを使用して東京都こどもDX子育て支援制度レジストリのJSONを編集する

Oracle AI Database 26aiには、JSONをそのままJSONとして保存できるJSONコレクション表というオブジェクトがあります。このJSONコレクション表に東京都のオープンデータ「東京都こどもDX_子育て支援制度レジストリ」を保存し、簡単なレポートとフォームのページを作成してみます。

保存先がリレーショナル表の場合は、APEXの標準コンポーネントを使うことができます。今回はJSON形式のデータをJSONコレクション表に保存し、JSONのまま操作します。JSONのまま操作するために、Uwe Simonさんが作成されたJSON Regionプラグインを使用します。

Oracle APEXでは共有コンポーネントとしてJSONソースがあります。JSONソースを作成することにより、JSONコレクション表からAPEXのデータ・ソースを定義できます。ただし、JSONソースはデータ・プロファイル(JSONの属性を列として見せる定義)が静的に定義されています。JSONデータの属性の追加や削除に対応するには、データ・プロファイルを更新する必要があります。この作業はアプリケーションの開発者が実施し、APEXアプリケーションの更新を伴います。

リージョン・プラグインのJSON Regionは、JSONデータとJSONスキーマの定義から、動的にフォームを生成します。フォームに表示するアイテムやレイアウトは、JSONスキーマによって決まります。これは、アプリケーションに静的に記述したり、JSONデータから動的に生成したり、SELECT文を実行してデータベースから取り出したり、色々な方法で決めることができます。フォームのアイテムやレイアウトの自由度には制限がありますが、表示するデータに依存したフォームの生成が可能です。

作成するAPEXアプリケーションは以下のように動作します。アプリケーションの動作や見かけは、データソースがリレーショナル表のときと違いはありません。


以下よりAPEXアプリケーションの作成手順を紹介します。

最初に東京都の子育て支援制度をJSONのまま保存する、JSONコレクション表TOKYO_KOSODATESHIENSEIDOを作成します。

create json collection table tokyo_kosodateshienseido with etag;

APEXのSQLコマンドから実行します。


東京都オープンデータカタログサイトの東京都こどもDX_子育て支援制度レジストリのページを開き、JSON形式のデータのURLを確認します。本記事では2025年8月20日時点のデータを参照しています。


SQLコマンドで以下のコードを実行し、JSONデータのダウンロードとJSONコレクション表への投入を実施します。

実行結果には1行が挿入されました。と表示されています。PL/SQLブロックを実行したときは、このように表示されます。表に挿入された行数ではありません。


データの準備ができたので、APEXアプリケーションの作成に移ります。

空のAPEXアプリケーションを作成します。名前東京都子育て支援制度とします。


APEXアプリケーションが作成されます。JSON Regionプラグインの導入から始めます。


APEX Worldのサイトを開き、Plug-insのタブを選択します。Plug-in typeRegionを選択し、Search KeywordJSONを入れてプラグインを検索します。

JSON-Region 0.9.8.0(バージョンは変わるかもしれません)が見つかるので、それを開きます。


Downloadをクリックし、プラグインやサンプル・アプリケーションを含むZIPファイルをダウンロードします。


2025年11月20日時点では、simonuwe-oracle-apex-json-region-rel-0.9.8.0-0-g67958cf.zipというファイル名で、ファイルがダウンロードされました。

このファイルを解凍しておきます。

APEXに戻り、共有コンポーネントプラグインを開きます。


インポートをクリックします。


インポートするファイルとして、ダウンロードしたZIPファイルに含まれているplug-in/region_type_plugin_json_region_uwesimon_selfhost_e.sqlを選択します。ファイル・タイププラグインです。

へ進みます。


ファイルのインポートが完了しました。へ進みます。


プラグインをインストールします。


コンポーネント設定SQL-Query for referenced JSON-schemaのデフォルト値の設定を求められます。必須ではなく、後からでも変更できるので空白のままとします。

変更の適用をクリックします。


コンポーネント設定のページに移ります。

すでにJSON-Regionプラグインは作成されています。


JSONコレクション表TOKYO_KOSODATESHIENSEIDOをソースとした、対話モード・レポートとフォームのページを作成します。

ページの作成をクリックします。


対話モード・レポートを選択します。


レポート定義名前支援制度一覧フォーム・ページを含めるオンにし、フォーム・ページ名として支援制度を設定します。ページ番号はそれぞれ、とします。

データ・ソースソース・タイプSQL問合せを選択し、SQL SELECT文を入力に以下を記述します。

select json_value(data,'$._id') "_id", data from tokyo_kosodateshienseido

へ進みます。


主キー列_id (Varchar2)を選択します。MongoDBと互換性を持つためだと思われますが、JSONコレクション表は属性"_id"として、一意キーが設定されています。

ページの作成をクリックします。


対話モード・レポートとフォームのページが作成されます。


APEXアプリケーションを実行します。

対話モード・レポートにはJSONがそのまま表示されています。任意の行の編集アイコンをクリックし、ドロワーを開きます。


ドロワーが開いたら、JSONは変更せずに、変更の適用をクリックします。


以下のエラーが発生します。これは、更新するJSONに"_id"属性が含まれていることが原因です。

ORA-54059: 不変列("WKSP_APEXDEV"."TOKYO_KOSODATESHIENSEIDO"."RESID")は別の値に更新できません


JSONコレクション表を操作するプロセス・フォーム支援制度の前に、プロセスRemove _idを作成します。タイプコードを実行です。

ソースPL/SQLコードに以下を記述し、受信したデータより"_id"属性を削除します。

select json_transform(:P3_DATA, remove '$._id') into :P3_DATA;

サーバー側の条件ボタン押下時SAVEを指定します。


プロセスRemove _idを追加することで先ほどのエラーは発生しなくなり、フォームでJSONデータを更新できるようになります。

これから、ページ・アイテムP3_DATAに含まれるJSONデータからフォームを生成します。

ページ・アイテムP3_DATAの下にリージョンを作成します。

識別名前JSON Regionタイプに先ほど導入したプラグインであるJson-Regionを選択します。


Json-Regionの属性を開きます。

設定JSON-itemにJSONデータが含まれるページ・アイテムP3_DATAを選択します。JSONスキーマのSourceとして、Generate Schemaを選択します。この設定では、JSONスキーマはP3_DATAに保存されているデータから生成されます。

その他は用途によって変更します。以下ではHide JSON-itemオンにしているので、JSONデータを保持しているP3_DATA非表示に変わります。


先ほどと同様の手順でフォームを開くと、JSONデータの代わりに自動的に生成されたフォームが開きます。


このままでは見辛いので、JSONスキーマを定義して表示されるページ・アイテムを限定します。

設定SourceStaticに変更し、Static Schemaに以下を記述します。

Column Width12を指定します。Universal Themeは横幅を12分割して配置を決めています。列幅に12を設定すると、1列すべてを1つのページ・アイテムが占有します。つまり、1列に1つだけページ・アイテムが配置されます。


先ほどと同様の手順でフォームを開きます。今度はJSONスキーマの定義に従ったフォームが開かれます。


編集も可能です。変更の適用をクリックします。


フォームのデータに一切変更を加えていないくても、JSON Regionの設定にあるKeep additional attributesRemove NULLS from JSONといった設定により、属性が削除されることがあります。また、JSON Regionが更新するのはページ・アイテムP3_DATAに読み込まれたJSONデータであり、データベースはP3_DATAの値で更新されます。JSON_TRANSFORMを呼び出して更新する場合と異なり、JSONデータは全体が更新されます。


本記事のテーマであるJSON Regionの組み込みは以上で完了です。

対話モード・レポートの表示がJSONそのままではいけないので、属性ごとに列として表示されるように変更します。

JSONコレクション表からJSONデータガイドを生成し、それを元にビューを作成します。

SQLコマンドで以下のスクリプトを実行し、ビューTOKYO_KOSODATESHIENSEIDO_Vを作成します。



対話モード・レポートのソースSQL問い合わせを、作成したビューTOKYO_KOSODATESHIENSEIDO_Vを参照するように変更します。

select * from tokyo_kosodateshienseido_v


対話モード・レポートで新しく認識された列は、デフォルトでは表示されません。

アクション・メニューを開き、新しく認識された列をレポートに表示します。


選択した列が対話モード・レポートに表示されます。これでJSONの属性がそれぞれ列として表示されるようになりました。

編集アイコンをクリックすると、ORA-1403が発生します。


これは対話モード・レポートでは主キーの値(属性"_id"の値)が大文字なのに対して(JSONデータガイドを元に作成したビューが列"_id"を大文字で返す)、フォームでは小文字で扱うためです。

フォームが"_id”の値を小文字で受け取るように、プロセス初期化フォーム支援制度の前にP3__IDの値を小文字に変換するプロセスを作成します。

識別名前Lower P3__IDとします。ソースPL/SQLコードに以下を記述します。

:P3__ID := lower(:P3__ID);

サーバー側の条件タイプアイテムはNULLではないを選択し、アイテムとしてP3__IDを設定します。


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

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

JSON RegionのプラグインとしてダウンローしたZIPには、プラグインの他にもサンプル・プログラムなどが含まれています。便利なプラグインなので、使い方を学ぶことをお勧めします。

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

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