ヘッダーをスキップ
Oracle Application Development Framework Forms/4GL開発者のための開発者ガイド
10g(10.1.3.0)
B40013-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

13 基本的なページの作成

この章では、ADF Facesコンポーネントを使用した、データ・コントロール・パレットでのデータ・バインド・フォームの作成方法を説明します。

この章の内容は次のとおりです。

13.1 基本的なページの作成の概要

ビジネス・サービス用に作成されたデータ・コントロールを使用して情報の表示および収集を行うための、UIウィジェットを作成できます。たとえば、データ・コントロール・パレットを使用して、項目の属性をドラッグし、読取り専用テキストまたはラベル付き入力テキスト・フィールドとして、値を表示できます。

JDeveloperでは、属性を個別にドロップする必要はなく、オブジェクトのすべての属性をフォームとして一度にドロップできます。フォームを構成する実際のUIコンポーネントは、ドロップしたフォームのタイプによって異なります。値を表示するフォーム、ユーザーが値を編集できるフォーム、値を収集するフォーム(入力フォーム)および検索フォームを作成できます。

UIコンポーネントをドロップしたら、ユーザーがデータを操作できるようにするための組込み操作を、コマンドUIコンポーネントとしてドロップできます。たとえば、フォームに表示されたデータ・オブジェクト間をユーザーが移動できるようにするためのボタンを作成できます。また、必要に応じてデフォルトのコンポーネントを変更することもできます。

この章の内容は次のとおりです。

13.2 属性を使用したテキスト・フィールドの作成方法

テキスト・フィールドを作成するには、属性バインディングを使用して、ADF FacesテキストUIコンポーネントをデータ・コントロールの属性にバインドします。JDeveloperでは、この処理をコードを記述せずに宣言的に行うことができます。また、JDeveloperには、JSFページ用の完全なWYSIWYG開発環境が用意されているため、ページのほとんどの内容をコードを見ずに設計することができます。

13.2.1 データ・コントロール・パレットを使用したテキスト・フィールドの作成方法

属性の表示または更新を行えるテキスト・フィールドを作成するには、データ・コントロールを使用して、UIコンポーネントを属性にバインドする必要があります。JDeveloperでは、データ・コントロール・パレットからコレクションの属性をドラッグ・アンド・ドロップして、この処理を宣言的に行えます。

バインドされたテキスト・フィールドの作成手順:

  1. データ・コントロール・パレットからコレクションの属性を選択します(属性およびデータ・コントロール・パレットのその他のオブジェクトを表すアイコンの説明は、12.2.1項「データ・コントロール・パレットの各項目の理解」を参照してください)。

    たとえば、図13-1は、SRDemoアプリケーションのSRServiceデータ・コントロールの、ServiceRequestsコレクションの下にあるProblemDescription属性を示しています。この属性は、サービス・リクエストに対する問題の説明を表示または入力する場合にドロップします。

    図13-1 コレクションに関連付けられた属性のデータ・コントロール・パレットでの表示

    コレクションの下にあるサービス・リクエストの属性
  2. ページに属性をドラッグし、ポップアップ・メニューから、属性値を表示または収集するウィジェットのタイプを選択します。各属性について、次の選択肢があります。

    • テキスト

      • ラベル付ADF出力テキスト: ADF Faces outputTextコンポーネントを保持するpanelLabelAndMessageコンポーネントを作成します。panelLabelAndMessageコンポーネントのlabel属性に値が移入されます。

      • ADF出力テキスト: ADF Faces outputTextコンポーネントを作成します。ラベルは作成されません。

      • ラベル付ADF入力テキスト: validatorを伴うADF Faces inputTextコンポーネントが作成されます。label属性に値が移入されます。


        ヒント:

        検証の詳細は、第20章「検証と変換の使用」を参照してください。

      • ADF入力テキスト: validatorを伴うADF Faces inputTextコンポーネントが作成されます。label属性に値は移入されません。

      • ADFラベル: ADF Faces outputLabelコンポーネント。

    • 単一選択

      これらのウィジェットによって、リストが表示されます。この章の目的にあわせて、ここではテキスト・ウィジェットのみについて説明します。リストおよびそのバインディングの詳細は、19.7項「選択リストの作成」を参照してください。

13.2.2 データ・コントロール・パレットを使用してテキスト・フィールドを作成した場合の処理

JSFページに属性をドラッグしてUIコンポーネントとしてドロップすると、ページのディレクトリ名を含むJSFページの名前を使用し、ページ定義ファイルの名前としてJSFページの名前にPageDefを追加して、そのページのページ定義ファイル(すでに存在する場合を除く)などが作成されます。たとえば、Webルートの./app/staffサブディレクトリのSREditページのページ定義ファイルは、app_staff_SREditPageDef.xmlです。属性をページにドラッグしたときに行われる処理の詳細は、12.2.3項「データ・コントロール・パレットの使用時に行われる処理」を参照してください。イテレータと属性のバインディングが作成され、ページ定義ファイルに追加されます。また、UIコンポーネントに必要なJSPXページのコードがJSFページに追加されます。

13.2.2.1 イテレータ・バインディングの作成および使用

データ・コントロール・パレットからコレクションの一部である項目をドロップして(またはコレクション全体をフォームまたは表としてドロップして)ページ上にUIコンポーネントを作成するたびに、既存のバインディングが存在しない場合はJDeveloperでイテレータ・バインディングが作成されます。イテレータ・バインディングは、データ・コレクションのイテレータを参照し、この機能によりそのデータ・オブジェクトを反復処理します。また、コレクション内のデータ・オブジェクトの現在行および状態を管理します。イテレータ・バインディングは実際にはデータにアクセスしません。かわりに、データにアクセスできるオブジェクトを単純に公開し、コレクション内の現在のデータ・オブジェクトを指定します。その後、現在のオブジェクトのデータを戻したり、オブジェクトのデータに対してアクションを実行するために、他のバインディングがこのイテレータ・バインディングを参照します。イテレータ・バインディングはイテレータではなく、イテレータへのバインディングであることに注意してください。ADF Business Componentsの場合、実際のイテレータは、アプリケーション・モジュールのデータ・モデル内のビュー・オブジェクト・インスタンスのデフォルト行セットに対するデフォルト行セット・イテレータです。


ヒント:

各コレクションに対して1つのイテレータ・バインディングが作成されます。つまり、同じコレクションから2つの属性をドロップした場合(もしくは同じコレクションを2回ドロップした場合)は、同じバインディングが使用されます。コンポーネントごとに動作の異なるバインディングが必要な場合を除き、同じバインディングが使用されても問題はありません。その場合は、別個のイテレータ・バインディングを手動で作成する必要があります。手順と例は、18.5項「検索ページの結果表の条件付き表示」を参照してください。

たとえば、ServiceRequestsコレクションの下にProblemDescription属性をドロップした場合、ServiceRequestsコレクションのイテレータ・バインディングが自動的に作成されます。

イテレータ・バインディングのrangeSize属性は、イテレータ・バインディングへのアクセスが行われるたびにページに対して使用可能なレコードの数を決定します。この属性により、行セット全体の中でいくつかの絶対開始位置に対して1-N行の相対セットが置かれます。デフォルトでは10に設定されています。この属性の使用方法は、13.4.2.2項「イテレータのRangeSize属性」を参照してください。例13-1に、ServiceRequestsコレクションから属性をドロップすると作成されるイテレータ・バインディングを示します。

例13-1 コレクションから属性をドロップした場合のイテレータ・バインディングのページ定義コード

<executables>
  <iterator id="ServiceRequestsIterator" RangeSize="10"
            Binds="ServiceRequests" DataControl="SRService"/>
</executables>

イテレータ・バインディング要素の属性に関する詳細は、A.2.2項「Oracle ADFデータ・バインディング・ファイル」を参照してください。

このメタデータにより、ADFバインディング・コンテナは属性にアクセスできます。イテレータ・バインディングは実行可能ファイルで、ページのロード時に起動されるため、これによってイテレータがServiceRequestsコレクションにアクセスし、反復処理を行うことができます。これは、コレクションのサービス・リクエストがすべてこのイテレータによって管理されることを意味します。現在のサービス・リクエストやサービス・リクエストのレンジの判別も含まれます。

13.2.2.2 値バインディングの作成および使用

