ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Application Development Framework Java EE開発者ガイド
11g リリース2(11.1.2.4.0)
B66160-04
  目次へ移動
目次

前
 
次
 

6 マスター/ディテール・データの表示

この章では、「データ・コントロール」パネルを使用して、ADF Facesコンポーネントに基づいたマスター/ディテール・オブジェクトを作成する方法について説明します。事前作成済のマスター/ディテール・ウィジェット、表、ツリーおよびツリー表を使用してマスター/ディテール・データを表示する方法と、選択イベントの操作方法について説明します。

この章には、次の項が含まれます:

選択リストを使用して、関連するマスター・コレクションまたはディテール・コレクションからのキー値をコレクションに移入する方法の詳細は、第7章「データバインドされた選択リストの作成」を参照してください。

6.1 マスター/ディテール・データの表示の概要

オブジェクトがマスター/ディテール関係にある場合は、両方のオブジェクトのデータを同時に表示するページを宣言的に作成できます。たとえば、図6-1に示すページでは、ページ上部のフォームに国コードを表示し、関連する州および地方をページ下部の表に表示しています。このような表示ができるのは、オブジェクトがマスター/ディテール関係にあるためです。この例では、Country Codeがマスター・オブジェクトで、Statesがディテール・オブジェクトです。ADFイテレータは、選択されたマスター・データ・オブジェクトに対して表示されるディテール・データ・オブジェクトの同期化を自動的に管理します。イテレータ・バインディングにより、データ・コレクションのスクロール処理やページング、または概要情報から詳細情報へのドリルダウンを可能にするユーザー・インタフェースを簡単に作成できます。

図6-1 ディテール表

この図は、マスター・フォーム・ディテール表を示しています。

マスター・オブジェクトとディテール・オブジェクトは、フォームおよび表に表示します。マスター/ディテール・フォームを使用すると、これらのオブジェクトを別々のページに表示できます。たとえば、マスター・オブジェクトをあるページの表に表示し、ディテール・オブジェクトを別のページの読取り専用フォームに表示できます。


注意:

Jdeveloperで提供されるマスター/ディテールUIコンポーネントでは必要な機能を発揮できない場合があります。たとえば、マスター/ディテールUIコンポーネントを使用するかわりに、コンポーネントをプログラム的にバインドすることが必要な場合があります。

マスター・オブジェクトは多数のディテール・オブジェクトを保持でき、各ディテール・オブジェクトも自身のディテール・オブジェクトを多くのレベル(深さ)にわたって保持できます。この階層内のディテール・オブジェクトの1つをアプリケーション・ナビゲータからマスター/ディテール・フォームとしてページにドロップすると、直接の親マスター・オブジェクトのみがページに表示されます。最上位の親オブジェクトまで、階層全体が表示されるわけではありません。

ディテール・オブジェクトをツリー・オブジェクトまたはツリー表オブジェクトとして表示すると、複数のレベルからなる階層全体を、最上位のマスター・オブジェクトから各ノードの子ディテール・オブジェクトまで表示できます。


6.2 「データ・コントロール」パネルでのマスター/ディテール・オブジェクトの識別

「データ・コントロール」パネルを使用して、マスター/ディテール・データを表示するページを宣言的に 作成できます。「データ・コントロール」パネルでは、マスター/ディテール関係にあるオブジェクトが階層に表示されます。この階層は、ディテール・オブジェクトがマスター・オブジェクトの子となるデータ・モデルを表したものです。

マスター/ディテール・オブジェクトをフォーム・オブジェクトまたは表オブジェクトとして表示するには、「データ・コントロール」パネルからディテール・オブジェクトをドラッグし、ページにドロップします。マスター・オブジェクトは、ページ上に自動的に作成されます。

図6-2は、「データ・コントロール」パネルに表示された、マスター/ディテール関係にある2つのアクセッサ戻りコレクションを示しています。ProductImageListProductFindAllの子として表示されています。


注意:

「データ・コントロール」パネルに表示されるマスター/ディテール階層には、関係のカーディナリティ(1対多、1対1、多対多)は反映されません。この階層は単に、どのアクセッサ戻りコレクション(マスター)を使用して別のアクセッサ戻りコレクション(ディテール)から1つ以上のオブジェクトを取得しているかを示します。


図6-2 「データ・コントロール」パネルでのマスター/ディテール・オブジェクト

「データ・コントロール」パネルでのマスター/ディテール・オブジェクト。

この例では、ProductFindAllProductImageListの関係は一方向関係です。

6.3 表およびフォームを使用したマスター/ディテール・オブジェクトの表示

「データ・コントロール」パネルを使用すると、マスター/ディテール参照ページを単一の宣言的アクションで作成できます。そのために必要な操作は、ディテールのアクセッサ戻りコレクションをページにドロップして、使用するウィジェットのタイプを選択することのみです。

「データ・コントロール」パネルで使用できる事前作成済のマスター/ディテール・ウィジェットには、コレクション内のデータ・オブジェクトをエンド・ユーザーがスクロールできるレンジ・ナビゲーションが含まれます。テキスト・フィールドまたは列をページから削除すると、不要な属性を削除できます。

図6-3に、事前作成済のマスター/ディテール・ウィジェットの例を示します。このウィジェットでは、ページ上部のフォームに商品情報が表示され、ページ下部の表に在庫レベルが表示されています。ユーザーが「次へ」ボタンをクリックし、ページ上部のマスター・データのレコードをスクロールすると、関連するディテール・データが自動的にページに表示されます。

