2020年8月27日木曜日

コンポーネントの見かけを変更する

 ページ・アイテムに含まれるラベルの色を変更するにはどうすればよいのか、という問い合わせを受けました。Oracle APEXはリージョン、ページ・アイテム、ボタン、その他色々なコンポーネントが含まれます。その見かけを変更する方法をそれぞれ覚えるのは、あまり現実的ではないでしょう。

これから、見かけを変更するための勘所というか、どこを変更すれば良いのか調べる方法について紹介しようと思います。

今回はページ・アイテムのラベルでした。


画面上に表示されるコンポーネントは必ずテンプレートの指定を含みます。ページ・デザイナにて、該当のラベルを持つページ・アイテムのテンプレートの設定を確認します。右ペインに配置されているプロパティ・エディタの外観のセクションに含まれています。

テンプレートとしてOptionalが選択されています。その他にも選択肢がいくつかあります。

Optional - Aboveを選ぶと以下のように表示されます。

Optional - Floatingでは以下です。


Requiredは以下です。必須を示す赤い印がラベルの先頭に付きます。

このように表示形式が変わるのは、ページ・アイテムに紐づいているテンプレートが異なるためです。では、使用しているテンプレートを参照します。

左ペインで共有コンポーネント・ビューを選びます。このビューは、ページ・デザイナで開いているページが参照している共有コンポーネントへのアクセスを提供します。今回の対象となっているP1_COLORED_TEXTという名前のページ・アイテムが参照しているテンプレートはOptionalです。Optionalを選択し、プロパティ・エディタからコンポーネントの編集を開きます。


ページ・アイテムが使用しているテンプレートの定義が開きます。


定義を確認します。


ラベルの前には、次のHTMLが出力されます。

<div class="t-Form-labelContainer col col-#LABEL_COLUMN_SPAN_NUMBER#">
<label for="#CURRENT_ITEM_NAME#" id="#LABEL_ID#" class="t-Form-label">

ラベルの後は、次のHTMLです。

</label>
</div>

labelエレメントのclass指定にテキスト色を指定するCSSクラスを指定すれば、色を設定できそうなことがわかります。id属性である#LABEL_ID#として何が設定されるのかを確認します。Chromeの開発者ツールを使ってみました。


ラベルの表示に関わる部分は以下です。

<label for="P1_COLORED_TEXT" id="P1_COLORED_TEXT_LABEL" class="t-Form-label">色付きテキスト</label>

idはP1_COLORED_TEXT_LABELであることが分かります。

後はclassに文字の色付けを行うクラス定義を追加するだけです。色々な方法があるかと思いますが、ここではjQueryを使ってみます。

$("#P1_COLORED_TEXT_LABEL").addClass("u-color-8-text")

このコードがページ・ロード時に実行されるようにJavaScriptページ・ロード時に実行へ指定します。


以上で、ページ・アイテムのラベルに色をつけることができました。

画面上の見かけを変更するために、元となるテンプレートの参照方法について紹介しました。今回はテンプレート自体は変更せずに、テンプレートを元に出力されたページをJavaScriptによって動的に変更しています。

より手の込んだ変更を行う場合は、テンプレートの記述そのものを変更します。特にクラシック・レポートに適用するテンプレートが対象である場合に有効な手法ですが、そちらについては、また記事を改めて紹介したいと思います。

Oracle APEXワークショップ資料の更新

昨年作成したOracle APEXのワークショップ資料を更新しました。これからOracle APEXを始めよう、という方がいらっしゃいましたらトライしてみてはどうでしょう?

Oracle APEX Workshop I 日本語版



それぞれの操作を収録した動画の一覧はこちらになります。

Oracle APEX Workshop II 日本語版



それぞれの操作を収録した動画の一覧はこちらになります。

Oracle APEX Workshop III 日本語版



それぞれの操作を収録した動画の一覧はこちらになります。

2020年8月26日水曜日

ページ・アイテムの色を指定する

 ページ・アイテムの色を指定するには、どのようにすればよいのかという質問があったので、確認してみました。