データ・コントロール・パレットから属性をドロップすると、JDeveloperによって、UIコンポーネントを属性の値にバインドするための属性バインディングが作成されます。このタイプのバインディングは、コレクション内の現在行のシングル・オブジェクトに対する属性の値を提示します。値バインディングは、属性値の表示と収集の両方に使用できます。

たとえば、ServiceRequestsコレクションの下にあるProblemDescription属性を「ラベル付ADF出力テキスト」ウィジェットとしてページにドロップすると、JDeveloperによって、ProblemDescription属性の属性バインディングが作成されます。これにより、バインディングが現在のレコードの属性値にアクセスできるようになります。例13-2に、ServiceRequestsコレクションから属性をドロップすると作成されるProblemDescriptionに対する属性バインディングを示します。この属性値は、ServiceRequestsIteratorという名前のイテレータを参照します。

例13-2 属性バインディングのページ定義コード

 <bindings>
    ...
    <attributeValues id="ServiceRequestsProblemDescription"
                     IterBinding="ServiceRequestsIterator">
      <AttrNames>
        <Item Value="ProblemDescription"/>
      </AttrNames>
    </attributeValues>
  </bindings>

属性バインディング要素の属性に関する詳細は、A.2.2項「Oracle ADFデータ・バインディング・ファイル」を参照してください。

13.2.2.3 EL式を使用したUIコンポーネントのバインド

データ・コントロール・パレットから属性をドロップしてテキスト・フィールドを作成すると、JDeveloperによって、対応するコードがJSFページに記述され、ドロップしたウィジェットに関連付けられているUIコンポーネントが作成されます。

たとえば、ProblemDescription属性を「ラベル付き出力テキスト」ウィジェットとしてドロップすると、JDeveloperによって、panelLabelAndMessage labelの属性をProblemDescriptionバインディングのlabelプロパティにバインドするEL式が作成されます。また、panelLabelAndMessage値属性をProblemDescriptionバインディングのinputValueプロパティ(ProblemDescription属性の値)にバインドする、別の式が作成されます。バインディング・オブジェクト・プロパティに関する詳細は、A.2.2項「Oracle ADFデータ・バインディング・ファイル」を参照してください。

例13-3は、ProblemDescription属性を「ラベル付き出力テキスト」ウィジェットとしてドロップしたときに、JSFページで生成されるコードを示しています。

例13-3 「ラベル付き出力テキスト」としてドロップされた属性のJSFページ・コード

<af:panelLabelAndMessage
         label="#{bindings.ServiceRequestsProblemDescription.label}">
    <af:outputText
         value="#{bindings.ServiceRequestsProblemDescription.inputValue}"/>
</af:panelLabelAndMessage>

かわりにProblemDescription属性をラベル付き入力テキスト・ウィジェットとしてドロップすると、JDeveloperによってinputTextコンポーネントが作成されます。例13-4で示すように、出力テキスト・コンポーネントと同様に、値はProblemDescriptionバインディングのinputValueプロパティにバインドされます。また、次のプロパティも設定されます。

  • label: バインディングのlabelプロパティにバインドされます。

  • required: バインディングのmandatoryプロパティにバインドされます。このプロパティの詳細は、20.3項「検証の追加」を参照してください。

  • columns: displayWidthプロパティにバインドされます。テキスト・ボックスの幅を決定します。

例13-4 ラベル付き入力テキストとしてドロップされた属性のJSFページ・コード

<af:inputText value="#{bindings.ServiceRequestsProblemDescription.inputValue}"
            label="#{bindings.ServiceRequestsProblemDescription.label}"
            required="#{bindings.ServiceRequestsProblemDescription.mandatory}"
          columns="#{bindings.ServiceRequestsProblemDescription.displayWidth}">
  <af:validator binding="#{bindings.ServiceRequestsProblemDescription.validator}"/>
</af:inputText>

プロパティの詳細は、付録B「ADFバインディング・プロパティのリファレンス」を参照してください。

13.2.3 実行時に行われる処理: JSFおよびADFのライフサイクル

ページが送信され、新しいページがリクエストされると、アプリケーションによってJSFライフサイクルとADFライフサイクルの両方が起動されます。JSFライフサイクルは、ビュー・レイヤーでコンポーネントを処理しますが、ADFライフサイクルは、モデル・レイヤーでデータを処理します。

特に、JSFファイルサイクルは、ページ上での値の送信、作成されるページでのコンポーネントの検証、ナビゲーションおよびコンポーネントの表示、そして保存およびリストアの状態を処理します。JSFライフサイクルのフェーズでは、UIコンポーネント・ツリーを使用して、Facesコンポーネントの表示が管理されます。このツリーは、JSFページの実行時の表現であり、ページ内のUIコンポーネントのタグは、それぞれツリー内の1つのUIコンポーネント・インスタンスに対応します。FacesServletオブジェクトは、JSFアプリケーションでのリクエスト処理のライフサイクルを管理します。FacesServletは、FacesContextというオブジェクトを作成します。このオブジェクトには、リクエスト処理およびライフサイクルを実行するオブジェクトの起動に必要な情報が含まれます。

ADFライフサイクルは、データ・モデルの準備と更新、モデル・レイヤーでのデータの検証、およびビジネス・レイヤーでのメソッドの実行を処理します。ADFライフサイクルは、バインディング・コンテナを使用して、現在ページのリクエスト時にページによる簡単なデータ参照を可能にします。

ライフサイクルは複数のフェーズに分かれます。2つのライフサイクルが連携して動作するように、JSFイベント・リスナーのメカニズムを使用して、ADFライフサイクルのフェーズがJSFライフサイクルのフェーズに統合されます。ADFライフサイクルは、ADFフェーズ・リスナーを使用して、フェーズのイベントをリスニングします。これにより、適切なJSFフェーズの前または後に、適切なADFフェーズが実行されます。

ADFデータ・コントロールにバインドされたADF Facesコンポーネントが最初にJSFページに挿入された際には、JDeveloperによって、ADF PhaseListenerがfaces-config.xmlに追加されます。例13-5は、faces-config.xmlでのADF PhaseListenerの構成を示しています。

例13-5 faces-config.xmlでのADF PhaseListenerの登録

<faces-config xmlns="http://java.sun.com/JSF/Configuration">
  ...
<lifecycle>
  <phase-listener>
    oracle.adf.controller.faces.lifecycle.ADFPhaseListener
  </phase-listener>
</lifecycle>
  ...
</faces-config>

図13-2は、JSFおよびADFのフェーズがライフサイクルの中でどのように統合されるかを示しています。

図13-2 ADF Facesコンポーネントを使用したADFアプリケーションのページ・リクエストのライフサイクル

ADFおよびJSFのフェーズの連携