図6-3 「データ・コントロール」パネルの事前作成済のマスター/ディテール・ウィジェット

事前作成済のマスター/ディテール・ウィジェット。

6.3.1 表およびフォームでのマスター/ディテール・オブジェクトの表示方法

事前作成済のマスター/ディテール・ウィジェットを使用しない場合、マスター・オブジェクトとディテール・オブジェクトを表やフォームとして、「データ・コントロール」パネルから単一のページまたは別々のページに1つずつドラッグ・アンド・ドロップできます。

「データ・コントロール」パネルで事前作成済のマスター/ディテール・フォームおよび表を使用すると、単一の宣言的アクションで、マスター・ウィジェットとディテール・ウィジェットの両方を1つのページ上に作成できます。

事前作成済のADFマスター/ディテール・フォームおよび表を使用したマスター/ディテール・ページを作成する手順:

  1. 「データ・コントロール」パネルでディテール・オブジェクトを特定します。

  2. ディテール・オブジェクトをJSFページにドラッグ・アンド・ドロップします。


    注意:

    編集可能なマスター/ディテール・フォームを作成する場合は、マスター・オブジェクトとディテール・オブジェクトを別々にページにドロップします。


  3. ポップアップ・メニューから、次のいずれかのマスター/ディテールUIコンポーネントを選択します。

    • ADFマスター表、ディテール・フォーム: 表にマスター・オブジェクトが表示され、表の下にある読取り専用フォームにディテール・オブジェクトが表示されます。

      マスター表で特定のデータ・オブジェクトを選択すると、その下にあるフォーム内に、関連する最初のディテール・データ・オブジェクトが表示されます。後続の各ディテール・データ・オブジェクトをスクロールするには、フォーム・ナビゲーションを使用する必要があります。

    • ADFマスター・フォーム、ディテール表: マスター・オブジェクトが読取り専用フォームに表示され、ディテール・オブジェクトがフォームの下にある読取り専用表に表示されます。

      フォームに特定のマスター・データ・オブジェクトを表示すると、その下にある表に、関連するディテール・データ・オブジェクトが表示されます。

    • ADFマスター・フォーム、ディテール・フォーム: マスター・オブジェクトとディテール・オブジェクトが別々のフォームに表示されます。

      上のフォームに特定のマスター・データ・オブジェクトを表示すると、その下にあるフォームに、関連する最初のディテール・オブジェクトが表示されます。後続の各ディテール・データ・オブジェクトをスクロールするには、フォーム・ナビゲーションを使用する必要があります。

    • ADFマスター表、ディテール表: マスター・オブジェクトとディテール・オブジェクトが別々の表に表示されます。

      上の表で特定のマスター・データ・オブジェクトを選択すると、その下にある表に、関連する最初のディテール・データ・オブジェクトのセットが表示されます。

6.3.2 マスター/ディテール表およびフォームの作成時の処理

「データ・コントロール」パネルからアクセッサ戻りコレクションをドラッグ・アンド・ドロップすると、様々な処理が自動的に行われます。たとえば、JSFページにコードが追加され、ページ定義ファイルに対応するエントリが追加されます。

6.3.2.1 JSFページで生成されるコード

事前作成済のマスター/ディテール・ウィジェット用に生成されたJSFコードは、「データ・コントロール」パネルを使用して読取り専用のフォームまたは表を作成したときに生成されるJSFコードとほぼ同じです。独自のマスター/ディテール・ウィジェットを作成する場合、事前作成済のマスター/ディテール表およびフォームに自動的に組み込まれるものと同様のコンポーネントを組み込むことを検討してください。

事前作成済のマスター/ディテール・ウィジェットの表およびフォームには、フォームまたは表にデータを移入するデータ・オブジェクトの完全修飾名を保持するpanelHeaderタグが含まれます。このラベルは、リソース・バンドルにバインドする文字列またはEL式を使用して、必要に応じて変更できます。

コレクション内に複数のデータ・オブジェクトがある場合、事前作成済のマスター/ディテール・ウィジェットのフォームには、レンジ・ナビゲーション用としてFirstPreviousNextおよびLastという4つのcommandButtonタグがあります。これらのレンジ・ナビゲーション・ボタンを使用して、コレクション内のデータ・オブジェクトをスクロールできます。各ボタンのactionListener属性は、ナビゲーションを実行するデータ・コントロール操作にバインドされています。ボタンをクリックすると、actionListenerバインディングで使用されるexecuteプロパティによって、操作が起動します。(フォームに単一のデータ・オブジェクトが表示されている場合、レンジ・ナビゲーション・コンポーネントは表示されません。)


ヒント:

ページに「ADFマスター表、ディテール・フォーム」ウィジェットまたは「ADFマスター表、ディテール表」ウィジェットをドロップすると、ディテール・コンポーネントの親タグ(panelHeaderタグやtableタグなど)のpartialTriggers属性はマスター・コンポーネントのidに自動的に設定されます。実行時に、ユーザーがマスター・コンポーネントで選択を行うと、partialTriggers属性によりディテール・コンポーネントのみが再度レンダリングされます。これは、部分レンダリングと呼ばれます。マスター・コンポーネントが表の場合、ADFでは部分レンダリングが使用されます。これは、ユーザーがファセット内で選択のみを行う場合、表を再度レンダリングする必要がないためです。新しいデータを表示するために再度レンダリングする必要があるのはディテール・コンポーネントのみです。


