2023年6月12日月曜日

選択リストを無効化すると値が送信されない件について

 ページ・アイテムのタイプが選択リストで、そのページ・アイテムを無効化すると、ページ・アイテムの値が送信されません。それがフォームの更新であれば、対応した列の値が空白になります。

以下に例を示します。

サンプル・データセットEMP/DEPTに含まれる表EMPを使用して、検証に使用するアプリケーションを作成します。

アプリケーション作成ウィザードを起動します。ホーム・ページを削除し、代わりに表EMPをデータ・ソースとした対話モード・レポートとフォームのページを追加します。


対話モード・レポートとフォームのページの追加では、以下を指定します。

ページ名EMP表またはビュー対話モード・レポートを選択し、表またはビューとしてEMPを選択します。フォームを含めるチェックします。


アプリケーションを作成します。

アプリケーションが作成されたら、フォームのページに選択リストの無効化を実装します。

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


JOBがPRESIDENTのときは、ページ・アイテムP2_DEPTNOを無効化、つまり所属部門の変更を禁止します。

ページ・アイテムP2_JOB動的アクションを作成します。

識別名前ジョブの変更タイミングイベント変更選択タイプアイテムアイテムP2_JOBになります。

クライアント側の条件タイプアイテム = 値を選択し、アイテムとしてP2_JOBとしてPRESIDENTを指定します。これでJOBがPRESIDENTのときだけ、TRUEアクションが実行されます。


TRUEアクションとして無効化を選択します。影響を受ける要素選択タイプとしてアイテムを選び、アイテムとしてP2_DEPTNOを選びます。

実行初期化時に実行チェックを入れ、フォームが開くときにTRUEアクションが実行されるようにします。

クライアント側の条件タイプアイテム = 値を選択し、アイテムとしてP2_JOBとしてPRESIDENTを指定します。動的アクションとしてはP2_JOBがPRESIDENTのときのみ実行されます。しかし、初期化時に呼び出されるときはP2_JOBがPRESIDENTとは限らないため、クライアント側の条件が必要です。


JOBとしてPRESIDENT以外に変更されたときに、選択リストを有効に戻すアクションを作成します。無効化反対のアクションの作成を実行します。

Falseアクションとして有効化影響を受ける要素選択タイプアイテムアイテムP2_DEPTNOになります。実行初期化時に実行オフです。


ページを実行し、問題の事象を確認します。

アプリケーションを実行し、JOBがPRESIDENTである従業員KINGを編集します。

Departmentがグレー・アウトされ変更不可になっていることが確認できます。

値の変更をせずに、変更の適用をクリックします。


レポートの表示に戻ります。従業員KINGの列Departmentが空白になっていることがわかります。


テキスト・フィールド(HTMLのinput要素)といったページ・アイテムであればreadonly属性の指定が可能で、これで変更を禁止した上で値を送信することができます。しかし、選択リストであるselect要素にはreadonly属性が無いため、同様の設定ができません。

ワークアラウンドとして、無効化した選択リストの代わりとなるページ・アイテムP2_DEPTNO_HIDDENを作成します。

タイプ非表示とします。動的アクションによって値を設定するため、設定保護された値オフにします。セッション・ステートストレージリクエストごと(メモリーのみ)を選択します。


P2_DEPTNOが無効化されるときに、ページ・アイテムP2_DEPTNOの値をP2_DEPTNO_HIDDENにコピーするTRUEアクションを作成します。

クライアントの条件実行初期化時に実行は、無効化と同じ設定にします。

TRUEアクションとして値の設定を選択し、設定タイプの設定JavaScript Expressionを選択します。JavaScript式として以下を記述します。

apex.items.P2_DEPTNO.getValue()

影響を受ける要素選択タイプとしてアイテムアイテムとしてP2_DEPTNO_HIDDENを選択します。


これでP2_DEPTNOが無効化されるときは、その値がP2_DEPTNO_HIDDENにコピーされます。

JOBとしてPRESIDENT以外に変更されたときに、P2_DEPTNO_HIDDENのクリアするFalseアクションを作成します。クリアは値の設定の反対のアクションではないため、Falseのノードでアクションの作成を実行します。

Falseアクションとしてクリアを選択します。影響を受ける要素選択タイプとしてアイテムアイテムとしてP2_DEPTNO_HIDDENを選びます。


以上で動的アクションの設定は完了です。

サーバー側で、ページ・アイテムP2_DEPTNO_HIDDENをP2_DEPTNOに設定し直すプロセスを作成します。

プロセスを作成し、プロセス・フォームEmployeeより上に配置します。

名前部門の更新タイプとしてコードを実行を選択します。

ソースPL/SQLコードとして以下を記述します。列DEPTNOの更新にはページ・アイテムP2_DEPTNOが使われるため、P2_DEPTNOの値をP2_DEPTNO_HIDDENの値で置き換えます。

:P2_DEPTNO := :P2_DEPTNO_HIDDEN;

置き換えを行う条件として、サーバー側の条件タイプとしてを選択し、PL/SQL式として以下を記述します。JOBがPRESIDENT、ページ・アイテムP2_DEPTNOが送信されていなくて、かつ、P2_DEPTNO_HIDDENに値が設定されている場合にのみ、P2_DEPTNO_HIDDENの値を更新に使用します。

:P2_DEPTNO is null and :P2_DEPTNO_HIDDEN is not null and :P2_JOB = 'PRESIDENT'


以上で対応は完了です。

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

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