まず、Oracle APEXのユニバーサル・テーマでは、色を指定するためのCSSクラスをあらかじめ用意されています。

https://apex.oracle.com/pls/apex/apex_pm/r/ut/color-and-status-modifiers


ですので、この中から適切な色となるクラスを選んで、詳細CSSクラスへ設定することでテキストの色を変更することができます。

例えば、u-color-8-textを設定するとページ・アイテムの表示は以下のようになります。

u-color-8-bgを指定すると、以下のようになります。


ユニバーサル・テーマはStateful Color Utilitiesとして、いくつかの状態にたいして指定する色を決めています。たとえば、危険を意味する色、警告を意味する色、単なる情報を意味する色などです。定義は以下になります。


ですので、直接色を指定するのではなく、どういった意味合いの色なのかを指定し、色、それ自体はテーマ・ローラーで割り当てるようにすると、標準の部分も含めて配色が変わります。

例えば、u-success-textを詳細のCSSクラスに設定します。標準では文字は緑色になります。


Oracle APEXの標準機能によって表示される成功メッセージも緑色です。テーマ・ローラーを開いて、StatesのSuccessに指定されている色を変更します。デフォルトでは緑色です。


青にすると、u-success-textとして指定した文字も、標準のメッセージも共に青に変更されます。このようにすることで、アプリケーションの配色に一貫性を持たせることが可能になります。



先ほど、u-color-8-textを指定することで文字を橙色に設定しました。この色はテーマ・ローラーのPalletの指定で変更できます。Color 8を赤に変更してみました。



Oracle APEXのユニバーサル・テーマでの色の扱いについての説明は(英語ですが)以下になります。


ページ・アイテムの色指定についての説明は以上です。

2020年8月21日金曜日

APEXコレクションを対話グリッドで扱う

 社内の質問箱に、APEXコレクションを対話グリッドで扱うには?という質問があったので、試しに実装してみました。

そもそもAPEXコレクションとは?

マニュアルのこちらに説明があります。開始されたセッションに紐づけて、データを保存や参照をすることができます。

データベースの一時表に似ていますが、Oracle APEXのそれぞれのリクエストは異なるデータベースのセッションで処理が行われるため、データベースのセッションに紐づけて行を保存する一時表は使えません。

APEX_COLLECTIONの初期化


セッションの開始後に、アプリケーション・プロセスなどでコレクションを作成します。以下の例ではコレクションの名前をTESTにしています。
apex_collection.create_or_truncate_collection(
p_collection_name => 'TEST'
);

対話グリッドの定義


ソースとして与えるSQLの例は以下になります。SEQ_IDを主キーとして扱うので、これは必ず含めます。それ以外はデータの保存に使用している列を含めます。以下の例ではC001とC002です。それ以外のカラムも必要にしたがって追加することができます。


SQL問合せの本文は以下になります。
select
       SEQ_ID,
       C001,
       C002
  from APEX_COLLECTIONS
where collection_name = 'TEST'
属性の編集有効にします。


主キーとなる列SEQ_IDの設定です。タイプ非表示とし、主キーONにします。


プロセスの設定


対話グリッド上でデータが編集し保存を実行すると、変更分のみがサーバーへ送信されます。SQLのINSERT/UPDATE/DELETE文をAPEXコレクションに実行することはできないため、それに対応した処理をPL/SQLコードとして記述します。


ターゲット・タイプPL/SQL Codeとし、行のロックNoに設定します。コードには以下を記述します。

挿入、更新、削除に対応したAPEX_COLLECTION APIをそれぞれ呼び出しているだけですので、コードの理解は難しくはないかと思います。

このように実装することで、APEXコレクションを対話グリッドで扱うことが可能になります。

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

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

2020年8月12日水曜日

HTTPヘッダーによる認証の制御について

 Autonomous DatabaseのAPEXを使う際に、ホワイトリストを設定できないのか、という話がありました。現時点ではそのような機能は提供されていないのですが、HTTPヘッダーを参照することで、限定的には実装することができます。なぜ限定的なのか、というとHTTPヘッダーを誤魔化すのは、それほど難しい作業ではないからです。