6.3.2.2 ページ定義ファイルで定義されるバインディング・オブジェクト

例6-1に、マスター/ディテール・ページ用に作成されたページ定義ファイルを示します。このマスター/ディテール・ページは、ProductFindAllオブジェクトの下位のディテール・オブジェクトであるWarehouseStockLevelListADFマスター・フォーム、ディテール表としてページにドロップして作成したものです。

executables要素は2つのaccessorIteratorを定義しています。1つは商品(マスター・オブジェクト)に対するもの、もう1つはWarehouseStockLevels(ディテール・オブジェクト)に対するものです。実行時には、UI対応のデータ・モデルと行セット・イテレータにより、現在の行が変更されたときに、ディテール・コレクションの行セットが現在のマスター行の正しい行セットになるようにリフレッシュされます。

bindings要素は、値バインディングを定義します。フォーム内のテキスト・フィールドにデータを移入する属性バインディングは、attributeValues要素内で定義されます。attributeValues要素のid属性には各データ属性の名前が含まれ、IterBinding属性はイテレータ・バインディングを参照し、マスター・オブジェクトのデータをテキスト・フィールドに表示します。

フォーム内のテキスト・フィールドにデータを移入する属性バインディングは、attributeValues要素内で定義されます。attributeValues要素のid属性には各データ属性の名前が含まれ、IterBinding属性はイテレータ・バインディングを参照し、マスター・オブジェクトのデータをテキスト・フィールドに表示します。

フォーム内のレンジ・ナビゲーション・ボタンは、action要素で定義されたアクション・バインディングにバインドされます。属性バインディングの場合と同様、アクション・バインディングのIterBinding属性は、マスター・オブジェクトのイテレータ・バインディングを参照します。

ディテール・データを表示する表は、table要素で定義される表バインディング・オブジェクトにバインドされます。IterBinding属性は、ディテール・オブジェクトのイテレータ・バインディングを参照します。

例6-1 マスター/ディテール・ページ用にページ定義に定義されたバインディング・オブジェクト

  <executables>
    <variableIterator id="variables"/>
    <iterator Binds="root" RangeSize="25" DataControl="SupplierFacadeLocal"
              id="SupplierFacadeLocalIterator"/>
    <accessorIterator MasterBinding="SupplierFacadeLocalIterator"
                      Binds="productFindAll" RangeSize="25"
                      DataControl="SupplierFacadeLocal"
                      BeanClass="oracle.fodemo.supplier.model.Product"
                      id="productFindAllIterator"
                      ChangeEventPolicy="ppr"/>
    <accessorIterator MasterBinding="productFindAllIterator"
                      Binds="warehouseStockLevelList" RangeSize="25"
                      DataControl="SupplierFacadeLocal"
                      BeanClass="oracle.fodemo.supplier.model.WarehouseStockLevel"
                      id="warehouseStockLevelListIterator"
                      ChangeEventPolicy="ppr"/>
  </executables>
  <bindings>
   <action IterBinding="productFindAllIterator" id="First"
            RequiresUpdateModel="true" Action="first"/>
   <action IterBinding="productFindAllIterator" id="Previous"
            RequiresUpdateModel="true" Action="previous"/>
   ...
    <attributeValues IterBinding="productFindAllIterator" id="attribute1">
      <AttrNames>
        <Item Value="warrantyPeriodMonths"/>
      </AttrNames>
    </attributeValues>
    ...
    <tree IterBinding="warehouseStockLevelListIterator"
          id="warehouseStockLevelList">
      <nodeDefinition DefName="oracle.fodemo.supplier.model.WarehouseStockLevel">
        <AttrNames>
          <Item Value="lastUpdateDate"/>
          <Item Value="objectVersionId"/>
          <Item Value="productId"/>
          <Item Value="quantityOnHand"/>
          ...
          <Item Value="warehouseId"/>
        </AttrNames>
      </nodeDefinition>
    </tree>
  </bindings>

6.3.3 実行時に行われる処理: マスター/ディテール表およびフォームのADFイテレータ

実行時に、ADFイテレータは、マスター表オブジェクトのどの行をマスター/ディテール・フォームに表示するかを決定します。フォームが最初に表示されるときは、マスター表オブジェクトの1行目がフォームのマスター・セクションに強調表示されます。マスター行に関連付けられているディテール表の行は、フォームのディテール・セクションに表示されます。

6.3.2.2項「ページ定義ファイルで定義されるバインディング・オブジェクト」で説明しているように、ADFイテレータは基礎となるrowsetIteratorオブジェクトに関連付けられています。これらのイテレータは、ページに現在表示されているデータ・オブジェクト(つまり行)がどれかを管理します。実行時には、行セット・イテレータがマスター・コンポーネントとディテール・コンポーネントに表示されるデータを管理します。

マスターおよびディテールの行セット・イテレータは、どちらも行セット・ナビゲーション・イベント(ユーザーによるレンジ・ナビゲーション・ボタンのクリックなど)をリスニングし、適切な行をUIに表示します。デフォルトのマスター/ディテール・コンポーネントの場合は、行セット・ナビゲーション・イベントは、フォーム上のコマンド・ボタン(「先頭へ」「前へ」「次へ」「最後へ」)になります。

ディテール・コレクションの行セット・イテレータは、 ディテール・データとマスター・データの同期化を管理します。ディテール行セット・イテレータは、マスター・コレクションとディテール・コレクションの両方で行ナビゲーション・イベントをリスニングします。マスター・コレクションで行セット・ナビゲーション・イベントが発生すると、ディテール行セット・イテレータが自動的に実行され、現在のマスター行に関連するディテール行が戻されます。

