Oracle® Fusion Middleware Oracle Application Development Framework Java EE開発者ガイド 11gリリース1(11.1.1) B61007-01 |
|
![]() 戻る |
![]() 次へ |
この章では、マスター/ディテール関係のデータを表示する、様々なタイプのページの作成方法について説明します。
この章の内容は次のとおりです。
選択リストを使用して、関連するマスター・コレクションまたはディテール・コレクションからのキー値をコレクションに移入する方法の詳細は、第6章「データバインドされた選択リストの作成」を参照してください。
オブジェクトがマスター/ディテール関係にある場合は、両方のオブジェクトのデータを同時に表示するページを宣言的に作成できます。たとえば、図5-1に示すページでは、ページ上部のフォームに国コードを表示し、関連する州および地方をページ下部の表に表示しています。このような表示ができるのは、オブジェクトがマスター/ディテール関係にあるためです。この例では、Country Code
がマスター・オブジェクトで、States
がディテール・オブジェクトです。ADFイテレータは、選択されたマスター・データ・オブジェクトに対して表示されるディテール・データ・オブジェクトの同期化を自動的に管理します。イテレータ・バインディングを使用することで、データ・コレクションのスクロール処理やページング、または概要情報から詳細情報へのドリルダウンを可能にするユーザー・インタフェースを簡単に作成できます。
マスター・オブジェクトとディテール・オブジェクトは、フォームおよび表に表示します。マスター/ディテール・フォームを使用すると、これらのオブジェクトを別々のページに表示できます。たとえば、マスター・オブジェクトをあるページの表に表示し、ディテール・オブジェクトを別のページの読取り専用フォームに表示できます。
注意: Jdeveloperで提供されるマスター/ディテールUIコンポーネントでは必要な機能を発揮できない場合があります。たとえば、マスター/ディテールUIコンポーネントを使用するかわりに、コンポーネントをプログラム的にバインドすることが必要な場合があります。マスター・オブジェクトは多くのディテール・オブジェクトを持つことができます。各ディテール・オブジェクトも自身のディテール・オブジェクトを持つことができ、これらのディテール・オブジェクトは多くのレベルからなる階層を形成します。この階層内のディテール・オブジェクトの1つをアプリケーション・ナビゲータからマスター/ディテール・フォームとしてページにドロップすると、直接の親マスター・オブジェクトのみがページに表示されます。最上位の親オブジェクトまで、階層全体が表示されるわけではありません。 ディテール・オブジェクトをツリー・オブジェクトまたはツリー表オブジェクトとして表示すると、複数のレベルからなる階層全体を、最上位のマスター・オブジェクトから各ノードの子ディテール・オブジェクトまで表示できます。 |
「データ・コントロール」パネルを使用して、マスター/ディテール・データを表示するページを宣言的に作成できます。「データ・コントロール」パネルでは、マスター/ディテール関係にあるオブジェクトが階層に表示されます。この階層は、ディテール・オブジェクトがマスター・オブジェクトの子となるデータ・モデルを表したものです。
マスター/ディテール・オブジェクトをフォーム・オブジェクトまたは表オブジェクトとして表示するには、「データ・コントロール」パネルからディテール・オブジェクトをドラッグし、ページにドロップします。マスター・オブジェクトは、ページ上に自動的に作成されます。
図5-2は、「データ・コントロール」パネルに表示された、マスター/ディテール関係にある2つのアクセッサ戻りコレクションを示しています。ProductImageList
がProductFindAll
の子として表示されています。
注意: 「データ・コントロール」パネルに表示されるマスター/ディテール階層には、関係のカーディナリティ(1対多、1対1、多対多)は反映されません。この階層は単に、どのアクセッサ戻りコレクション(マスター)を使用して別のアクセッサ戻りコレクション(ディテール)から1つ以上のオブジェクトを取得しているかを示します。 |
この例では、ProductFindAll
とProductImageList
の関係は一方向関係です。
「データ・コントロール」パネルを使用すると、マスター/ディテール参照ページを単一の宣言的アクションで作成できます。そのために必要な操作は、ディテールのアクセッサ戻りコレクションをページにドロップして、使用するウィジェットのタイプを選択することのみです。
「データ・コントロール」パネルで使用できる事前作成済のマスター/ディテール・ウィジェットには、コレクション内のデータ・オブジェクトをエンド・ユーザーがスクロールできるレンジ・ナビゲーションが含まれます。テキスト・フィールドまたは列をページから削除すると、不要な属性を削除できます。
図5-3に、事前作成済のマスター/ディテール・ウィジェットの例を示します。このウィジェットでは、ページ上部のフォームに商品情報が表示され、ページ下部の表に在庫レベルが表示されています。ユーザーが「次へ」ボタンをクリックし、ページ上部のマスター・データのレコードをスクロールすると、関連するディテール・データが自動的にページに表示されます。
事前作成済のマスター/ディテール・ウィジェットを使用しない場合、マスター・オブジェクトとディテール・オブジェクトを表やフォームとして、「データ・コントロール」パネルから単一のページまたは別々のページに1つずつドラッグ・アンド・ドロップできます。
「データ・コントロール」パネルで事前作成済のマスター/ディテール・フォームおよび表を使用すると、単一の宣言的アクションで、マスター・ウィジェットとディテール・ウィジェットの両方を1つのページ上に作成できます。
事前作成済のADFマスター/ディテール・フォームおよび表を使用したマスター/ディテール・ページを作成する手順:
「データ・コントロール」パネルでディテール・オブジェクトを特定します。
ディテール・オブジェクトをJSFページにドラッグ・アンド・ドロップします。
注意: 編集可能なマスター/ディテール・フォームを作成する場合は、マスター・オブジェクトとディテール・オブジェクトを別々にページにドロップします。 |
ポップアップ・メニューから、次のいずれかのマスター/ディテールUIコンポーネントを選択します。
ADFマスター表、ディテール・フォーム: 表にマスター・オブジェクトが表示され、表の下にある読取り専用フォームにディテール・オブジェクトが表示されます。
マスター表で特定のデータ・オブジェクトを選択すると、その下にあるフォーム内に、関連する最初のディテール・データ・オブジェクトが表示されます。後続の各ディテール・データ・オブジェクトをスクロールするには、フォーム・ナビゲーションを使用する必要があります。
ADFマスター・フォーム、ディテール表: マスター・オブジェクトが読取り専用フォームに表示され、ディテール・オブジェクトがフォームの下にある読取り専用表に表示されます。
フォームに特定のマスター・データ・オブジェクトを表示すると、その下にある表に、関連するディテール・データ・オブジェクトが表示されます。
ADFマスター・フォーム、ディテール・フォーム: マスター・オブジェクトとディテール・オブジェクトが別々のフォームに表示されます。
上のフォームに特定のマスター・データ・オブジェクトを表示すると、その下にあるフォームに、関連する最初のディテール・オブジェクトが表示されます。後続の各ディテール・データ・オブジェクトをスクロールするには、フォーム・ナビゲーションを使用する必要があります。
ADFマスター表、ディテール表: マスター・オブジェクトとディテール・オブジェクトが別々の表に表示されます。
上の表で特定のマスター・データ・オブジェクトを選択すると、その下にある表に、関連する最初のディテール・データ・オブジェクトのセットが表示されます。
「データ・コントロール」パネルからアクセッサ戻りコレクションをドラッグ・アンド・ドロップすると、様々な処理が自動的に行われます。たとえば、JSFページにコードが追加され、ページ定義ファイルに対応するエントリが追加されます。
事前作成済のマスター/ディテール・ウィジェット用に生成されたJSFコードは、「データ・コントロール」パネルを使用して読取り専用のフォームまたは表を作成したときに生成されるJSFコードとほぼ同じです。独自のマスター/ディテール・ウィジェットを作成する場合、事前作成済のマスター/ディテール表およびフォームに自動的に組み込まれるものと同様のコンポーネントを組み込むことを検討してください。
事前作成済のマスター/ディテール・ウィジェットの表およびフォームにはpanelHeader
タグがあります。このタグには、フォームまたは表にデータを移入するデータ・オブジェクトの完全修飾名が含まれています。このラベルは、リソース・バンドルにバインドする文字列またはEL式を使用して、必要に応じて変更できます。
コレクション内に複数のデータ・オブジェクトがある場合、事前作成済のマスター/ディテール・ウィジェットのフォームには、レンジ・ナビゲーション用としてFirst
、Previous
、Next
およびLast
という4つのcommandButton
タグがあります。これらのレンジ・ナビゲーション・ボタンを使用して、コレクション内のデータ・オブジェクトをスクロールできます。各ボタンのactionListener
属性は、ナビゲーションを実行するデータ・コントロール操作にバインドされています。ボタンをクリックすると、actionListener
バインディングで使用されるexecute
プロパティによって、操作が起動します。(フォームに単一のデータ・オブジェクトが表示されている場合、レンジ・ナビゲーション・コンポーネントは表示されません。)
ヒント: ページに「ADFマスター表、ディテール・フォーム」ウィジェットまたは「ADFマスター表、ディテール表」ウィジェットをドロップすると、ディテール・コンポーネントの親タグ(panelHeader タグやtable タグなど)のpartialTriggers 属性は自動的にマスター・コンポーネントのid に設定されます。実行時に、ユーザーがマスター・コンポーネントで選択を行うと、partialTriggers 属性により、ディテール・コンポーネントのみが再度レンダリングされます。これは、部分レンダリングと呼ばれます。マスター・コンポーネントが表であるときは、部分レンダリングが使用されます。これは、ユーザーがファセット内で選択を行うだけの場合、表を再度レンダリングする必要がないためです。新しいデータを表示するために再度レンダリングする必要があるのはディテール・コンポーネントのみです。 |
例5-1に、マスター/ディテール・ページ用に作成されたページ定義ファイルを示します。このマスター/ディテール・ページは、ProductFindAll
オブジェクトの下位のディテール・オブジェクトであるWarehouseStockLevelList
をADFマスター・フォーム、ディテール表としてページにドロップして作成したものです。
executables
要素は2つのaccessorIterator
を定義しています。1つは商品(マスター・オブジェクト)に対するもの、もう1つはWarehouseStockLevel
(ディテール・オブジェクト)に対するものです。実行時には、UI対応のデータ・モデルと行セット・イテレータにより、現在の行が変更されたときに、ディテール・コレクションの行セットが現在のマスター行の正しい行セットになるようにリフレッシュされます。
bindings
要素は、値バインディングを定義します。フォーム内のテキスト・フィールドにデータを移入する属性バインディングは、attributeValues
要素内で定義されます。attributeValues
要素のid
属性には各データ属性の名前が含まれ、IterBinding
属性はイテレータ・バインディングを参照し、マスター・オブジェクトのデータをテキスト・フィールドに表示します。
フォーム内のテキスト・フィールドにデータを移入する属性バインディングは、attributeValues
要素内で定義されます。attributeValues
要素のid
属性には各データ属性の名前が含まれ、IterBinding
属性はイテレータ・バインディングを参照し、マスター・オブジェクトのデータをテキスト・フィールドに表示します。
フォーム内のレンジ・ナビゲーション・ボタンは、action
要素で定義されたアクション・バインディングにバインドされます。属性バインディングの場合と同様、アクション・バインディングのIterBinding
属性は、マスター・オブジェクトのイテレータ・バインディングを参照します。
ディテール・データを表示する表は、table
要素で定義される表バインディング・オブジェクトにバインドされます。IterBinding
属性は、ディテール・オブジェクトのイテレータ・バインディングを参照します。
例5-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"/> <accessorIterator MasterBinding="productFindAllIterator" Binds="warehouseStockLevelList" RangeSize="25" DataControl="SupplierFacadeLocal" BeanClass="oracle.fodemo.supplier.model.WarehouseStockLevel" id="warehouseStockLevelListIterator"/> </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="productFindAllIterator" id="productFindAll"> <nodeDefinition DefName="oracle.fodemo.supplier.model.Product"> <AttrNames> <Item Value="attributeCategory"/> <Item Value="listPrice"/> <Item Value="minPrice"/> <Item Value="objectVersionId"/> <Item Value="productId"/> <Item Value="productName"/> <Item Value="productStatus"/> </AttrNames> </nodeDefinition> </tree> <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>
実行時に、ADFイテレータは、マスター表オブジェクトのどの行をマスター/ディテール・フォームに表示するかを決定します。フォームが最初に表示されるときは、マスター表オブジェクトの1行目がフォームのマスター・セクションに強調表示されます。マスター行に関連付けられているディテール表の行は、フォームのディテール・セクションに表示されます。
5.3.2.2項「ページ定義ファイルで定義されるバインディング・オブジェクト」で説明しているように、ADFイテレータは基礎となるrowsetIterator
オブジェクトに関連付けられています。これらのイテレータは、ページに現在表示されているデータ・オブジェクト(つまり行)がどれかを管理します。実行時には、行セット・イテレータがマスター・コンポーネントとディテール・コンポーネントに表示されるデータを管理します。
マスターおよびディテールの行セット・イテレータは、どちらも行セット・ナビゲーション・イベント(ユーザーによるレンジ・ナビゲーション・ボタンのクリックなど)をリスニングし、適切な行をUIに表示します。デフォルトのマスター/ディテール・コンポーネントの場合は、行セット・ナビゲーション・イベントは、フォーム上のコマンド・ボタン(「先頭へ」、「前へ」、「次へ」、「最後へ」)になります。
ディテール・コレクションの行セット・イテレータは、ディテール・データとマスター・データの同期化を管理します。ディテール行セット・イテレータは、マスター・コレクションとディテール・コレクションの両方で行ナビゲーション・イベントをリスニングします。マスター・コレクションで行セット・ナビゲーション・イベントが発生すると、ディテール行セット・イテレータが自動的に実行され、現在のマスター行に関連するディテール行が戻されます。
デフォルトのマスター/ディテール・コンポーネントでは、マスター/ディテール・データは単一のページに表示されます。ただし、「データ・コントロール」パネルでマスター・オブジェクトとディテール・オブジェクトを使用して、バインディング・イテレータにマスター・オブジェクトとディテール・オブジェクトの同期化を管理させたまま、コレクションを別々のページに表示することもできます。
マスター/ディテール・オブジェクトを別々のページに表示するには、マスター・オブジェクト用として1ページ、ディテール・オブジェクト用として1ページの、計2ページを作成します。その際には、「データ・コントロール」パネルから使用できる、個々の表またはフォームを使用します。前述のように、ディテール・オブジェクト・イテレータは、マスターとディテールのデータの同期化を管理します。ディテール・データを表示するページを作成する際には、必ず「データ・コントロール」パネルから適切なディテール・オブジェクトをドラッグしてください。詳細は、5.2項「「データ・コントロール」パネルでのマスター/ディテール・オブジェクトの識別」を参照してください。
ページ・ナビゲーションを処理するには、ADFタスク・フローを作成し、マスター・ページ用として1つ、ディテール・ページ用として1つの、計2つのビュー・アクティビティを追加します。コマンド・ボタンまたはリンクを各ページに追加するか、「データ・コントロール」パネルを使用してフォームまたは表を作成するときに使用可能なデフォルトの「発行」ボタンを使用します。各ボタンについて、action
属性内で、ナビゲーション・ルールの結果値を指定する必要があります。task-flow-defintion.xml
ファイルで、マスター・データ・ページからディテール・データ・ページへのナビゲーション・ルール、およびディテール・データ・ページからマスター・データ・ページに戻るための別のルールを追加します。ナビゲーション・ルール内のfrom-outcome
の値は、ボタンのaction属性で指定された結果値と一致する必要があります。
表とフォーム以外に、階層ツリーにもマスター/ディテール・データを表示できます。ADF Facesのtree
コンポーネントは階層データの表示に使用します。マスター・オブジェクトのバインディングによってデータが移入される複数のルート・ノードを表示できます。ツリー内の各ルート・ノードは、ディテール・オブジェクトのバインディングによってデータが移入されるブランチを持つことが可能で、その数に制限はありません。ツリーには複数のレベルのノードがあり、各ノードは親ノードのディテール・オブジェクトを示します。ツリー内の各ノードは、階層内のノードのレベルがわかるようにインデント表示されます。
tree
コンポーネントには、ツリー・ノードを開閉するメカニズムが含まれていますが、フォーカス機能はありません。フォーカス機能を使用する必要がある場合は、ADF FacesのtreeTable
コンポーネントの使用を検討してください(詳細は、5.5項「ツリー表を使用したマスター/ディテール・オブジェクトの表示」を参照)。デフォルトでは、ツリーの各ノードのアイコンはフォルダですが、独自のアイコンを階層内の各レベルのノードに使用できます。
図5-4は、ルートとブランチという2つのレベルのノードを表示するツリーの例を示しています。ルート・ノードには「Media」、「Office」、「Electronics」などの親商品カテゴリが表示されます。ブランチ・ノードには、「Office」親カテゴリの下の「Hardware」、「Supplies」、「Software」のような、各親カテゴリの下のサブカテゴリが表示されます。
ツリーはノードの階層で構成され、各サブノードは上位レベルのノードから分岐します。データバインドされたADF Facesのtree
コンポーネントの各ノード・レベルには、異なるデータ・コレクションによってデータが移入されます。JDeveloperでは、「ツリー・バインディングの編集」ダイアログを使用してデータバインド・ツリーを定義します。このダイアログで、ツリー内の各ノード・レベルにデータを移入するためのルールを定義できます。階層内の各ノード・レベルに対して1つのルールが必要です。各ルールで、次のノード・レベル・プロパティを定義します。
そのノード・レベルにデータを移入するアクセッサ戻りコレクション
そのノード・レベルで表示される、アクセッサ戻りコレクションの属性
ツリーにマスター/ディテール・オブジェクトを表示する手順:
「データ・コントロール」パネルからマスター・オブジェクトをドラッグし、ページにドロップします。これは、ツリーのルート・レベルを表すマスター・データである必要があります。
ポップアップ・メニューから、「ツリー」→「ADFツリー」を選択します。
図5-5に示す「ツリー・バインディングの編集」ダイアログが表示されます。バインディング・エディタを使用し、ツリーに表示する各レベルのルールを定義します。
「ルート・データソース」ドロップダウン・リストで、ルート・ノード・レベルにデータを移入するアクセッサ戻りコレクションを選択します。
これがマスター・データ・コレクションとなります。デフォルトでは、これはツリーを作成するために「データ・コントロール」パネルからドラッグしたものと同じコレクション(マスター・コレクション)です。
ヒント: 目的のアクセッサ戻りコレクションが「ルート・データソース」リストに見つからない場合は、「追加」ボタンをクリックします。「データソースの追加」ダイアログで、データ・コントロールとイテレータ名を選択して新しいデータソースを作成します。 |
「追加」アイコンをクリックし、選択したルート・データソースを「ツリー・レベル・ルール」リストに追加します。
「ツリー・レベル・ルール」リストで、追加したデータソースを選択します。
「使用可能な属性」リストで属性を選択し、「属性の表示」リストに移動します。
この属性はマスター・レベルのノードの表示に使用されます。
マスター・レベルのルールを定義したら、次にツリー内のマスター・レベルの下に表示されるディテール・レベルに対して2つ目のルールを定義する必要があります。
2つ目のルールを追加するには、「ツリー・レベル・ルール」リストの上の「追加」アイコンをクリックします。
図5-6に示すように、マスター・データソースの下にディテール・データソースが自動的に表示されます。
たとえば、マスターのルート・データソースとしてProductFindAll
を指定すると、「ツリー・レベル・ルール」リストの下にWarehouseStockLevelList
が自動的に表示されます。これは、2つのデータソースがマスター/ディテール関係にあるためです。
再帰的なマスター/ディテール階層を持つツリーを作成する場合は、データソースとセルフアクセッサを指定したルールを定義するだけで済みます。再帰的なツリーには、単一のコレクションに基づいてルート・ノードが表示されるとともに、そのコレクションからデータを繰返しフェッチするセルフアクセッサの属性から、子ノードが表示されます。再帰的なツリーは、ツリーのブランチを定義するためのルールが1つしか必要ないため、通常のマスター/ディテール・ツリーとは異なります。再帰的なデータソースは、図5-7に示すように、データソースの後にセルフアクセッサ名をカッコで囲んで指定した形で表示されます。
たとえば、EmployeesView
で定義されたコレクションでは、各ブランチのルート・ノードを従業員のManagerId
で指定できます。その場合、セルフアクセッサDirectReports
で指定されたとおり、同じブランチの子ノードはManagerId
に関連する従業員になります。
「OK」をクリックします。
「ツリー・レベル・ルール」リストにデータソースを追加し、ツリーに表示されるノード数を増やすこともできます。残りのデータソースの順序は、ツリーに表示するノードの階層に従う必要があります。
「データ・コントロール」パネルからドラッグ・アンド・ドロップすると、様々な処理が自動的に行われます。
「データ・コントロール」パネルを使用してデータバインド・ツリーを作成すると、ページ定義ファイルにバインディング・オブジェクトが追加され、JSFページにtreeタグが追加されます。作成されたUIコンポーネントは、そのままで十分機能するため、変更する必要はありません。
例5-2は、「データ・コントロール」パネルを使用してツリーを作成したときにJSFページで生成されるコードを示しています。このサンプル・ツリーには、注文番号がルート・ノードとして、商品名がリーフ・ノードとして表示されます。
例5-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のtableコンポーネントに対して行がレンダリングされるのと同様の方法で、nodeStamp
ファセットが繰返しレンダリングされます。
ADF Facesのtree
コンポーネントは、oracle.adf.view.faces.model.PathSet
クラスのインスタンスを使用して、開いた状態のノードを表示します。このインスタンスは、コンポーネントのtreeState
属性として格納されます。このインスタンスを使用して、階層での要素の開閉状態をプログラム的に管理できます。PathSet
インスタンスに含まれるすべての要素は、開いた状態とみなされます。その他のすべての要素は閉じた状態です。
例5-3は、ADFデータバインド・ツリー用にページ定義ファイルで定義されたバインディング・オブジェクトを示しています。
例5-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
要素があり、各要素には次の属性およびサブ要素が含まれます。
id
: ノードの名前を定義する属性
ページ定義ファイルでのnodeDefintion
要素の順序によって、ツリーでのノードの順序またはレベルが決まります。先頭のnodeDefinition
要素は、ルート・ノードを定義します。後続の各nodeDefinition
要素は、その前にあるノードのサブノードを定義します。
tree
コンポーネントは、org.apache.myfaces.trinidad.model.TreeModel
を使用してデータにアクセスします。このクラスは、ADF Facesのtable
コンポーネントがデータへのアクセスに使用するCollectionModel
を拡張します。TreeModel
クラスの詳細は、ADF Faces Javadocを参照してください。
tree
を含むページが表示されると、ツリーのイテレータ・バインディングによって、ルート・ノードにデータが移入されます。ユーザーがノードを開いてブランチを表示したり、閉じて非表示にすると、DisclosureEvent
イベントが送信されます。このイベントのisExpanded
メソッドは、ユーザーの操作に基づいてノードを開くか閉じるかを判断します。DisclosureEvent
イベントには、リスナーが関連付けられています。
tree
のDisclosureListener
属性は、ページ定義ファイルで定義済のノード・ルールで指定されたアクセッサ属性にバインドされます。このアクセッサ属性は、DisclosureEvent
イベントに応じて起動します。つまり、ユーザーがノードを開くたびに、アクセッサ属性によってブランチ・ノードにデータが移入されます。
ADF FacesのtreeTable
コンポーネントを使用すると、マスター/ディテール・コレクションの階層を表に表示できます。tree
コンポーネントのかわりにtreeTable
コンポーネントを使用することの利点は、treeTable
コンポーネントがツリー内の特定のノードにフォーカスして表示するメカニズムを使用できることです。
たとえば、国、州または地方、都市という3つのノード・レベルを表示するツリー表を作成できます。各ルート・ノードは、個別の国を表します。各ルート・ノードが分岐して、その国の州または地方が表示されます。各州または地方のノードが分岐して、その中の都市を表示します。
ツリーの場合と同様、複数のノードがあるツリー表を作成するには、コレクションにマスター/ディテール関係を持たせる必要があります。たとえば、国、州、都市という3つのレベルを持つツリー表を作成するには、CountryCodes
コレクションからStatesandProvinces
コレクションへのマスター/ディテール関係、およびStatesandProvinces
コレクションからCities
コレクションへのマスター/ディテール関係が必要です。
データバインドされたADF FacesのtreeTable
には、一度に1つのルート・ノードしか表示されませんが、様々なルート・ノードをスクロールするためのナビゲーションが用意されています。また、各ルート・ノードに表示されるブランチの数は制限されません。すべてのノードは表内で個別の行として表示され、各行の左端の列には、フォーカス・メカニズムが用意されています。
プロパティ・インスペクタで、次のtreeTable
コンポーネント・プロパティを編集できます。
レンジ・ナビゲーション: ユーザーは、「前へ」および「次へ」のナビゲーション・ボタンをクリックして、ルート・ノードをスクロールできます。
リスト・ナビゲーション: 「前へ」ボタンと「次へ」ボタンの間にあるリスト・ナビゲーションにより、ユーザーは、選択リストを使用してデータ・コレクション内の特定のルート・ノードに移動できます。
ノードを開閉するためのメカニズム: ユーザーは、それぞれのノードを個別に開閉するか、「すべて開く」または「すべて閉じる」のコマンド・リンクを使用できます。デフォルトでは、個々のノードを開閉するためのアイコンは、プラス記号またはマイナス記号が表示された矢印です。カスタム・アイコンを選択して使用することもできます。
フォーカス・メカニズム: ユーザーがノードの横(左端の列)のフォーカス・アイコンをクリックすると、ページが再表示され、ノードとそのブランチのみが表示されます。親ノードに戻るためのナビゲーション・リンクも表示されます。
ADF Facesデータバインド・ツリー表の作成手順は、ADF Facesデータバインド・ツリーの作成手順とほぼ同じですが、アクセッサ戻りコレクションをドロップする際に、ADFツリーとしてではなくADFツリー表としてドロップします。
「データ・コントロール」パネルからドラッグ・アンド・ドロップすると、様々な処理が自動的に行われます。
「データ・コントロール」パネルを使用してデータバインド・ツリー表を作成すると、ページ定義ファイルにバインディング・オブジェクトが追加され、JSFページにtreeTable
タグが追加されます。作成されたUIコンポーネントは、そのままで十分機能するため、変更する必要はありません。
例5-4は、「データ・コントロール」パネルを使用してツリー表を作成したときにJSFページで生成されるコードを示しています。このサンプル・ツリー表には、商品と在庫レベルという2つのノード・レベルが表示されます。
デフォルトでは、フォームの中にtreeTable
タグが作成されます。tree
tableタグのvalue
属性には、tree
コンポーネントを、データ移入を行うバインディング・オブジェクトにバインドするEL式が含まれます。treeModel
プロパティは、基礎となるデータ・モデルに基づいてtree階層の表示方法を定義する、ADFクラスを参照します。var
属性は、現在のノードにアクセスできるようにします。
例5-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
ファセットは、各ノードのデータを表示するために使用されます。treeでは、ノードごとにコンポーネントを持つかわりに、ADF Facesのtable
コンポーネントに対して行がレンダリングされるのと同様の方法で、nodeStamp
ファセットが繰返しレンダリングされます。pathStamp
ファセットは、ユーザーがディテール・ノードにフォーカスした後で親ノードに戻れるように、表の上に列およびパスのリンクをレンダリングします。
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のtable
コンポーネントと同様に、treeTable
コンポーネントでは、レンジ・ナビゲーションを使用できます。ただし、treeTable
コンポーネントでは、rows
属性のかわりにrowsByDepth
属性が使用されます。この属性の値は、スペースで区切られた正数のリストです。それぞれの数字は、ツリー上のノード・レベルのレンジ・サイズを定義します。最初の数字はツリーのルート・ノードで、最後の数字はブランチ・ノードに対応します。ツリーのブランチの数がrowsByDepth
属性に含まれる数字より多い場合は、残りのブランチに対して、リストの最後の数字が使用されます。各数字は、各ブランチに一度に表示される項目数の制限を定義します。ブランチにすべての項目を表示するには、リストの対応する位置で0
を指定します。
たとえば、rowsByDepth
属性が0 0 3
に設定されている場合、ルート・ノードおよびその直下にある子はすべて表示されますが、それより下は、ブランチごとに3つのノードしか表示されません。ただし、treeTable
コンポーネントには追加のノードに移動するためのリンクが含まれるため、ユーザーは追加のノードを表示できます。
ADF FacesのtreeTable
コンポーネントの詳細は、ADF Faces Javadocのoracle.adf.view.faces.component.core.data.CoreTreeTable
クラスを参照してください。
ページ定義エディタでノード・バインディングを展開すると、ページのnode Definition
要素を表示できます。これらは、ツリー・バインディング・ダイアログで構成できる同じツリー・バインディング・ルールです。
ノード定義(ルール)ごとに、オプションのTargetIterator
プロパティを指定できます。その値は、ユーザーがツリーで行を選択すると、実行時に評価されるEL式です。このEL式は、現在のバインディング・コンテナ内のイテレータ・バインディングを評価します。イテレータ・バインディングの行キーの属性は、ツリー用にnodeDefinition
タイプの行が取得されるイテレータの行キーと(数値、データ型の順で)一致します。
実行時に、ツリー・コントロールはselectionChanged
イベントを受け取ると、ツリーのレベルごとにキーのリストを渡します。これらのキーは選択されたノードを一意に識別します。
ツリー・バインディングは、ツリーの最上位から始まります。現在選択されているツリー・ノード・キー
のリストにキーが存在するツリー・レベルごとに、そのnodeDefinition
について構成されているTargetIterator
プロパティがある場合、ツリー・バインディングは選択されたターゲット・イテレータに対してsetCurrentRowWithKey()
操作を実行します。現在選択されているツリー・ノード・キー
のリストの適切なレベルからキーを使用します。
アプリケーションでなんらかの処理を行うために、ツリーまたはツリー表で選択されているノードを判別する必要が生じることがあります。たとえば、ユーザーが「参照」ツリーでカテゴリ・ノードを選択すると、選択イベントが起動します。このイベントに関連付けられているリスナーは、選択されたノードの商品カテゴリを判別し、その値に一致するカテゴリ属性を持つ商品をすべて戻す必要があります。
選択イベントをプログラム的に使用するには、選択イベントを処理して必要なロジックを実行するリスナーを、マネージドBean内に作成する必要があります。その後、ツリーまたは表のselectionListener
属性をそのリスナーにバインドする必要があります。
ツリーおよび表で選択イベントを使用する手順:
必要なリスナーを格納するマネージドBeanがまだ存在しない場合は、作成します。
マネージドBeanのリスナー・メソッドを作成します。リスナー・メソッドの作成の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』のADF Facesサーバー・イベントの使用に関する項を参照してください。リスナーは次の処理を実行する必要があります。
イベント・ソースを使用してコンポーネントにアクセスします。例5-5は、HomeBean
マネージドBeanのproductCategoriesTreeSelectionListener
メソッドが、選択イベントを起動したツリーにアクセスする方法を示しています。
例5-5 イベント・ソースの取得
public void productCategoriesTreeSelectionListener(SelectionEvent evt) { RichTree tree = (RichTree)evt.getSource();
イベント・ソース・コンポーネントの特定の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』のイベントの発生元を返す方法に関する項を参照してください。
ツリー・モデルにアクセスしてモデルの値を取得し、RowKeySet
オブジェクトを使用して現在選択されているノードを取得した後、例5-6に示すように、それをモデルの現在の行として設定します。RowKeySet
オブジェクトの詳細は、5.6.2項「実行時に行われる処理: RowKeySetオブジェクトとSelectionEventイベント」を参照してください。
次に、現在選択されている行に対して実行するロジックを追加します。たとえば、productCategoriesTreeSelectionListener
メソッドは、選択されている行の値バインディングを使用してカテゴリIDを判別した後、その値を、実行時にそのカテゴリIDを持つ商品をすべて戻す(例5-7を参照)別のメソッドのパラメータとして使用します。
例5-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();
対応するJSFページで、ツリー・コンポーネントまたは表コンポーネントを選択します。プロパティ・インスペクタで、「動作」セクションを開いて、SelectionListener
属性の値を、作成したリスナー・メソッドに設定します。ドロップダウン・メソッドの「編集」オプションを使用すると、Beanとメソッドを宣言的に選択できます。
ユーザーがツリーのノード(または表の行)を選択するたびに、コンポーネントは選択イベントを起動します。selectionEvent
イベントは、選択解除された行と選択された行をレポートします。現在の選択内容、つまり選択されている行は、RowKeySet
オブジェクトによって管理されます。このオブジェクトは、行の関連キーをキー・セットに追加、またはキーセットから削除することで、現在選択されているすべてのノードを追跡します。ユーザーが新しいノードを選択したときに、ツリーまたは表が単一選択用に構成されている場合、それまで選択されていたキーは破棄され、新たに選択されたキーが追加されます。ツリーまたは表が複数選択用に構成されている場合は、新たに選択されたキーがセットに追加されます。それまで選択されていたキーを破棄するかどうかは、ノードの選択方法によって決まります。たとえば、ユーザーが[Ctrl]キーを押した場合、新たに選択されたノードは現在のセットに追加されます。