とはいえ、何もしないよりはよいかもしれません。古くからのオラクル・ユーザーであれば、OWA_UTILパッケージを知っている人が多いのですが、Oracle APEXでもそれが使えるということはあまり知られていないようです。ですので、OWA_UTILパッケージのプロシージャなどを使って、HTTPヘッダーを使った認証を組み込んでみます。

OWA_UTILパッケージのマニュアルの記載はこちらになります。

まず、Oracle APEXのアプリケーションで参照できるHTTPヘッダーを確認します。

空のページを作成して、それに新規にリージョンを追加します。リージョンのタイプPL/SQL動的コンテンツとします。

ソースPL/SQLコードとして以下を指定します。

owa_util.print_cgi_env;
このリージョンを含むページを開くと、Oracle APEXのアプリケーションで扱うことができるHTTPヘッダーが出力されます。


エンドポイントの特定に使用できる情報は、X-Real-IP、X-Forwarded-ForといったHTTPヘッダーやREMOTE_ADDRのどれかになるでしょう。これらの情報はOracle APEXに限った話ではないので、それぞれどういった情報であるのかといった説明は割愛します。今回はX-Real-IPを認証の制御に使用することにします。

次に、認証スキームにコードを追加します。共有コンポーネントから認証スキームを開きます。


カレントの認証スキームを開きます。くれぐれも本番稼働中のアプリケーションで作業をしないよう気を付けましょう。


PL/SQLコードとして、認証に使用するコードを追加します。そして、そこで定義したファンクション名をセッション無効ファンクション名の確認として指定します。


ファンクションの記述は以下になります。
function check_x_real_ip_header return boolean
is
l_client_ip_addr varchar2(200);
l_c integer;
begin
    l_client_ip_addr := owa_util.get_cgi_env('X-Real-IP');
    apex_debug.info('X-Real-IP is ' || l_client_ip_addr);
    select count(*) into l_c from res_client_ip where ip_address = l_client_ip_addr;
    if l_c > 0 then
        return true;
    end if;
    return false;
end check_x_real_ip_header;
あらかじめ、以下のDDLにて表RES_CLIENT_IPが作成されていて、列IP_ADDRESSにアクセスを許可するIPアドレスが記載されていることを前提としています。
CREATE TABLE "RES_CLIENT_IP" 
   (	"IP_ADDRESS" VARCHAR2(16), 
	 PRIMARY KEY ("IP_ADDRESS")
  USING INDEX  ENABLE
   ) ;
ファンクションがfalseを返す、つまりセッションが無効であると判断すると、移動先として設定されたページに遷移します。X-Real-IPとして渡されるIPアドレスが、あらかじめ表RES_CLIENT_IPに登録されていないと、ログイン画面から先に進めません。

実用的にするには、IPアドレスだけではなくワイルド・カードによる指定や、アクセスの許可、拒否にしたがってログを取得するなど、色々と考慮する必要はあります。今までの説明を元に、必要な機能を追加してゆくことになるかと思います。

2020年8月11日火曜日

Oracle APEXでJSONを使う

 Oracle APEXでアプリケーションを作成するには、必ずではないですが、データベースに表がある、ということを前提としています。Oracle APEXを開発している部門を統括しているSenior Vice PresidentのMike Hichwaのツイートにあるように、

With a strong data model the application almost write itself.

であり、Oracle APEXは単にUIを作るためのツールというより、データモデル(スキーマ定義といってもよい)からUIを自動的に生成するツールとして作られています。

とはいえ、データモデルを作る、または、スキーマを定義する、というのは大変な作業であり、さらに言うと、現在あるすべての要件を盛り込むことや、将来発生しうる要件を考慮すること、そういったことができるのかどうかもわかりません。

Oracle DatabaseはJSON形式のドキュメントを列に保存することができます。スキーマの定義を厳密に行えないケースに対応するために、JSONを使うことができます。これから、Oracle APEXでJSONを扱う方法について紹介します。