6.3.4 別々のページへのマスター/ディテール・ウィジェットの表示について

デフォルトのマスター/ディテール・コンポーネントでは、 マスター/ディテール・データは単一のページに表示されます。ただし、「データ・コントロール」パネルでマスター・オブジェクトとディテール・オブジェクトを使用して、バインディング・イテレータにマスター・オブジェクトとディテール・オブジェクトの同期化を管理させたまま、コレクションを別々のページに表示できます。

マスター/ディテール・オブジェクトを別々のページに表示するには、マスター・オブジェクト用として1ページ、ディテール・オブジェクト用として1ページの、計2ページを作成します。その際には、「データ・コントロール」パネルから使用できる、個々の表またはフォームを使用します。ディテール・オブジェクト・イテレータは、マスター・データとディテール・データの同期化を管理することを忘れないでください。ディテール・データを表示するページを作成する際には、必ず「データ・コントロール」パネルから適切なディテール・オブジェクトをドラッグしてください。詳細は、第6.2項「「データ・コントロール」パネルでのマスター/ディテール・オブジェクトの識別」を参照してください。

ページ・ナビゲーションを処理するには、ADFタスク・フローを作成し、マスター・ページ用として1つ、ディテール・ページ用として1つの、計2つのビュー・アクティビティを追加します。コマンド・ボタンまたはリンクを各ページに追加するか、「データ・コントロール」パネルを使用してフォームまたは表を作成するときに使用可能なデフォルトの「発行」ボタンを使用します。各ボタンについて、action属性内で、ナビゲーション・ルールの結果値を指定する必要があります。task-flow-defintion.xmlファイルで、マスター・データ・ページからディテール・データ・ページへのナビゲーション・ルール、およびディテール・データ・ページからマスター・データ・ページに戻るための別のルールを追加します。ナビゲーション・ルール内のfrom-outcomeの値は、ボタンのaction属性で指定された結果値と一致する必要があります。

6.4 ツリーを使用したマスター/ディテール・オブジェクトの表示

表およびフォーム以外に、階層ツリーにもマスター/ディテール・データを表示できます。ADF Facesのtreeコンポーネントは階層データの表示に使用します。マスター・オブジェクトのバインディングによって移入される複数のルート・ノードが表示されます。ツリー内の各ルート・ノードは、ディテール・オブジェクトのバインディングによって移入されるブランチを持つことが可能で、その数に制限はありません。ツリーには複数のレベルのノードがあり、各ノードは親ノードのディテール・オブジェクトを示します。ツリー内の各ノードは、階層でのノードのレベルを示します。

treeコンポーネントには、ツリー・ノードを開閉するメカニズムが含まれていますが、フォーカス機能はありません。フォーカス機能を使用する必要がある場合は、ADF FacesのtreeTableコンポーネントの使用を検討してください(詳細は、6.5項「ツリー表を使用したマスター/ディテール・オブジェクトの表示」を参照)。デフォルトでは、ツリーの各ノードのアイコンはフォルダですが、独自のアイコンを階層内の各レベルのノードに使用できます。

図6-4は、ルートとブランチという2つのレベルのノードを表示するツリーの例を示しています。ルート・ノードは「Media」、「Office」および「Electronics」などの親製品カテゴリを表示します。ブランチ・ノードには、「Office」親カテゴリの下の「Hardware」、「Supplies」、「Software」のような、各親カテゴリの下のサブカテゴリが表示されます。

図6-4 データバインドされたADF Facesツリー

この図は、データバインドされたADF Facesツリーを示しています。

6.4.1 ツリーでのマスター/ディテール・オブジェクトの表示方法

ツリーはノードの階層で構成され、各サブノードは上位レベルのノードから分岐します。データバインドされたADF Facesのtreeコンポーネントの各ノード・レベルは、異なるデータ・コレクションによって移入されます。JDeveloperでは、「ツリー・バインディングの編集」ダイアログを使用してデータバインド・ツリーを定義します。このダイアログで、ツリー内の各ノード・レベルにデータを移入するためのルールを定義できます。階層内の各ノード・レベルに対して1つのルールが必要です。それぞれのルールは、次のノード・レベル・プロパティを定義します。

  • そのノード・レベルにデータを移入するアクセッサ戻りコレクション

  • そのノード・レベルで表示される、アクセッサ戻りコレクションの属性