ADFモデル・レイヤーを使用するJSFアプリケーションでは、ライフサイクルは次のようになります。

  • ビューのリストア: リクエストされたページのURLがbindingContextに渡され、URLと一致するページ定義が検索されます。リクエストされたページのコンポーネント・ツリーが、新しく作成されるかリストアされます。送信されたページ上のすべてのコンポーネント・タグ、イベント・ハンドラ、コンバータおよびバリデータは、FacesContextインスタンスにアクセスできます。ツリーが新しく、空の場合(つまり、送信されたページからのデータがない)は、ライフサイクルは直接レスポンスのレンダリング・フェーズに進みます。それ以外の場合は、ビューのリストア・フェーズによって、ADFモデル・レイヤーのコンテキストの初期化フェーズがリスニングするイベントが発行され、実行されます。

    たとえば、ページに含まれているinputText UIコンポーネントがServiceRequest戻りコレクションのProblemDescription属性にバインドされている場合、URLが渡されると、そのページ定義が公開されます。その後、UIコンポーネントが作成されます。データが表示される場合は、コンテキストの初期化フェーズが実行されます。表示されない場合は、ライフサイクルがレスポンスのレンダリング・フェーズに進みます。

  • コンテキストの初期化: ページ定義ファイルを使用してbindingContainerオブジェクトが作成されます。このオブジェクトは、リクエストされたページのページ定義の実行時表現です。ADFライフサイクルの全フェーズの情報を保存するために使用されるLifecycleContextクラスがインスタンス化され、初期化されます。

  • モデルの準備: バインディング・コンテナがリフレッシュされ、ページ定義に含まれるすべてのページ・パラメータが設定されます。Refresh属性およびRefreshCondition属性の値に基づいて、ページ定義の実行可能セクションに含まれるすべてのエントリがリフレッシュされます。

    RefreshおよびRefreshCondition属性は、実行可能セクションを起動するかどうか、またいつ起動するかを決定するために使用されます。たとえば、実行可能セクションが、ある一定の条件下でのみ起動する必要があるという場合です。リフレッシュは、実行可能セクションを起動するフェーズを決定します。一方で、リフレッシュ条件は条件が満たされているかどうかを判断します。バインディングが操作の結果に依存する場合は、Refresh属性をprepareModelに設定します。RefreshprepareModelに設定されているか、値が指定されていない(つまり、デフォルトのifneededが使用される)場合は、RefreshCondition属性値が評価されます。RefreshCondition値が存在しない場合は、実行可能セクションが起動します。RefreshConditionの値が存在する場合は、値が評価され、評価の戻り値がtrueの場合は、実行可能セクションが起動します。値がfalseと評価された場合は、実行可能セクションは起動しません。デフォルト値は常に、実行を強制します。受け取ったリクエストにPOSTデータまたは問合せパラメータが含まれていない場合、ライフサイクルはレスポンスのレンダリング・フェーズに進みます。

    詳細は、10.5.5.1項「イテレータ・バインディングのRefreshプロパティの適切な構成」を参照してください。リフレッシュ属性の詳細は、A.6.1項「PageDef.xmlの構文」を参照してください。

    問題の説明の例では、bindingContainerによって、ServiceRequestsコレクションを戻すServiceRequestsIteratorイテレータが起動されます。その後、イテレータによってデータが反復処理され、最初に検出されたレコードのデータがバインディング・コンテナに配置されて、UIコンポーネントで使用できるようになります。イテレータからの値にアクセスできるページ定義内のProblemDescription属性にバインディングが設定されているため(例13-2を参照)、また、EL式(#{bindings.problemDescription.inputValue})を使用してUIコンポーネントがProblemDescriptionバインディングにバインドされているため、そのデータがコンポーネントによって表示されます。

  • リクエスト値の適用: ツリー内の各コンポーネントにより、リクエスト・パラメータから(そのデコード・メソッドを使用して)新しい値が抽出され、ローカルに格納されます。関連付けられているほとんどのイベントは、後の処理のためにキューされます。コンポーネントのimmediate属性がtrueに設定されている場合は、コンポーネントに関連付けられている検証、変換およびイベントが、このフェーズで処理されます。検証および変換の詳細は、第20章「検証と変換の使用」を参照してください。

    たとえば、ユーザーがinputTextコンポーネントに新しい値を入力すると、その値はinputTextコンポーネントのsetSubmittedValueメソッドを使用してローカルに格納されます。

  • 処理の検証: コンポーネントのローカルの値が変換され、検証されます。エラーが発生した場合は、ライフサイクルがレスポンスのレンダリング・フェーズに進みます。このフェーズの最後に、コンポーネントの新しい値が設定され、検証または変換のエラー・メッセージおよびイベントがFacesContextでキューされて、すべての値変更イベントが配信されます。

    ライフサイクルのこのフェーズおよび後続の2つのフェーズの詳細な説明は、第20章「検証と変換の使用」を参照してください。

  • モデル値の更新: コンポーネントの検証済のローカル値がモデルに移され、ローカル・コピーが破棄されます。

  • モデル更新の検証: モデルに設定された検証ルーチンと比較して、更新されたモデルが検証されます。

  • アプリケーションの起動: コマンド・コンポーネントまたはイベントのアクション・バインディングが起動されます。ライフサイクルのこのフェーズおよび後続の2つのフェーズの詳細な説明は、16.4項「動的ナビゲーションの使用」を参照してください。ビジネス・ロジックの起動に使用されるアクション・バインディングの説明は、13.4項「フォームへのレンジ・ナビゲーションの組込み」を参照してください。

  • メタデータのコミット: 実行時メタデータへの変更がコミットされます。このフェーズは今回のリリースでは使用されていませんが、将来のリリースで使用されます。

  • コンテキストの初期化(アプリケーションの起動ライフサイクルでナビゲーションが発生した場合のみ): 次のページのページ定義が初期化されます。

  • モデルの準備(アプリケーションの起動ライフサイクルでナビゲーションが発生した場合のみ): 次のページの定義に含まれるすべてのページ・パラメータが設定されます。ページ定義の実行可能セクションに含まれるすべてのエントリを使用して、対応するメソッドが表示順に起動されます。

  • レンダリングの準備: バインディング・コンテナがリフレッシュされ、リクエスト値の適用フェーズまたは検証フェーズで発生したすべての変更が反映されます。登録されたすべてのリスナーに、prepareRenderイベントが送信されます。


    注意:

    選択する有効フェーズとして、JDeveloperではprepareRenderではなくrenderModelが表示されます。これは、バインディング・コンテナでコールされるrefresh(RENDER_MODEL)メソッドを表します。

    refreshConditionがモデルに依存する場合は、実行可能セクションのRefresh属性をrenderModelに設定する必要があります。たとえば、実行可能セクションのRefreshCondition#{adfFacesContext.postback}式を使用する場合は、RefreshプロパティをrenderModelまたはrenderModelIfNeededに設定する必要があります。これにより、メソッドがprepareRenderフェーズ中に実行されます。詳細は、10.5.5.1項「イテレータ・バインディングのRefreshプロパティの適切な構成」を参照してください。

  • レスポンスのレンダリング: J2EE Webコンテナがページ内のタグを横断するにつれて、ツリー内のコンポーネントがレンダリングされます。後続のリクエストおよびビューのリストア・フェーズ用に、状態の情報が保存されます。

13.3 基本的なフォームの作成

JDeveloperでは、属性を個別にドロップしてフォームを作成するのではなく、オブジェクトのすべての属性のデータを表示または収集する、完全なフォームをドロップできます。たとえば、SREditページは、指定されたサービス・リクエストの編集に必要なすべての属性が含まれているServiceRequestsコレクションをドロップして作成されています。

コレクションからのデータ表示よりも多くの機能を提供するフォームの作成もできます。ユーザーによるデータ更新が可能なフォームの作成については、13.5項「既存レコードを編集するフォームの作成」を参照してください。ユーザーによるコレクションに対する新規オブジェクト作成が可能なフォームの作成については、13.6項「入力フォームの作成」を参照してください。また、検索フォームも作成できます。詳細は、第18章「検索フォームの作成」を参照してください。

13.3.1 データ・コントロール・パレットを使用したフォームの作成方法

データ・コントロールを使用してフォームを作成するには、UIコンポーネントをデータ・コントロールの対応するオブジェクトの属性にバインドします。JDeveloperでは、データ・コントロール・パレットからコレクションまたは構造化された属性をドラッグ・アンド・ドロップして、この処理を宣言的に行えます。

基本的なフォームの作成手順:

  1. データ・コントロール・パレットから、表示するデータを表すコレクションを選択します。図13-3に、SRServiceデータ・コントロールのServiceRequestsコレクションを示します。

    図13-3 データを表示するフォームの作成にコレクションを使用できる

    SRServiceアプリケーション・モジュールの下のServiceRequestコレクション
  2. ページにコレクションをドラッグし、ポップアップ・メニューから、オブジェクトのデータを表示または収集するフォームのタイプを選択します。各フォームについて、次の選択肢があります。

    • ADFフォーム: 「フォーム・フィールドの編集」ダイアログが開き、デフォルトですべての属性に対して1つのフィールドを作成するのではなく、属性を個別に選択できます。また、各属性に使用するラベルおよびUIコンポーネントを選択できます。デフォルトでは、ADF inputTextコンポーネントが使用されますが、例外として、日付にはselectInputDateコンポーネントが使用されます。各inputTextコンポーネントには、属性の検証を設定するためのバリデータ・タグが含まれます。詳細は、20.3項「検証の追加」を参照してください。

      ユーザーがコレクション内の全データ・オブジェクト間を移動できるようにする、ナビゲーション・コントロールを含めることもできます。詳細は、13.4項「フォームへのレンジ・ナビゲーションの組込み」を参照してください。必要に応じて、フォームを送信するための「発行」ボタンを含めることもできます。このボタンにより、HTMLフォームを送信し、JSF/ADFページ・ライフサイクルの一環としてフォームのデータをバンディングに適用します。このダイアログの使用方法に関する追加のヘルプを表示するには、「ヘルプ」をクリックします。すべてのUIコンポーネントは、panelFormコンポーネントの中に配置されます。

    • ADF読取り専用フォーム: 「ADFフォーム」と同じですが、デフォルトではoutputTextコンポーネントが使用されます。このフォームはデータの表示を目的としているため、validatorタグは追加されません。各コンポーネントのlabel属性に値が移入されます。タイプDateの属性でも、outputTextコンポーネントが使用されます。すべてのコンポーネントはpanelLabelAndMessageコンポーネントの中に配置され、panelLabelAndMessageコンポーネントはpanelFormコンポーネントの中に配置されます。

    • ADF検索フォーム: Query-By-Example(QBE)検索の実行に使用できるフォームを作成します。詳細は、第18章「検索フォームの作成」を参照してください。

    • ADF作成フォーム: ユーザーがコレクションの新規インスタンスを作成できる入力フォームを作成します。詳細は、13.6項「入力フォームの作成」を参照してください。

  3. ユーザーがデータを更新できるようにするためのフォームを作成する場合は、ここで、更新を実行する操作をドラッグ・アンド・ドロップする必要があります。詳細は、13.5項「既存レコードを編集するフォームの作成」を参照してください。

13.3.2 データ・コントロール・パレットを使用してフォームを作成した場合の処理

データ・コントロール・パレットからオブジェクトをフォームとしてドロップすることは、単一の属性をドロップするのと同じ効果があります。ただし、複数の属性バインディングと関連するUIコンポーネントが作成される点が異なります。UIコンポーネントの属性(valueなど)は、その属性のバインディング・オブジェクト(inputValueなど)のプロパティにバインドされます。例13-6は、ServiceRequestsコレクションをデフォルトADFフォームとしてドロップした場合にJSFページで生成されるコードを示しています。

例13-6 入力フォームのJSFページのコード

<af:panelForm>
  <af:inputText value="#{bindings.SvrId.inputValue}"
                label="#{bindings.SvrId.label}"
                required="#{bindings.SvrId.mandatory}"
                columns="#{bindings.SvrId.displayWidth}">
    <af:validator binding="#{bindings.SvrId.validator}"/>
  </af:inputText>
  <af:inputText value="#{bindings.Status.inputValue}"
                label="#{bindings.Status.label}"
                required="#{bindings.Status.mandatory}"
                columns="#{bindings.Status.displayWidth}">
    <af:validator binding="#{bindings.Status.validator}"/>
  </af:inputText>
  <af:selectInputDate value="#{bindings.RequestDate.inputValue}"
                      label="#{bindings.RequestDate.label}"
                      required="#{bindings.RequestDate.mandatory}">
   <af:validator binding="#{bindings.RequestDate.validator}"/>
   <f:convertDateTime pattern="#{bindings.RequestDate.format}"/>
 </af:selectInputDate>
...
</af:panelForm>

注意:

バリデータおよびコンバータのタグの詳細は、第20章「検証と変換の使用」を参照してください。

13.3.2.1 ファセットの使用方法

JSFコンポーネントでは、ファセット・タグを使用して、親コンポーネントとの特別な関係が要求される他のコンポーネント(たとえば、表の列のヘッダーとフッター、またはpanelFormコンポーネントのfooter)が保持されます。データ・コントロール・パレットを使用してウィジェットをドロップすると、デフォルトのファセットが組み込まれます。

ファセットは多くのコンポーネントで使用されます。ウィジェットを使用して複雑なコンポーネント(panelFormなど)を作成する際には、多くの場合、出力タグが自動的に作成され、ファセットに挿入されます。これらのコンポーネントを手動で編集するか、他のコンポーネントをファセットに追加できます。

コレクションを入力フォームとしてドロップする際に「発行」ボタンを含めることを選択した場合は、コマンド・ボタンがpanelFormfooterファセットに追加されます。このコマンド・ボタンによって、panelFormを保持するフォームが送信されます。デフォルトでは、テキストは「発行」になります。図13-4は、panelFormfooterファセットのコマンド・ボタンを示しています。

図13-4 パネル・フォームのフッター・ファセット

構造ウィンドウに表示されたフッター・ファセットおよびフォーム

例13-7は、JSFページの対応するコードを示しています。

例13-7 JSFページのファセット

<af:panelForm>
...
  <f:facet name="footer">
    <af:commandButton text="Submit"/>
  </f:facet>
</af:panelForm>

各ファセットで保持できるのは1つのコンポーネントのみです。複数のコンポーネントを保持するファセットが必要な場合は、複数のコンポーネントを1つのコンテナ・コンポーネントにネストし、ファセットにネストできる状態にする必要があります。たとえば、panelGroupコンポーネントとpanelButtonBarコンポーネントは、フォームのfooterファセットにあるすべてのボタンのグループ化に使用されています。これに関する詳細は、13.4.2.3項「EL式を使用したナビゲーション操作へのバインド」を参照してください。

また、コンポーネントに使用できるすべてのファセットは、構造ウィンドウに自動的に表示されます。ただし、アクティブな状態で表示されるのは、UIコンポーネントを含むファセットのみです。空のファセットはグレー表示されます。図13-5は、panelPageコンポーネントの完全なファセットと空のファセットの両方を示しています。

図13-5 構造ウィンドウに表示された空のファセット・フォルダおよび完全なファセット・フォルダ

構造ウィンドウに表示されたPanelPageの全ファセット

13.4 フォームへのレンジ・ナビゲーションの組込み

ADFフォームを作成する際、ナビゲーションの追加オプションが提供されます。ナビゲーションの追加を選択する場合、JDeveloperによって、データ・コントロールの既存ナビゲーション・ロジックにバインドされているADF Facesコマンド・コンポーネントが組み込まれます。この組込みロジックによって、ユーザーは、コレクション内のすべてのデータ・オブジェクトを移動できるようになります。図13-6は、ナビゲーション・ボタンを含むフォームを示しています。

図13-6 フォームのナビゲーション・ボタン

検索結果の詳細ページのナビゲーション・ボタン

13.4.1 フォームへのナビゲーション・コントロールの挿入方法

デフォルトでは、データ・コントロール・パレットを使用してフォームを作成する際にナビゲーションを含めることを選択すると、JDeveloperによって、「先頭へ」「最後へ」「前へ」および「次へ」の各ボタンが作成され、ユーザーがコレクション内を移動できるようになります。

また、既存のフォームにナビゲーション・ボタンを手動で追加できます。

ナビゲーション・ボタンを手動で追加する場合の手順:

  1. 操作の実行対象となるオブジェクトのコレクションに関連付けられている操作をデータ・コントロール・パレットから選択し、JSFページ上にドラッグします。

    たとえば、サービス・リクエスト全体を移動できるようにする場合は、ServiceRequestsコレクションに関連付けられている「次へ」操作をドラッグします。図13-7は、コレクションに関連付けられている操作を示しています。

    図13-7 コレクションに関連付けられているナビゲーション操作

    データ・コントロール・パレットに表示されたナビゲーション操作
  2. ポップアップ・メニューから「コマンド・ボタン」または「コマンド・リンク」を選択します。

13.4.2 データ・コントロール・パレットでコマンド・ボタンを作成した場合の処理

任意の操作をコマンド・コンポーネントとしてドロップすると、JDeveloperによって次の処理が行われます。

  • 関連付けられている操作について、ページ定義ファイルでアクション・バインディングが定義されます。

  • コマンド・コンポーネント用のコードがJSFページに挿入されます。

13.4.2.1 組込みナビゲーション操作のアクション・バインディングの使用方法

アクション・バインディングは、ビジネス・ロジックを実行します。たとえば、アクション・バインディング・オブジェクト上で組込みメソッドを起動できます。このような組込みメソッドは、イテレータやデータ・コントロール自体に対して作用し、データ・コントロール・パレットに操作として表示されます。ユーザーは、JDeveloperによって提供されるナビゲーション操作を使用して、コレクション内の前後のオブジェクトに移動したり、最後または最初のオブジェクトに移動できます。

値バインディングのように、操作のアクション・バインディングには、NextまたはPreviousなどのイテレータレベル・アクションの1つにアクション・バインディングがバインドされる際のイテレータ・バインディングへの参照が含まれます。この参照は、現在のオブジェクトの判別に使用され、これによって、各ナビゲーション・ボタンがクリックされたときに表示するオブジェクトが正しく判別されます(たとえば、AM上のカスタム・メソッドに対して、またはコミット操作やロールバック操作に対して、イテレータレベル・アクション以外にバインドされるアクション・バインディングは、この参照には含まれません)。例13-8は、ナビゲーション操作のアクション・バインディングを示しています。


ヒント:

<action>タグのAction属性の数値(図13-7に示される)は、oracle.adf.model.meta.OperationDefinitionクラスで定義されます。ただし、ADFモデル・レイヤーのアクション・バインディング・エディタを使用する場合は、手動で数値コードを設定する必要はありません。

例13-8 操作アクション・バインディングのページ定義コード

 <action id="First" RequiresUpdateModel="true" Action="12"
            IterBinding="ServiceRequestsIterator"/>
 <action id="Previous" RequiresUpdateModel="true" Action="11"
            IterBinding="ServiceRequestsIterator"/>
 <action id="Next" RequiresUpdateModel="true" Action="10"
            IterBinding="ServiceRequestsIterator"/>
 <action id="Last" RequiresUpdateModel="true" Action="13"
            IterBinding="ServiceRequestsIterator"/>

13.4.2.2 イテレータのRangeSize属性

イテレータ・バインディングにはrangeSize属性が含まれ、各イテレータに対してページを使用可能にするデータ・オブジェクト数が決定されます。この属性は、データソース内のオブジェクト数がきわめて多い場合に役立ちます。すべてのオブジェクトではなく、1つのセット番号のみが戻され、他のバインディングによるアクセスが可能になります。イテレータはレンジの最後に到達すると、次のセットにアクセスします。例13-9は、ServiceRequestsIteratorイテレータのデフォルトのレンジ・サイズを示しています。


注意:

このrangeSize属性は、表コンポーネントのrow属性とは異なります。詳細は、表14-1「ADF Faces表の属性と移入される値」を参照してください。

例13-9 イテレータのRangeSize属性

<executables>
  <iterator id="ServiceRequestsIterator" RangeSize="10"
            Binds="ServiceRequests" DataControl="SRService"/>
</executables>

デフォルトでは、rangeSize属性は10に設定されています。つまり、ユーザーは、データソースにアクセスせずに、前後に移動しながら10個のオブジェクトを表示できます。イテレータは、現在のオブジェクトを追跡します。ユーザーが新しいレンジが要求されるボタンをクリックすると(たとえば、オブジェクト番号10で「次へ」ボタンをクリックすると)、バインディング・オブジェクトによってイテレータに対して関連するメソッドが実行され、イテレータによって別の10個のレコードのセットが取得されます。その後、取得されたセットがバインディングによって使用されます。この設定は、必要に応じて変更できます。完全なレコード・セットを戻すには、-1に設定します。リスト・バインディングの有効選択肢リストを提供するイテレータ・バインディングの場合、デフォルトは-1です。

表13-1は、データ・コントロールで提供される組込みナビゲーション操作、ページ定義で設定されるアクション属性値、および操作の起動または操作にバインドされたイベントの起動の結果を示しています。アクション・イベントの詳細は、13.4.3項「実行時の処理: アクション・イベントおよびアクション・リスナー」を参照してください。

表13-1 組込みナビゲーション操作

操作 アクション属性値 関連イテレータ・バインディングによる起動時の処理

Next

10

現在のポインタを結果セットの次のオブジェクトに移動します。このオブジェクトが現在のレンジの外にある場合は、レンジ・サイズと同じオブジェクト数だけレンジが進むようにスクロールされます。

Previous

11

現在のポインタを結果セットの前のオブジェクトに移動します。このオブジェクトが現在のレンジの外にある場合は、レンジ・サイズと同じオブジェクト数だけレンジが戻るようにスクロールされます。

First

12

現在のポインタを結果セットの最初に移動します。

Last

13

現在のポインタを結果セットの最後に移動します。

Next Set

14

レンジ・サイズ属性と同じオブジェクト数だけ、レンジを進めるように移動します。

Previous Set

15

レンジ・サイズ属性と同じオブジェクト数だけ、レンジを戻すように移動します。


操作の各アクション・バインディングには、enabledブール型プロパティが含まれます。このプロパティは、操作を起動しない場合には、ADFフレームワークによってfalseに設定されます。この値にUIコンポーネントをバインドすると、コンポーネントを有効化するかどうかを指定できます。enabledプロパティの詳細は、付録B「ADFバインディング・プロパティのリファレンス」を参照してください。

13.4.2.3 EL式を使用したナビゲーション操作へのバインド

ナビゲーション操作を使用してコマンド・コンポーネントを作成すると、作成したコンポーネントはpanelButtonBarコンポーネント内に配置されます。JDeveloperによってEL式が作成され、この式によって、ナビゲーション・コマンド・ボタンのactionListener属性が、指定された操作のアクション・バインディングのexecuteプロパティにバインドされます。ユーザーがボタンをクリックすると、この式によって、イテレータに対してバインディングの操作が起動されます。

コマンド・ボタンのactionListener属性の詳細は、13.4.3項「実行時の処理: アクション・イベントおよびアクション・リスナー」を参照してください。たとえば、Firstコマンド・ボタンのactionListener属性は、Firstアクション・バインディングのexecuteメソッドにバインドされます。

disabled属性は、ボタンを無効化するかどうかの判別に使用されます。たとえば、ユーザーが現在、最初のレコードを表示している場合は、「先頭へ」ボタンをクリックできないようにする必要があります。コードでは、アクション・バインディングのenabledプロパティに対して評価するEL式が使用されます。プロパティ値がtrueでない場合(たとえば、現在のレコードが最初のレコードで、First操作の有効化が禁止されている場合)は、ボタンが無効になります。例13-10は、ナビゲーション操作ボタンに対してJSFページで生成されたコードを示しています。

例13-10 ADF操作にバインドされているナビゲーション・ボタンのJSFコード

<f:facet name="footer">
   <af:panelButtonBar>
     <af:commandButton actionListener="#{bindings.First.execute}"
                         text="First"
                         disabled="#{!bindings.First.enabled}"/>
     <af:commandButton actionListener="#{bindings.Previous.execute}"
                       text="Previous"
                       disabled="#{!bindings.Previous.enabled}"/>
     <af:commandButton actionListener="#{bindings.Next.execute}"
                       text="Next"
                       disabled="#{!bindings.Next.enabled}"/>
     <af:commandButton actionListener="#{bindings.Last.execute}"
                       text="Last"
                       disabled="#{!bindings.Last.enabled}"/>
   </af:panelButtonBar>
   <af:commandButton text="Submit"/>
 </f:facet>

13.4.3 実行時の処理: アクション・イベントおよびアクション・リスナー

アクション・イベントは、コマンド・コンポーネントがアクティブになっているときに発生します。たとえば、ユーザーがボタンをクリックすると、そのコンポーネントが含まれているフォームが送信され、続いてアクション・イベントが起動します。アクション・イベントは、ユーザー・インタフェースのみに影響する場合(たとえば、異なるフィールド・プロンプトを表示させる、ロケールを変更するためのリンク)と、なんらかのロジック処理を伴う場合(たとえば、次のレコードに移動するためのボタン)があります。

アクション・リスナーは、コマンド・コンポーネントによってアクション・イベントが起動されたときに通知を必要とするクラスです。アクション・リスナーには、コマンド・コンポーネントによって渡されるアクション・イベント・オブジェクトを処理する、アクション・リスナー・メソッドが含まれます。

ナビゲーション操作の場合、ユーザーがたとえば「次へ」ボタンをクリックすると、アクション・イベントが起動します。このイベントは、イテレータから取得した現在のデータ・オブジェクトの現在行位置情報を格納します。コンポーネントのactionListener属性がNextアクション・バインディングのexecuteメソッドにバインドされているため、Next操作が起動します。このメソッドは、イベント・オブジェクトで渡された現在行位置情報を使用して、次のデータ・オブジェクトを判別します。

13.4.4 ブラウザの「戻る」ボタンについての考慮事項

ユーザーがナビゲーション・ボタンをクリックすると、イテレータによって次に表示するデータ・オブジェクトが判別されます。ただし、ユーザーがブラウザの「戻る」ボタンをクリックすると、アクションやイベントはブラウザ外で共有されず、イテレータが無視されます。つまり、ユーザーがページのナビゲーション・ボタンを使用するかわりにブラウザの「戻る」ボタンをクリックした場合は、表示されたページとイテレータが同期しなくなるため、予期しない結果が発生します。

たとえば、ユーザーがオブジェクト103を参照し、ブラウザの「戻る」ボタンを使用したとします。ブラウザは、最後に表示されたページを表示するため、ブラウザにオブジェクト102が表示されます。ただし、イテレータは無視されたため、イテレータの認識では、現在のオブジェクトは103のままです。その後、ユーザーが103を表示しようとして「次へ」ボタンをクリックすると、イテレータが次のオブジェクトとして認識している104が表示されます。

イテレータとページが同期していないため、ユーザーがレコードを編集する際に問題が生じます。たとえば、ユーザーがブラウザの「戻る」ボタンをクリックした後でオブジェクト102を編集すると、変更内容が103にポストされます。これは、イテレータが、103を現在のオブジェクトとして認識しているためです。

ユーザーが間違ったオブジェクト・インスタンスに変更を行うのを防ぐために、トークン検証を使用できます。ページのトークン検証を有効化すると、そのページのレンダリングに使用されるすべてのイテレータに対する現在のオブジェクトを使用して、ページに注釈が付けられます。この注釈は、ブラウザにレンダリングされたHTMLペイロードにエンコードされ、データとともにサーバーに送信されます。その時点で、イテレータの現在のオブジェクトが注釈と比較されます。一致していなかった場合は、例外がスローされます。

たとえば、前述の例のように、ユーザーが最初にオブジェクト103を表示し、102に移動しようとしてブラウザの「戻る」ボタンをクリックした場合は、前のページが表示されます。ただし、ページには102の注釈が付いています。そのため、ユーザーがページを送信して次のページに移動するつもりで「次へ」ボタンをクリックしても、注釈(102)がイテレータ(103のまま)と一致しないため、例外がスローされ、Next操作は実行されません。ページは、イテレータの現在のオブジェクトである103を使用して、レンダリングされます。データを使用して送信された注釈に基づいて、サーバーでは102を予定していたため、ページには、102を予定していたことを示すエラー・メッセージが表示されます。現在は103が表示されているため、注釈とイテレータがともに現在は103で、再び同期された状態になります。

トークン検証は、JSFページのページ定義で設定されます。トークン検証は、デフォルトでオンになっています。

トークン検証の設定手順:

  1. ページのページ定義ファイルを開きます。

  2. 構造ウィンドウで、ページ定義自体のルート・ノードを選択します。

  3. プロパティ・インスペクタのEnableTokenValidation属性のドロップダウン・リストを使用して、検証をtrueに設定してトークン検証をオンにするか、falseに設定してオフにします。

例13-11は、トークン検証がtrueに設定された後のページ定義ファイルを示しています。

例13-11 ページ定義ファイルで有効化されたトークン検証

<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
                version="10.1.3.35.29" id="createProductPageDef"
                Package="oracle.srdemo.view.pageDefs"
                EnableTokenValidation="true">

13.5 既存レコードを編集するフォームの作成

ユーザーが現在のデータを編集し、その変更をデータ・ソースにコミットするためのフォームを作成できます。次に、コレクションに関連付けられた操作またはデータ・コントロール自体を使用して、データ・レコードの変更に使用されるコマンド・ボタンを作成します。たとえば、Delete操作を使用して、ユーザーが現在のレンジからレコードを削除できるボタンを作成します。または、組込みの「発行」ボタンを使用して、変更を送信できます。


ヒント:

フォーム上で作成操作を使用して、新規オブジェクトを作成することもできますが、「ADF作成フォーム」を使用すると追加の組込み機能が提供されます。詳細は、13.6項「入力フォームの作成」を参照してください。

重要なのは、これらの操作がADFキャッシュのオブジェクトに対してのみ実行されるという点です。ルート・データ・コントロール上でCommit操作を使用して、任意の変更をデータ・ソースに実際にコミットする必要があります。データ・コントロールのRollback操作を使用して、キャッシュされたオブジェクトに対する任意の変更をロールバックします。

13.5.1 データ・コントロール・パレットを使用した編集フォームの作成方法

フォーム上の操作を使用するには、ナビゲーション操作と同じ手順(13.4.1項「フォームへのナビゲーション・コントロールの挿入方法」を参照)に従いますが、データ・ストアで変更をコミットする、あるいはキャッシュをリストアするため、コミット操作およびロールバック操作のボタンも作成する必要があります。

編集フォームの作成方法:

  1. データ・コントロール・パレットから、フォームを作成するコレクションをドラッグし、ポップアップ・メニューから「ADFフォーム」を選択します。

  2. ユーザーが「フォーム・フィールドの編集」ダイアログでデータを変更できるようにするには、「送信ボタンを含める」を選択します。

  3. 操作の実行対象となるオブジェクトのコレクションに関連付けられている操作をデータ・コントロール・パレットから選択し、JSFページ上にドラッグします。

    たとえば、サービス・リクエスト全体を削除できるようにする場合は、ServiceRequestsコレクションに関連付けられているDelete操作をドラッグします。図13-8は、コレクションに関連付けられている操作を示しています。

    図13-8 コレクションに関連付けられている操作

    データ・コントロール・パレットに表示されたナビゲーション操作
  4. ポップアップ・メニューから「コマンド・ボタン」または「コマンド・リンク」を選択します。

  5. データ・コントロール・パレットから、ルート・レベル・データ・コントロールに関連付けられたCommit操作とRollback操作をドラッグし、コマンド・ボタンまたはコマンド・リンクのいずれかとしてドロップします。これにより、変更がコミットまたはロールバックされるようになります。図13-9に、SRServiceデータ・コントロールのコミット操作とロールバック操作を示します。

    図13-9 データ・コントロールのコミット操作とロールバック操作

    コミット操作はOperationsフォルダの下にネストされます。

13.5.2 組込み操作を使用してデータを変更した場合の処理

コマンド・ボタンとして任意のデータ・コントロール操作をドロップすると、ナビゲーション操作のドロップと同じイベントが発生します。詳細は、13.4.2項「データ・コントロール・パレットでコマンド・ボタンを作成した場合の処理」 を参照してください。

Commit操作とRollback操作はアプリケーション・モジュールでメソッドを実行するため、これらの操作のアクション・バインディングがイテレータへの参照を必要としないことが唯一の相違点です。例13-12に、これらの操作に対するページ定義ファイルに生成されたアクション・バインディングを示します。

例13-12 コミット操作とロールバック操作のアクション・バインディング

<action id="Commit" InstanceName="SRService"
            DataControl="SRService" RequiresUpdateModel="true"
            Action="100"/>
<action id="Rollback" InstanceName="SRService"
            DataControl="SRService" RequiresUpdateModel="false"
            Action="101"/>

次の表は、データ・コントロールで可能な組込みのナビゲーション以外の操作と、その操作の起動結果または操作にバインドされたイベントの実行結果を示します(アクション・イベントの詳細は、13.4.3項「実行時の処理: アクション・イベントおよびアクション・リスナー」を参照してください)。

表13-2 追加の組込み操作

操作 アクション属性値 関連イテレータ・バインディングによる起動時の処理

Create

41

現在行の直前に行を作成し、現在行のポインタを新規行に移動します。レンジは移動しません。つまり、レンジの最終行がレンジから除外される場合があります。また、この操作が実行するのはCreate操作であって、CreateInsert操作ではありません。つまり、レコードは行セットに挿入されません。これは、実際にデータを作成せずにユーザーが別のページに移動してしまった場合の空白行を回避するためです。新規行は、ユーザーがデータを送信すると作成されます。

Delete

30

キャッシュから現在行を削除し、現在行のポインタを結果セットの次の行に移動します。レンジは移動しません。つまり、行がレンジの最後に追加される場合があります。最終行が削除される場合は、現在行のポインタが前の行に移動します。コレクションに行がそれ以上ない場合は、有効な属性が「無効」に設定されます。

SetCurrentRowWithKey

96

行キーを、入力フィールドで指定された値から変換されたStringとして設定します。行キーは、バインドされたデータ・コレクション内のデータ・オブジェクトの現状設定に使用されます。この使用例は、14.7.1項「手動による現在行の設定方法」を参照してください。

SetCurrentRowWithKeyValue

98

キーの値を使用して、イテレータの現在のオブジェクトを設定します。

RemoveRowWithKey

99

入力フィールドによって指定された値から変換されたStringとして行キーを使用し、バインドされたデータ・コレクションのデータ・オブジェクトを削除します。

Commit

100

現在キャッシュ内にあるすべての項目をデータベースにコミットします。

Rollback

101

キャッシュをクリアして、トランザクションおよびイテレータを初期状態に戻します。

ExecuteおよびFind


これらの操作は、検索フォームでのみ使用されます。詳細は、第18章「検索フォームの作成」を参照してください。


13.6 入力フォームの作成

ユーザーが新規レコードの情報を入力し、そのレコードをデータソースにコミットするためのフォームを作成できます。デフォルトのADFフォームを使用して、作成操作をコマンド・ボタンとしてドロップすることもできますが、このタイプのフォームを最初にレンダリングする際には、コレクションの最初のインスタンスのデータが表示されます。「ADF作成フォーム」を使用すると、ユーザーは既存のインスタンスを最初に表示せずにコレクションの新規インスタンスを作成できます。

ただし、場合によっては、新規オブジェクトの作成方法をより詳細に制御する必要があります。たとえば、特定の属性にプログラム的に値を移入するとします。この場合、オブジェクトの作成を処理するカスタム・メソッドをアプリケーション・モジュール上で作成できます。カスタム・メソッドを使用して入力フォームを作成するには、「ADF作成フォーム」を使用するかわりに、標準フォームを使用してからコマンド・ボタンとしてカスタム・メソッドをドロップします。ユーザーがボタンをクリックすると、カスタム・メソッドが実行されます。


注意:

プログラムで行を作成する場合、NewRow.setNewRowState(RowSet.STATUS_INITIALIZEDメソッドをコールして、組込みのCreateアクションと同じ動作を取得する必要があります。詳細は、10.4.4項「CreateおよびCreateInsertについて」を参照してください。

13.6.1 入力フォームの作成方法

その他のフォームの作成方法と同様に、入力フォームを作成します。ただし、コレクションをドロップする際に「ADF作成フォーム」を選択すると、JDeveloperでは追加機能が自動的に提供されます。

入力フォームの作成方法:

  1. データ・コントロール・パレットから、フォームを作成するコレクションをドラッグし、ポップアップ・メニューから「ADF作成フォーム」を選択します。

  2. 「フォーム・フィールドの編集」ダイアログには、「発行」ボタンを含めないでください。

  3. データ・コントロール・パレットから、ルート・データ・コントロールに関連付けられたコミット操作およびロールバック操作をドラッグし、コマンド・ボタンまたはリンクとしてドロップします。

  4. 構造ウィンドウで、コミット操作のコマンド・ボタンを選択します。

  5. プロパティ・インスペクタで、コマンド・ボタンのDisabledプロパティをFalseに設定します。

    デフォルトでは、JDeveloperはボタンのDisabled属性をバインディングのEnabledプロパティにバインドします。これにより、EnabledプロパティがFalseに設定されると、ボタンが無効になります。このバインディングの場合、更新がポストされるまで、Enabledプロパティはfalseです。ユーザーに新しいオブジェクトを作成する必要が生じるまでは変更がポストされないため、入力フォームの目的上、ボタンは常に有効にしておく必要があります。

13.6.2 入力フォームの作成時の処理

「ADF作成フォーム」を使用して入力フォームを作成すると、JDeveloperによって次の処理が行われます。

  • コレクションのイテレータ・バインディング、作成操作のアクション・バインディング、そしてコレクションのオブジェクトの各属性の属性バインディングを作成します。また、ページ定義の実行可能セクションに起動アクションが作成され、このアクションによって、このCreate操作がモデル・レンダリング・フェーズで実行されます。Commit操作およびRollback操作を使用してコマンド・ボタンまたはリンクを作成した場合、JDeveloperではこれらの操作のアクション・バインディングも作成されます。

  • ADF Faces inputTextコンポーネント、および操作の場合はcommandButtonコンポーネントを使用して、JSFページにフォームのコードが挿入されます。

たとえば、SRDemoアプリケーションで製品の単純な入力フォームを作成するには、図13-10のように、データ・コントロール・パレットからProductsListコレクションをADF作成フォームとしてドロップし、そのフォームの下に、コミット操作をボタンとしてドロップできます。


注意:

この例で示したページは、実際のSRDemoアプリケーションには含まれていません。

図13-10 単純な製品作成フォーム

ID、名前および説明を入力できる製品作成フォーム

例13-13は、この入力フォームのページ定義ファイルを示しています。起動アクションがレンダリング準備ライフサイクル・フェーズで実行されると、Create操作が起動され、コレクションの新規インスタンスが作成されます。ライフサイクルの詳細は13.2.3項「実行時に行われる処理: JSFおよびADFのライフサイクル」を参照してください。

例13-13 作成フォームのページ定義コード

<executables>
  <iterator id="ProductListIterator" RangeSize="10" Binds="ProductList"
            DataControl="SRService"/>
  <invokeAction Binds="Create" id="invokeCreate" Refresh="renderModel"
                RefreshCondition="${!adfFacesContext.postback and empty
                                              bindings.exceptionsList}"/>
</executables>
<bindings>
  <action id="Create" RequiresUpdateModel="true" Action="41"
          IterBinding="ProductListIterator"
          InstanceName="SRServiceDataControl.ProductList"
          DataControl="SRServiceDataControl"/>
  <attributeValues id="ProdId" IterBinding="ProductListIterator">
    <AttrNames>
      <Item Value="ProdId"/>
    </AttrNames>
  </attributeValues>
  <attributeValues id="Name" IterBinding="ProductListIterator">
    <AttrNames>
      <Item Value="Name"/>
    </AttrNames>
  </attributeValues>
  <attributeValues id="Description" IterBinding="ProductListIterator">
    <AttrNames>
      <Item Value="Description"/>
    </AttrNames>
  </attributeValues>
  <action id="Commit" InstanceName="SRServiceDataControl"
          DataControl="SRServiceDataControl" RequiresUpdateModel="true"
          Action="100"/>
</bindings>

Create操作が起動される場合は常に(たとえば、ページが最初にレンダリングされる場合)、データ・オブジェクトが作成されます。ただし、データがキャッシュされる(これにより、Create操作によるサーバーへのポストバックが可能になる)ため、また、ページがrenderModelフェーズになる場合はいつでもCreate操作が起動されるため、Create操作では、ユーザーが別のオブジェクト作成のためにこのページに再びアクセスすると、同一オブジェクトが再作成されます。また、エラーが発生すると、エラー・メッセージを使用してページが再レンダリングされるため、オブジェクトが再び作成されます。

複製を回避するために、起動アクションのrefreshConditionプロパティは、サーバーへのポストバックが存在せず、エラー・メッセージがないかぎり、Create操作が1回しか起動されないように設定されています(EL式は例13-13を参照してください)。ユーザーが(アクション・バインディングによってコミット・アクションにバインドされる)「コミット」ボタンをクリックすると、データを持つ新規オブジェクトがデータソースに送信されます。ユーザーが同じページ上で複数のオブジェクトを作成できるようにするには、第13章「フォームの作成およびRefreshConditionについて」を参照してください。

13.6.3 順序番号の表示について

ページが表示される前にinvokeCreateアクションが実行されるため、順序を使用して主キー(この場合は製品ID)を移入する場合は、番号が入力テキスト・フィールドに表示されます。たとえば、空白にしておくかわりに、図13-10の製品IDに製品ID番号を表示します。これは、製品エンティティ・クラスに、Eagerフェッチを使用してprodId属性の番号の順序を生成するメソッドが含まれるためです。これにより、行が作成される際に値が移入されます。

ただし、かわりに属性のタイプを(データベース・トリガーを使用して順序を生成する)DBSequenceに構成した場合、オブジェクトがデータベースにコミットされるまで番号は移入されません。この場合は、プレースホルダとして負の数が表示されます。この状態を回避するには、入力テキスト・フィールドのRendered属性に次のEL式を使用できます。

#{bindings.EmployeeId.inputValue.value > 0}

この式は、値がゼロより大きい場合のみコンポーネントを表示します。これは、コミットの前ではなくなります。同様に、単純にRendered属性をfalseに設定できます。ただし、これによってページに主キーの入力テキスト・フィールド・コンポーネントが表示されなくなります。

13.6.4 フォームの作成およびRefreshConditionについて

ユーザーが入力フォームの「コミット」ボタンでページを閉じることができない場合は、そのページで最後のエントリからのデータ表示が再レンダリングされます。これは、invokeCreate起動アクション上のrefreshCondition${!adfFacesContext.postback and empty bindings.exceptionsList})が、ポストバックがある場合にアクションが起動されなくなる原因となるためです。これは、データがコミットされる場合に該当します。

