2025年5月20日火曜日

対話グリッドの新規行を任意の処理で初期化する

対話グリッドで行の追加を実行する際に、ブラウザ上のJavaScriptで計算した値を列の初期値として設定します。対話グリッドののプロパティとしてデフォルトがありますが、この値はサーバー側で設定するため、データベースに保存されている値か、それを元にした値に限定されます。

今回はサンプル・データセットのEMP/DEPTに含まれる表EMPをデータ・ソースとした対話グリッドを作成し、対話グリッド上で選択した従業員の給与の最大値を、新規行の給与として設定します。

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


以下より実装について紹介します。

空のAPEXアプリケーションを作成し、ホーム・ページに対話グリッドのリージョンを作成します。

ソース表名EMPを指定し、ROWIDを含めるオンにします。表EMPの主キー列はEMPNOですが、対話グリッドでは主キーは自動採番されることを想定しているため、主キー列として列EMPNOは選択できません。


ROWIDを含めるオンにすることにより、主キー列としてROWIDが対話グリッドに追加されます。

EMPNOを選択し、ソース問合せのみ主キーの両方をオフにします。また、列EMPNOは実際には主キーなので、検証必須の値オンにします。


対話グリッドで行の追加をできるようにするため、対話グリッドの属性を開き、編集有効オンにします。


選択した行の主キーの値を保持するページ・アイテムとしてP1_SELECTIONを作成します。

属性タイプ非表示が適切ですが、今回はデバッグしやすいようにタイプをテキスト・フィールドにしています。


対話グリッド上で選択した行の主キー値がページ・アイテムP1_SELECTIONに設定されるように、初期化JavaScriptファンクションに以下を記述し、selectionStateItemとしてP1_SELECTIONを割り当てます。
function( config ) {
    config.defaultGridViewOptions = {
        selectionStateItem: "P1_SELECTION"
    };
    return config;
}

以上で対話グリッドで選択した行のROWIDが、: (コロン)区切りでページ・アイテムP1_SELECTIONに設定されます。


最後に対話グリッドの動的アクションを作成します。

タイミングイベントとして行の初期化[対話グリッド]を選択します。


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

/*
* https://docs.oracle.com/en/database/oracle/apex/24.2/aexjs/model.html
*/
const model = this.data.model;
const newRecord = this.data.record;
/*
* 選択されている従業員で一番高い給与を見つける。
* https://docs.oracle.com/en/database/oracle/apex/24.2/aexjs/model.html#getValue
*/
const selectedRowIds = apex.item("P1_SELECTION").getValue();
apex.debug.info("selectedRowIds", selectedRowIds);
let maxSalary = null;
selectedRowIds.split(":").forEach( (recId) => {
const rec = model.getRecord(recId);
let sal = model.getValue(rec, "SAL");
maxSalary = (maxSalary === null) ? sal : Math.max(maxSalary, sal);
});
apex.debug.info("max salary of selected employees %s", maxSalary);
/*
* 新しい行の給与に設定する。
* https://docs.oracle.com/en/database/oracle/apex/24.2/aexjs/model.html#setValue
*/
model.setValue(newRecord, "SAL", maxSalary);

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

対話グリッドで行の追加をクリックすると、デフォルトではすべての列が空白になります。サーバー側でデフォルト値を設定できますが、クライアント側のJavaScriptのコーディングにより初期値を設定できると、さらに新規行の入力の手間が減るでしょう。

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

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/set-initial-value-for-new-row-on-interactive-grid.zip

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