ツリーにマスター/ディテール・オブジェクトを表示する手順:

  1. 「データ・コントロール」パネルからマスター・オブジェクトをドラッグし、ページにドロップします。これは、ツリーのルート・レベルを表すマスター・データである必要があります。

  2. ポップアップ・メニューから、「ツリー」「ADFツリー」を選択します。

    図6-5に示す「ツリー・バインディングの編集」ダイアログが表示されます。バインディング・エディタを使用し、ツリーに表示する各レベルのルールを定義します。

    図6-5 「ツリー・バインディングの編集」ダイアログ

    「ツリー・バインディングの編集」ダイアログを示しています。
  3. 「ルート・データソース」ドロップダウン・リストで、ルート・ノード・レベルにデータを移入するアクセッサ戻りコレクションを選択します。

    これがマスター・データ・コレクションとなります。デフォルトでは、これはツリーを作成するために「データ・コントロール」パネルからドラッグしたものと同じコレクション(マスター・コレクション)です。


    ヒント:

    目的のアクセッサ戻りコレクションが「ルート・データソース」リストに見つからない場合は、「追加」ボタンをクリックします。「データソースの追加」ダイアログで、データ・コントロールとイテレータ名を選択して新しいデータソースを作成します。


  4. 「追加」アイコンをクリックし、選択したルート・データソースを「ツリー・レベル・ルール」リストに追加します。

  5. 「ツリー・レベル・ルール」リストで、追加したデータソースを選択します。

  6. 「使用可能な属性」リストで属性を選択し、「属性の表示」リストに移動します。

    この属性はマスター・レベルのノードの表示に使用されます。

    マスター・レベルのルールを定義したら、次にツリー内のマスター・レベルの下に表示されるディテール・レベルに対して2つ目のルールを定義する必要があります。

  7. 2つ目のルールを追加するには、「ツリー・レベル・ルール」リストの上の「追加」アイコンをクリックします。

    図6-6に示すように、マスター・データソースの下にディテール・データソースが自動的に表示されます。

    図6-6 マスター/ディテール・ツリー・レベル・ルール

    マスター/ディテール・ツリー・ルールを示します。

    たとえば、マスターのルート・データソースとしてProductFindAllを指定すると、「ツリー・レベル・ルール」リストの下にWarehouseStockLevelListが自動的に表示されます。これは、2つのデータソースがマスター/ディテール関係にあるためです。

    再帰的なマスター/ディテール階層を持つツリーを作成する場合は、データソースとセルフアクセッサを指定したルールを定義するだけで済みます。再帰的なツリーには、単一のコレクションに基づいてルート・ノードが表示されるとともに、そのコレクションからデータを繰返しフェッチするセルフアクセッサの属性から、子ノードが表示されます。再帰的なツリーは、ツリーのブランチを定義するためのルールが1つしか必要ないため、通常のマスター/ディテール・ツリーとは異なります。再帰的なデータソースは、図6-7に示すように、データソースの後にセルフアクセッサ名をカッコで囲んで指定した形で表示されます。

    図6-7 再帰的なツリー・レベル・ルール

    再帰的なツリー・ルールを示します。

    たとえば、EmployeesViewで定義されたコレクションでは、各ブランチのルート・ノードを従業員のManagerIdで指定できます。その場合、セルフアクセッサDirectReportsで指定されたとおり、同じブランチの子ノードはManagerIdに関連する従業員になります。

  8. 「OK」をクリックします。

  9. 「ツリー・レベル・ルール」リストにデータソースを追加し、ツリーに表示されるノード数を増やすこともできます。残りのデータソースの順序は、ツリーに表示するノードの階層に従う必要があります。

6.4.2 ADFデータバインド・ツリーの作成時の処理

「データ・コントロール」パネルからドラッグ・アンド・ドロップすると、様々な処理が自動的に行われます。

「データ・コントロール」パネルを使用してデータバインド・ツリーを作成すると、ページ定義ファイルにバインディング・オブジェクトが追加され、JSFページにtreeタグが追加されます。作成されたUIコンポーネントは、そのままで十分機能するため、変更する必要はありません。

6.4.2.1 JSFページで生成されるコード

例6-2は、「データ・コントロール」パネルを使用してツリーを作成したときにJSFページで生成されるコードを示しています。このサンプル・ツリーには、注文番号がルート・ノードとして、商品名がリーフ・ノードとして表示されます。

例6-2 データ・バインド・ツリー用にJSFページで生成されたコード

<af:tree 
   value="#{bindings.orderItemFindAll.treeModel}" 
   var="node"
   selectionListener="#{bindings.orderItemFindAll.treeModel.makeCurrent}"
   rowSelection="single" id="orderItemsTree">
   <f:facet name="nodeStamp">
       <af:outputText value="#{node}" id="ot2"/>
   </f:facet>
</af:tree>

デフォルトで、フォームの中にaf:treeタグが作成されます。treeタグのvalue属性には、treeコンポーネントをページ定義ファイルのorderItemFindAllツリー・バインディング・オブジェクトにバインドするEL式が含まれます。バインディング式のtreeModelプロパティは、基礎となるデータ・モデルに基づいてtree階層の表示方法を定義する、ADFクラスを参照します。var属性は、現在のノードへのアクセスを提供します。

f:facetタグに含まれるnodeStampファセットは、各ノードのデータを表示するために使用されます。treeでは、ノードごとにコンポーネントを持つかわりに、ADF Facesの表コンポーネントに対して行がレンダリングされるのと同様の方法で、nodeStampファセットが繰返しレンダリングされます。

ADF Facesのtreeコンポーネントは、oracle.adf.view.faces.model.PathSetクラスのインスタンスを使用して、開いた状態のノードを表示します。このインスタンスは、コンポーネントのtreeState属性として格納されます。このインスタンスを使用して、階層での要素の開閉状態をプログラム的に管理できます。PathSetインスタンスに含まれるすべての要素は、開いた状態とみなされます。その他のすべての要素は閉じた状態です。

6.4.2.2 ページ定義ファイルで定義されるバインディング・オブジェクト

例6-3は、ADFデータバインド・ツリー用にページ定義ファイルで定義されたバインディング・オブジェクトを示しています。

例6-3 データバインド・ツリー用にページ定義ファイルで定義されたバインディング・オブジェクト