一度に複数の製品を作成するなど、ページ上にユーザーが留まることができるようにする場合は、refreshConditionを変更して、新規オブジェクトをコミットした後にinvokeCreateアクションを実行できるようにする必要があります。これを実行するために、Commitコマンド・コンポーネント内でsetActionListenerコンポーネントを使用します。setActionListenerコンポーネントを使用すると、移動する前にコマンド・コンポーネントによって値が設定されます。この場合、コマンド・コンポーネントはリクエスト・スコープ上でcreateAnotherという名前のフラグをtrueに設定します。次の手順に示すように、refreshConditionではこのフラグを評価し、invokeCreateアクションを実行するかどうかを判断できます。setActionListenerコンポーネントの詳細は、17.4.2項「パラメータの設定時に行われる処理」を参照してください。

複数オブジェクトを作成できる入力フォームの作成方法:

  1. この手順に従って、入力フォームを作成します。

  2. JSFページで、コンポーネント・パレットからsetActionListenerコンポーネントを「コミット」コマンド・ボタン上にドラッグします。


    注意:

    この手順は、ユーザーがこの「コミット」ボタンをクリックした後、別のエントリを作成するために同じページに戻ることを前提にしています。これを反映するため、ボタンの名前をCommit and Create Anotherなどに変更する場合があります。ページを閉じるには、別のボタンを作成する必要があります。

  3. 「setActionListenerの挿入」ダイアログで、次の項目を設定します。

    • : #{true}

    • : #{requestScope.createAnother}

    これにより、リクエスト・スコープ上でcreateAnotherという名前のフラグを作成し、それをtrueに設定します。

  4. JSFページのページ定義を開きます。

  5. invokeCreate起動アクションのrefreshConditionを次のように変更します。

    ${!adfFacesContext.postback and empty bindings.exceptionsList}
    

    変更後:

    #{empty bindings.expressionList and (!adfFacesContext.postback or
     requestScope.createAnother)}
    

    これにより、エラー・メッセージを含む式リストが空であり、ポストバックまたはリクエスト・スコープ上のcreateAnotherフラグがtrueに設定されている場合に、invokeCreateアクションを実行する条件が設定されます。