Oracle DatabaseでJSONを扱う方法を、OracleのBeda HammerschmidtがLIve SQLYouTubeで紹介しています。タイトルはUsing JSON for FlexfieldsまたはUsing JSON to Implement Flexfieldsです。ここで使用されているEMP表の定義を少々簡単にして、Oracle APEXによるユーザー・インターフェースを開発します。

クイックSQLの以下のモデルから表FF_EMPを作成します。

# prefix: ff
emp
    empno    num /pk
    ename    vc50
    job      vc50
    hiredate
    sal      num
    flex     json
JSON形式のドキュメントを保存する列は、flexとして定義されています。

SQLの生成SQLスクリプトを保存レビューおよび実行を順次クリックします。


スクリプト・エディタが開きます。

列FLEXの定義をCLOBからBLOBに変更します。また、Autonomous Databaseであればformat osonの指定を付加します。

    flex                           blob check (flex is json format oson)

JSONのデータはCLOBとしても保存可能ですが、日本語を含むデータをCLOBで保存すると内部的にUTF-16のエンコーディングに変換されるため効率が良くありません。

このスクリプトを実行すると、表FF_EMPが作成されます。


作成された表FF_EMPを元に、アプリケーションを作成します。

アプリケーションの作成を実行します。確認画面が開くので、そこでもアプリケーションの作成をクリックします。


アプリケーション作成ウィザードが起動します。

アプリケーションの名前JSON flexfieldの実装とします。フォーム付きの対話モード・レポートのページだけを使用するので、ホーム・ページは削除します。

以上でアプリケーションの作成を実行します。


これで元になるアプリケーションが作成されました。


アプリケーションを実行し、JSONを保存する列FLEXを確認します。

対話モード・レポートのページが開きます。データは未入力であるため、一行もありません。作成をクリックします。


表FF_EMPにデータを入力するフォームが開きます。列FLEXのデータ型はBLOBであるため、ファイル・セレクタがUIになっています。ファイルとしてJSONのデータが存在している場合は、そのファイルを選択すると、列FLEXへJSONデータが保存されます。


Live SQLで紹介されているように、列FLEXとして

{"shoeSize":12, "skills":["oracle", "c", "java"]}

を登録することにします。つまり、数値フィールドであるshoeSizeと、複数の値を持つskillsをフォーム画面から与え、列FLEXにJSON形式で保存します。そのデータを呼び出すときはJSON形式のデータから、shoeSizeとskillsを取り出すことになります。

ページ・デザイナでページ番号のフォームのページを開きます。

列FLEXに対応するページ・アイテムP2_FLEXを、ビルド・オプションコメント・アウトします。


ページ・アイテムP2_FLEXの代わりに、shoeSizeに対応するページ・アイテムを追加します。

名前P2_SHOESIZEとします。タイプ数値フィールドです。ラベル靴のサイズソース使用セッション・ステートの値がNULLの場合のみを設定し、セッション・ステートストレージリクエストごと(メモリーのみ)を設定します。


次に、skillsに対応するページ・アイテムを追加します。名前P2_SKILLSとします。タイプはテキスト・フィールドです。ラベルスキル(複数)、それ以外はP2_SHOESIZEと同じにします。


上記を保存し、アプリケーションを実行して修正したフォームを開くと、ファイル・セレクタの代わりに靴のサイズスキル(複数)の2つのフィールドが追加されていることを確認できます。


ページ・デザイナに戻り、列FLEXからP2_SHOESIZE、P2_SKILLSを取り出すプロセス、および、P2_SHOESIZE、P2_SKILLSを列FLEXへ保存するプロセスを作成します。

従業員番号を引数として、靴のサイズとスキルを取り出すプロシージャread_from_jsonを作成します。


プロセスを作成し、レンダリング前ヘッダーの前にあるプロセス初期化フォームFf Empの直下に配置します。

識別名前JSON読み取りタイプAPIの呼出しを選択します。設定タイプとしてPL/SQL Procedure or Functionを選択し、作成済みのプロシージャREAD_FROM_JSONが呼び出されるようにします。サーバー側の条件としてタイプアイテムはNULLではないを選択し、アイテムとしてP2_EMPNOを指定します。