<executables>
    <variableIterator id="variables"/>
    <iterator Binds="root" RangeSize="25" DataControl="SupplierFacadeLocal"
              id="SupplierFacadeLocalIterator"/>
    <accessorIterator MasterBinding="SupplierFacadeLocalIterator"
                      Binds="orderItemFindAll" RangeSize="25"
                      DataControl="SupplierFacadeLocal"
                      BeanClass="oracle.fodemo.supplier.model.OrderItem"
                      id="orderItemFindAllIterator"/>
</executables>
<bindings>
    <tree IterBinding="orderItemFindAllIterator" id="orderItemFindAll">
      <nodeDefinition DefName="oracle.fodemo.supplier.model.OrderItem"
                      Name="orderItemFindAll0">
        <AttrNames>
          <Item Value="orderId"/>
        </AttrNames>
        <Accessors>
          <Item Value="product"/>
        </Accessors>
      </nodeDefinition>
      <nodeDefinition DefName="oracle.fodemo.supplier.model.Product"
                      Name="orderItemFindAll1">
        <AttrNames>
          <Item Value="productName"/>
        </AttrNames>
      </nodeDefinition>
    </tree>
</bindings>

tree要素は、ツリーに表示されるすべての属性の値バインディングです。tree要素のIterBinding属性は、ツリーにデータを移入するイテレータ・バインディングを参照します。tree要素内のAttrNames要素は、マスター・コレクション内のすべての属性のバインディング・オブジェクトを定義します。ただし、ツリーに表示するように選択する属性は、nodeDefinition要素内のAttrNames要素で定義されます。

nodeDefinition要素は、ツリーのノードにデータを移入するためのルールを定義します。ノードごとに1つのnodeDefinition要素があり、各要素には次の属性およびサブ要素が含まれます。

  • DefName: ノードへのデータの移入に使用されるデータ・コレクションの完全修飾名が含まれる属性

  • id: ノードの名前を定義する属性

  • AttrNames: 実行時にノードに表示される属性を定義するサブ属性

  • Accessors: ツリーの次のブランチを戻すアクセッサ属性を定義するサブ属性

ページ定義ファイルでのnodeDefintion要素の順序によって、ツリーでのノードの順序またはレベルが決まります。最初のnodeDefinition要素は、ルート・ノードを定義します。後続の各nodeDefinition要素は、先行するノードのサブノードを定義します。

6.4.3 実行時に行われる処理: ADFデータバインド・ツリーの表示

treeコンポーネントは、org.apache.myfaces.trinidad.model.TreeModelを使用してデータにアクセスします。このクラスは、ADF Facesのtableコンポーネントがデータへのアクセスに使用するCollectionModelを拡張します。TreeModelクラスの詳細は、ADF Faces Javadocを参照してください。

treeを含むページが表示されると、ツリーのイテレータ・バインディングによって、ルート・ノードにデータが移入されます。ユーザーがノードを開いてブランチを表示したり、閉じて非表示にすると、DisclosureEventイベントが送信されます。このイベントのisExpandedメソッドは、ユーザーによるノードの操作(開いているか、閉じているか)を判断します。DisclosureEventイベントには、リスナーが関連付けられています。

treeDisclosureListener属性は、ページ定義ファイルで定義済のノード・ルールで指定されたアクセッサ属性にバインドされます。このアクセッサ属性は、DisclosureEventイベントに応じて起動します。つまり、ユーザーがノードを開くたびに、アクセッサ属性によってブランチ・ノードにデータが移入されます。

6.5 ツリー表を使用したマスター/ディテール・オブジェクトの表示

ADF FacesのtreeTableコンポーネントを使用すると、マスター/ディテール・コレクションの階層を表に表示できます。treeコンポーネントのかわりにtreeTableコンポーネントを使用することの利点は、treeTableコンポーネントがツリー内の特定のノードにフォーカスして表示するメカニズムを使用できることです。

たとえば、国、州または地方、都市という3つのノード・レベルを表示するツリー表を作成できます。各ルート・ノードは、個別の国を表します。各ルート・ノードが分岐して、その国の州または地方が表示されます。各州または地方のノードが分岐して、その中の都市を表示します。

ツリーの場合と同様、複数のノードがあるツリー表を作成するには、コレクションにマスター/ディテール関係を持たせる必要があります。たとえば、国、州、都市という3つのレベルを持つツリー表を作成するには、CountryCodesコレクションからStatesandProvincesコレクションへのマスター/ディテール関係、およびStatesandProvincesコレクションからCitiesコレクションへのマスター/ディテール関係が必要です。

データバインドされたADF FacesのtreeTableには、一度に1つのルート・ノードしか表示されませんが、様々なルート・ノードをスクロールするためのナビゲーションが用意されています。また、各ルート・ノードに表示されるブランチの数は制限されません。すべてのノードは表内で個別の行として表示され、各行の左端の列には、フォーカス・メカニズムが用意されています。

プロパティ・インスペクタで、次のtreeTableコンポーネント・プロパティを編集できます。

6.5.1 ツリー表でのマスター/ディテール・オブジェクトの表示方法

ADF Facesデータバインド・ツリー表の作成手順は、ADF Facesデータバインド・ツリーの作成手順とほぼ同じですが、アクセッサ戻りコレクションをドロップする際に、ADFツリーとしてではなくADFツリー表としてドロップします。

6.5.2 データバインド・ツリー表の作成時の処理

「データ・コントロール」パネルからドラッグ・アンド・ドロップすると、様々な処理が自動的に行われます。

「データ・コントロール」パネルを使用してデータバインド・ツリー表を作成すると、ページ定義ファイルにバインディング・オブジェクトが追加され、JSFページにtreeTableタグが追加されます。作成されたUIコンポーネントは、そのままで十分機能するため、変更する必要はありません。