注意:

setActionListenerコンポーネントは、ライフサイクルのアプリケーションの起動フェーズで実行します。このため、invokeCreateアクションのrefresh属性を後続フェーズに設定する必要があります。この場合は、デフォルトでrenderModelに設定されるため変更しないでください。

13.7 フォーム上のUIコンポーネントおよびバインディングの変更

データ・コントロール・パレットを使用してフォームを作成したら、属性の削除、表示順序の変更、表示に使用するコンポーネントの変更、およびバインド先の属性の変更を行えます。

13.7.1 UIコンポーネントおよびバインディングの変更方法

データ・コントロール・パレットからドロップしたデフォルト・コンポーネントについて、一部の内容を変更することができます。構造ウィンドウを使用して、コンポーネントの表示順序の変更、新規コンポーネントの追加や既存のコンポーネントの変更、またはコンポーネントの削除を行えます。プロパティ・インスペクタを使用すると、バインディングの変更や削除、またはコンポーネントに対して表示されるラベルの変更を行えます。

デフォルト・コンポーネントおよびバインディングの変更の手順:

  1. 構造ウィンドウを使用して、次の処理を行います。

    • UIコンポーネントの順序の変更。ツリー内でUIコンポーネントを上下にドラッグします。矢印付きの黒い線は、UIコンポーネントが配置される場所を示しています。

    • 新規属性のUIコンポーネントの追加。構造ウィンドウで既存のUIコンポーネントを右クリックし、新規コンポーネントの配置場所として、選択したコンポーネントの前、後ろ、内部のいずれかを選択します。その後、リストからUIコンポーネントを選択します。

      新規コンポーネントを属性にバインドするには、プロパティ・インスペクタを使用する必要があります。詳細は、手順2の最初の項目を参照してください。

    • UIコンポーネントの削除。コンポーネントを右クリックして、「削除」を選択します。コンポーネントを残してバインディングのみを削除する場合は、プロパティ・インスペクタを使用する必要があります。手順2の2番目の項目を参照してください。

  2. 構造ウィンドウでUIコンポーネントを選択した後、プロパティ・インスペクタで次の処理を行えます。

    • UIコンポーネントのバインディングの追加。「値」フィールドにEL式を入力するか、「値」フィールドの省略記号(...)ボタンをクリックして、EL式ビルダーを開きます。データ・コントロールから使用できるバインディングを選択するには、「ADFバインディング」→「Bindings」ノードを選択します。このノードは、現在バインドされているコレクションから使用できる操作、イテレータ、属性、およびバインディング・プロパティを表示します。EL式の使用の詳細は、12.6項「ADFデータ・バインディングEL式の作成」を参照してください。

    • UIコンポーネントのバインディングの削除。EL式を削除します。

    • バインディングの変更。その他の属性または別の属性の任意のプロパティに、コンポーネントをリバインドできます。手順は、13.7.1.1項「UIコンポーネントの値バインディングの変更」を参照してください。

    • UIコンポーネントのラベルの変更。デフォルトでは、ラベルはバインディングのlabelプロパティにバインドされています(このプロパティの詳細は、付録B「ADFバインディング・プロパティのリファレンス」を参照してください)。このプロパティにより、エンティティ・オブジェクト属性またはビュー・オブジェクト属性に対して定義したラベルのUIコントロール・ヒントをページで使用できるようになります。ここでは、値の1度の変更で、ラベルを表示するすべてのページに同じ値を表示できます。

      現在のページのラベルのみを変更することもできます。その場合は、Label属性を選択します。ラベル値を別のもの(たとえば、プロパティ・ファイルやリソース・ファイルのキー)にバインドするために、テキストまたはEL式を入力します。

      たとえば、サービス・リクエストのステータスの入力に使用するinputTextコンポーネントでは、Label属性に対して次のコードが含まれます。

      #{bindings.Status.label}
      

      この式のstatusは、ページ定義ファイルの属性バインディングのIDです。

      この式を変更して、プロパティ・ファイルのキーにバインドすることもできます。次に例を示します。

      #{srproperties['sr.status']}
      

      この例のsrpropertiesは、プロパティ・ファイルのロードに使用する、JSFページで定義された変数です。SREditページでは、resという変数が使用されます。取消ボタンのラベルには、次の値が設定されています。

      #{res['srdemo.cancel']}
      

      リソース・バンドルの使用方法の詳細は、22.4項「アプリケーションの国際化」を参照してください。