パラメータp_empnop_shoesizep_skillsにはそれぞれページ・アイテムP2_EMPNOP2_SHOESIZEP_SKILLSがデフォルトで割り当てられます。


JSONから靴のサイズとスキルを読み取るプロセスを作成しました。次にそれらをJSON形式にし、書き込むプロセスを作成します。

従業員番号を引数として、靴のサイズとスキルをJSONに変換して書き込むプロシージャwrite_to_jsonを作成します。


プロセス・ビューを開きます。プロセスを作成し、プロセスプロセス・フォームEf Empの直下に配置します。

識別名前JSON書き込みタイプAPIの呼出しを選択します。設定タイプとしてPL/SQL Procedure or Functionを選択し、作成済みのプロシージャWRITE_TO_JSONが呼び出されるように設定します。サーバー側の条件としてタイプリクエストは値に含まれるを選択し、としてCREATE,SAVEを指定します。


両方のプロシージャで、Oracle Databaseが提供しているJSONを扱う機能を使用しています。

取り出しと書き込みのプロセスが登録されたので、実際にデータの入力、編集を行います。フォームを開いて、靴のサイズ(ここでは12)、スキル(ここではoracle c java)を登録して確認します。


作成をクリックしフォームを閉じた後、再度フォームを開いて設定した値を確認します。

最後の対話モード・レポートのSQLに靴のサイズとスキルを表示するよう、変更を加えます。対話モード・レポートのページを開き、ソースSQL問合せを以下に変更します。
select EMPNO,
       ENAME,
       JOB,
       HIREDATE,
       SAL,
       e.flex.shoeSize "SHOESIZE",
       e.flex.skills "SKILLS"
  from FF_EMP e


対話モード・レポートの表示は以下のようになります。


Oracle APEXでJSON形式のドキュメントを扱う方法の紹介は以上になります。

データの活用を考えたとき、スキーマとして定義できるに越したことはありませんが、そうも行かない場合は多々あるかと思います。そのような場合、JSONが扱えるのはアプリケーションを開発する側に色々なオプションを与えてくれるでしょう。

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

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

2020年8月6日木曜日

ユニバーサル・テーマのコンテント・モディファイアを使う

Oracle APEXのユニバーサル・テーマに含まれるコンテント・モディファイアについて紹介します。

コンテント・モディファイアは以下に説明があります。

コンテント・モディファイアは、主にページ・アイテムに対して適用します。プロパティの詳細に含まれるCSSクラスです。
指定可能なコンテント・モディファイアについて、効果を確認します。

実際の効果を確認するためにアプリケーションを作成しています。

テキストの配置に関する指定は以下になります。
  • u-textStart: 左揃え
  • u-textCenter: 中央揃え
  • u-textEnd: 右揃え
テキストの変換に関する指定は以下になります。
  • u-textUpper: 英字を大文字にする
  • u-textLower: 英字を小文字にする
  • u-textInitCap: 英単語の先頭文字だけを大文字にする
テキストのスタイルに関する指定は以下になります。
  • u-bold: 太字
  • u-italics: 斜体
  • u-underline: 下線付き
  • u-fixedFont: 固定幅フォント
これ以外に、アクセシビリティに対応するために、u-VisuallyHiddenというモディファイアがあります。以前のブログ記事に利用例があります。


といったハートマークが入ったロゴですが、ソースは以下になります。
<span class="footer-apex">Built with 
  <span class="fa fa-heart">
    <span class="u-VisuallyHidden">love</span>
  </span> 
  using <a href="https://apex.oracle.com/" target="_blank" title="Oracle Application Express">Oracle APEX</a>
</span>
最新のOracle APEXでは、スイッチひとつでアプリケーションの画面に追加することができるようになっています。

ここで、以下の定義はu-VisuallyHiddenが指定されているため、画面には表示されません。
<span class="u-VisuallyHidden">love</span>
画面には表示されませんが、スクリーン・リーダーの対象になります。結果として、上記のロゴは以下のように読み上げられます。

Built with love using Oracle APEX