6.5.2.1 JSFページで生成されるコード

例6-4は、「データ・コントロール」パネルを使用してツリー表を作成したときにJSFページで生成されるコードを示しています。このサンプル・ツリー表には、商品と在庫レベルという2つのノード・レベルが表示されます。

デフォルトで、フォームの中にtreeTableタグが作成されます。tree tableタグのvalue属性には、treeコンポーネントを、データ移入を行うバインディング・オブジェクトにバインドするEL式が含まれます。treeModelプロパティは、基礎となるデータ・モデルに基づいてツリー階層の表示方法を定義する、ADFクラスを参照します。var属性は、現在のノードへのアクセスを提供します。

例6-4 データバインドされたADF Facesツリー表用にJSFページで生成されたコード

<af:treeTable value="#{bindings.orderItemFindAll.treeModel}" var="node"
     selectionListener="#{bindings.orderItemFindAll.treeModel.makeCurrent}"
     rowSelection="single" id="tt1">
     <f:facet name="nodeStamp">
          <af:column id="c1">
              <af:outputText value="#{node}" id="ot1"/>
          </af:column>
     </f:facet>
     <f:facet name="pathStamp">
          <af:outputText value="#{node}" id="ot2"/>
     </f:facet>
</af:treeTable>

facetタグに含まれるnodeStampファセットは、各ノードのデータを表示するために使用されます。ノードごとにコンポーネントを持つかわりに、ツリーでは、ADF Faces tableコンポーネントに対して行がレンダリングされるのと同様の方法で、nodeStampファセットが繰返しレンダリングされます。pathStampファセットは、ユーザーがディテール・ノードにフォーカスした後で親ノードに戻れるように、表の上に列およびパスのリンクをレンダリングします。

6.5.2.2 ページ定義ファイルで定義されるバインディング・オブジェクト

ツリー表に対してページ定義ファイルで作成されるバインディング・オブジェクトは、ツリーに対して作成されるものとまったく同じです。

6.5.3 実行時に行われる処理: イベント

treeコンポーネントは、oracle.adf.view.faces.model.TreeModelを使用してデータにアクセスします。このクラスは、ADF Facesのtableコンポーネントがデータへのアクセスに使用するCollectionModelを拡張します。TreeModelクラスの詳細は、ADF Faces Javadocを参照してください。

ツリー表を含むページが表示されると、treeTableコンポーネントのイテレータ・バインディングは、ルート・ノードにデータを移入し、行ナビゲーション・イベント(ユーザーによる「次へ」ボタンまたは「前へ」ボタンのクリック、もしくはレンジ・ナビゲータからの行の選択)をリスニングします。ユーザーが行ナビゲーション・イベントを開始すると、イテレータによって適切な行が表示されます。

ユーザーがコンポーネントのフォーカス・アイコンをクリックして表示のフォーカスを変更すると、treeTableコンポーネントによってフォーカス・イベント(FocusEvent)が生成されます。フォーカス変更後のノードが現在のノードになった後で、イベントが配信されます。その後、treeTableコンポーネントによってfocusPathプロパティが適切に変更されます。ツリー上のFocusListener属性は、マネージドBeanのメソッドにバインドできます。これにより、このメソッドはフォーカス・イベントに応じて起動されます。

ユーザーがノードを開閉するたびに、公開イベント(DisclosureEvent)が送信されます。この公開イベントのisExpandedメソッドは、ユーザーの操作に基づいてノードを開くか閉じるかを判断します。公開イベントには、リスナーDisclosureListenerが関連付けられます。ツリー表上のDisclosureListener属性は、ページ定義ファイルで定義済のノード規則で指定されたアクセッサ属性にバインドされます。このアクセッサ属性は、公開イベント(ユーザーがノードを開くなど)に応じて起動し、そのノードを移入するコレクションを戻します。

treeTableコンポーネントには、「すべて展開」リンクおよび「すべて閉じる」リンクも表示されます。ユーザーがどちらかのリンクをクリックすると、treeTableによってDisclosureAllEventイベントが送信されます。このイベントのisExpandedメソッドは、ユーザーの操作に基づいてすべてのノードを開くか閉じるかを判断します。その後、現在フォーカスしているルート・ノードの子ノードが、開くか閉じます。大規模なツリーの場合は、すべて展開コマンドを使用しても、直下の子より下にあるノードは開きません。ADF FacesのtreeTableコンポーネントでは、oracle.adf.view.faces.model.PathSetクラスのインスタンスを使用して、開いたノードが判別されます。このインスタンスは、コンポーネントのtreeState属性として格納されます。このインスタンスを使用して、階層でのノードの開閉状態をプログラム的に管理できます。PathSetインスタンスに含まれるすべてのノードは、開いているとみなされます。その他のすべてのノードは閉じた状態になります。このクラスでは、addAll()removeAll()のような操作もサポートされます。

ADF FacesのtreeTableコンポーネントの詳細は、ADF Faces Javadocのoracle.adf.view.faces.component.core.data.CoreTreeTableクラスを参照してください。

6.5.4 TargetIteratorプロパティの使用

ページ定義エディタでノード・バインディングを展開すると、ページのnode Definition要素を表示できます。これらは、ツリー・バインディング・ダイアログで構成できる同じツリー・バインディング・ルールです。