13.7.1.1 UIコンポーネントの値バインディングの変更

バインディングを変更するかわりに、フォーム内のUIコンポーネントがバインドされているオブジェクトを完全に変更することができます。

UIコンポーネントのリバインドの手順:

  1. データ・コントロール・パレットから、コンポーネントの新しいバインド先となるコレクションまたは属性をドラッグし、コンポーネント上にドロップします。

    または

    構造ウィンドウでUIコンポーネントを右クリックし、「バインディングを編集」を選択します。バインディングを変更するUIコンポーネントに応じて、属性、表またはリストのバインディング・エディタが起動します。

  2. ポップアップ・メニューから「既存の<コンポーネント名>のバインド」を選択します。

13.7.1.2 UIコンポーネントのアクション・バインディングの変更

コンポーネントが組込み操作にバインドされている場合は、アクション・バインディング・エディタを使用してアクションを変更できます。

UIコマンド・コンポーネントのリバインドの手順:

  1. 構造ウィンドウでコマンド・コンポーネントを右クリックし、「バインディングを編集」を選択します。これによって、アクション・バインディング・エディタが起動します。

  2. アクション・バインディング・エディタのドロップダウン・メニューを使用して、別のアクションを選択します。

13.7.2 属性およびバインディングを変更した場合の処理

UIコンポーネントを移動または変更して属性の表示を変更すると、JDeveloperによって、JSFページの対応するコードが変更されます。バインディング・エディタを使用してバインディングを追加または変更すると、JDeveloperによって、JSFページにコードが追加され、ページ定義ファイルに適切な要素が追加されます。