ノード定義(ルール)ごとに、オプションのTargetIteratorプロパティを指定できます。その値は、ユーザーがツリーで行を選択すると、実行時に評価されるEL式です。このEL式は、現在のバインディング・コンテナ内のイテレータ・バインディングを評価します。イテレータ・バインディングの行キーの属性は、ツリー用にnodeDefinitionタイプの行が取得されるイテレータの行キーと(数値、データ型の順で)一致します。

実行時に、ツリー・コントロールはselectionChangedイベントを受け取ると、ツリーのレベルごとにキーのリストを渡します。これらのキーは選択されたノードを一意に識別します。

ツリー・バインディングは、ツリーの最上位から始まります。Currently Selected Tree Node Keysリストにキーが存在するツリー・レベルごとに、そのnodeDefinitionについて構成されているTargetIteratorプロパティがある場合、ツリー・バインディングは選択されたターゲット・イテレータに対してsetCurrentRowWithKey()操作を実行します。Currently Selected Tree Node Keysリストの適切なレベルからキーを使用します。

6.6 ツリーおよび表での選択イベントの使用

アプリケーションでなんらかの処理を行うために、ツリーまたはツリー表で選択されているノードを判別する必要が生じることがあります。たとえば、ユーザーが「参照」ツリーでカテゴリ・ノードを選択すると、選択イベントが起動します。このイベントに関連付けられているリスナーは、選択されたノードの商品カテゴリを判別し、その値に一致するカテゴリ属性を持つ商品をすべて戻す必要があります。

6.6.1 ツリーおよび表での選択イベントの使用方法

選択イベントをプログラム的に使用するには、選択イベントを処理して必要なロジックを実行するリスナーを、マネージドBean内に作成する必要があります。その後、ツリーまたは表のselectionListener属性をそのリスナーにバインドする必要があります。

ツリーおよび表で選択イベントを使用する手順:

  1. 必要なリスナーを格納するマネージドBeanがまだ存在しない場合は、作成します。

  2. マネージドBeanのリスナー・メソッドを作成します。リスナー・メソッドの作成の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』のADF Facesサーバー・イベントの使用に関する項を参照してください。リスナーは次の処理を実行する必要があります。

    1. イベント・ソースを使用してコンポーネントにアクセスします。例6-5は、HomeBeanマネージドBeanのproductCategoriesTreeSelectionListenerメソッドが、選択イベントを起動したツリーにアクセスする方法を示しています。

      例6-5 イベント・ソースの取得

      public void productCategoriesTreeSelectionListener(SelectionEvent evt) {
          RichTree tree = (RichTree)evt.getSource();
      

      イベント・ソース・コンポーネントの特定の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』のイベントの発生元を返す方法に関する項を参照してください。

    2. ツリー・モデルにアクセスしてモデルの値を取得し、RowKeySetオブジェクトを使用して現在選択されているノードを取得した後、例6-6に示すように、それをモデルの現在の行として設定します。RowKeySetオブジェクトの詳細は、6.6.2項「実行時に行われる処理: RowKeySetオブジェクトとSelectionEventイベント」を参照してください。

      例6-6 ツリー・モデルの現在の行の設定

      TreeModel model = (TreeModel)tree.getValue();
      RowKeySet rowKeySet = evt.getAddedSet();
      Object key = rowKeySet.iterator().next();
      model.setRowKey(key);
      
    3. 次に、現在選択されている行に対して実行するロジックを追加します。たとえば、productCategoriesTreeSelectionListenerメソッドは、選択されている行の値バインディングを使用してカテゴリIDを判別した後、その値を、実行時にそのカテゴリIDを持つ商品をすべて戻す(例6-7を参照)別のメソッドのパラメータとして使用します。

      例6-7 特定の属性値に一致するオブジェクトを戻す

      JUCtrlValueBinding nodeBinding = 
          (JUCtrlValueBinding)model.getRowData();
      Number catId = (Number)nodeBinding.getAttribute("CategoryId");
      _selectedCategory = (String)nodeBinding.getAttribute("CategoryName");
      
      OperationBinding ob =
           ADFUtils.findOperation("ProductsByCategoriesExecuteWithParams");
      ob.getParamsMap().put("category", catId);
      ob.execute();
      
  3. 対応するJSFページで、ツリー・コンポーネントまたは表コンポーネントを選択します。プロパティ・インスペクタで、「動作」セクションを開いて、SelectionListener属性の値を、作成したリスナー・メソッドに設定します。ドロップダウン・メソッドの「編集」オプションを使用すると、Beanとメソッドを宣言的に選択できます。

6.6.2 実行時に行われる処理: RowKeySetオブジェクトとSelectionEventイベント

ユーザーがツリーのノード(または表の行)を選択するたびに、コンポーネントは選択イベントを起動します。selectionEventイベントは、選択解除された行と選択された行をレポートします。現在の選択内容、つまり選択済の行は、RowKeySetオブジェクトによって管理され、このオブジェクトは、行の関連キーをキー・セットに追加、またはキーセットから削除することで、現在選択されているすべてのノードを追跡します。ユーザーが新しいノードを選択したときに、ツリーまたは表が単一選択用に構成されている場合、それまで選択されていたキーは破棄され、新たに選択されたキーが追加されます。ツリーまたは表が複数選択用に構成されている場合は、新たに選択されたキーがセットに追加されます。それまで選択されていたキーを破棄するかどうかは、ノードの選択方法によって決まります。たとえば、ユーザーが[Ctrl]キーを押した場合、新たに選択されたノードは現在のセットに追加されます。