ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド
11gリリース1 (11.1.1.7.0)
B52029-07
  目次へ移動
目次

前
 
次
 

10 表、ツリー、およびその他のコレクションベースのコンポーネントの使用

この章では、データのコレクションを反復処理し、コレクション内の各行を表示できるコンポーネントの構造化データを、ADF FacesのtabletreetreeTablelistViewおよびcarouselの各コンポーネントを使用して表示する方法について説明します。アプリケーションでFusionテクノロジ・スタックが使用される場合、データ・コントロールを使用してこれらのコンポーネントを作成できます。詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』の「ADFによるデータバインドされた表の作成」、「マスター/ディテール・データの表示」および「より複雑なページの作成」の各章を参照してください。

この章では、次の項目について説明します。

10.1 コレクションベースのコンポーネントの使用の概要

ADF Facesには、構造化データのコレクションの反復処理と表示に使用できるコンポーネントが用意されています。表示される各レコード用に子コンポーネントを含め、それらのコンポーネントを個々のレコードにバインドするかわりに、これらのコンポーネントがコレクション全体にバインドされ、各レコードの値にスタンプを設定することにより、1つのコンポーネント(outputTextコンポーネントなど)が繰り返しレンダリングされます。

たとえば、表に子の列コンポーネントが2つ含まれるとします。各列には、出力コンポーネントを使用して行の単一の属性値が表示され、4つのレコードが表示されます。データを表示するために、2つの出力コンポーネントの4セットをバインドするかわりに、表自体が4つすべてのレコードのコレクションにバインドされ、1セットの出力コンポーネントが単純に4回スタンプ設定されます。各行にスタンプが設定されると、現在行のデータが表のvar属性にコピーされ、出力コンポーネントが行の正しい値を取得できるようになります。特に、クライアント・コンポーネントでスタンプ設定がどのように機能するかの詳細は、第10.1.5項「クライアントのコレクション・コンポーネントへのアクセス」を参照してください。

例10-1に、var属性の値がrowである表のJSFコードを示します。値が変数の特定のプロパティにバインドされているため、列の各outputTextコンポーネントにより行のデータが表示されます。

例10-1 値へのアクセスにvar属性を使用する表のJSFコード

<af:table var="row" value="#{myBean.allEmployees}">
  <af:column>
    <af:outputText value="#{row.firstname}"/>
  </af:column>
  <af:column>
    af:outputText value="#{row.lastname}"/>
  </af:column>
</af:table>

コレクション・コンポーネントでは、CollectionModelクラスを使用して基礎となるコレクションのデータにアクセスします。このクラスはJSFのDataModelクラスを拡張したものですが、索引ではなく行キーに基づいて基礎となるデータの変更をサポートしています。また、ソートなど、より高度な機能もサポートします。

java.util.Listarrayおよびjavax.faces.model.DataModelなど、別のモデル・クラスも使用できます。このような別のクラスのいずれかを使用する場合は、コレクション・コンポーネントにより、インスタンスがCollectionModelクラスに自動的に変換されますが、機能は追加されません。CollectionModelクラスの詳細は、http://myfaces.apache.org/trinidad/trinidad-1_2/trinidad-api/apidocs/index.htmlにあるMyFaces TrinidadのJavadocを参照してください。


注意:

アプリケーションでFusionテクノロジ・スタックを使用する場合は、データ・コントロールを使用してコレクション・コンポーネントを作成でき、コレクション・モデルが作成されます。詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』の「ADFによるデータバインドされた表の作成」、「マスター/ディテール・データの表示」および「より複雑なページの作成」の各章を参照してください。


tableコンポーネントは単純な表データを表示します。表の各行には、データベースの1行など、コレクションのオブジェクトが1つ表示されます。列コンポーネントは、各オブジェクトの属性の値を表示します。

たとえば、図10-1に示すように、File Explorerアプリケーションの表タブでは、選択されたディレクトリのコンテンツの表示に表が使用されています。表のvalue属性は、File ExplorerデモのtableContentViewマネージドBeanのcontentTableプロパティにバインドされています。

図10-1 File Explorerアプリケーションの表コンポーネント

File Explorerの表コンポーネント

tableコンポーネントは、列のソート、1行以上の選択、選択した行でのアプリケーション定義のアクションの実行など、エンド・ユーザーに様々な機能を提供します。また、グリッド線やバンディング、行ヘッダーと列ヘッダー、列のグループにまたがる列ヘッダー、およびセル内で折り返される値の表示など、多様な表示機能も用意されています。これらの機能の多くは、すべてのコレクション・コンポーネントで使用できます。

File Explorerアプリケーションのディレクトリなどの階層データ(親子関係のあるデータ)は、ツリー・コンポーネントを使用して展開可能なツリーとして表示できます。項目は、データの親子の構造をミラー化するノードとして表示されます。トップレベルの各ノードを開いて子ノードを表示し、それを開いて、その子ノードを表示することもできます。開かれた各ノードを閉じて、子ノードを非表示にできます。図10-2に、ツリー・コンポーネントを使用して表示されているFile Explorerアプリケーションのファイル・ディレクトリを示します。

図10-2 File Explorerアプリケーションのツリー・コンポーネント

ADF Facesのツリー・コンポーネント

ツリー表コンポーネントを使用して、階層データも表示できます。ツリー表でも、展開および縮小可能な親子のノードを表示できますが、これは表形式で、ページにノードの属性値がデータの列として表示されます。たとえば、表コンポーネントを使用してディレクトリのコンテンツを表示するだけでなく、File Explorerアプリケーションには、図10-3に示すように、ツリー表コンポーネントを使用してコンテンツを表示する別のタブもあります。

図10-3 File Explorerアプリケーションのツリー表

ADF Facesのツリー表コンポーネント

ツリー・コンポーネント同様、ツリー表コンポーネントも、項目間の親子関係を表示できます。また、表コンポーネントと同じように、ツリー表コンポーネントでも列の項目の属性値を表示できます。

表、ツリーおよびツリー表をpanelCollectionコンポーネントで囲むことにより、ツールバーおよびステータス・バーを追加できます。上部のパネルには、メニューとメニュー・オプション、ツールバーとツールバー・ボタン、およびステータス・バーなど、メニュー・タイプのコンポーネントを保持するツールバーのみでなく、標準のメニュー・バーも含まれます。デフォルトで追加されているボタンおよびメニューもあります。たとえば、表、ツリーまたはツリー表をpanelCollectionコンポーネントで囲むと、表示メニューを含むツールバーが追加されます。このメニューには、表、ツリーまたはツリー表コンポーネントに固有のメニュー項目が含まれます。

図10-4に、panelCollectionコンポーネントを使用して作成されたツールバー、メニューおよびツールバー・ボタンのあるFile Explorerアプリケーションのツリー表を示します。

図10-4 パネル・コレクションを使用したTreeTable

ツールバーを保持するpanelCollection

listViewコンポーネントは表より軽量で、構造化データをリスト形式で表示できます。表とは異なり、列がないため、単純な表形式のレイアウトよりも多様なパターンでデータを表示できます。

実際のデータを表示する各コンポーネントは、1つの子listItemコンポーネントに含まれています。図10-5に、1つの子listItemコンポーネントを含むlistViewコンポーネントを示します。listItemコンポーネントには、レイアウト・コンポーネント、出力コンポーネントおよびボタン・コンポーネントが混在しています。

図10-5 listItemコンポーネントを使用して各行のデータを保持するlistViewコンポーネント

オブジェクトのリストを表示するlistViewコンポーネント

listViewコンポーネントでは、階層データも表示できます。親データにバインドされたコンポーネントがgroupHeaderStampファセットに配置されている場合、そのデータはヘッダーに表示されます。図10-6に、アルファベット文字(親データ)がヘッダーに表示され、子である個人のデータが親の下の各行に表示される様子を示します。

図10-6 階層データのグループ別表示が可能

階層データのグループ別表示が可能

カルーセル・コンポーネントは、図10-7に示すように、イメージのコレクションを回転カルーセルに表示します。ユーザーは、下部にあるスライダを使用するか、補助イメージの1つをクリックしてそのイメージを前面に移動することにより、前面のイメージを変更できます。

図10-7 ADF Facesカルーセル

カルーセル・コンポーネント

10.1.1 コンテンツの配信

コレクション・コンポーネントは仮想化されているため、サーバーのコンポーネントに存在するすべての行がクライアントに配信されて表示されるわけではありません。コレクションベースのコンポーネントは、一度に一定数の行をデータ・ソースからフェッチするように構成されます。レンダリング時にすぐにデータをコンポーネントに配信したり、利用可能な場合は、コンポーネントのシェルがレンダリングされた後に遅延フェッチできます(コンポーネントでは、利用可能な場合はデフォルトでデータがフェッチされます)。

すぐに配信する場合は、最初のリクエスト時にデータがフェッチされます。遅延配信では、ページにコレクション・コンポーネントが1つ以上含まれる場合、ページで最初に標準のライフサイクルが実行されます。ただし、最初のリクエスト時にデータがフェッチされるのではなく、特別な個別の部分ページ・レンダリング(PPR)リクエストが実行され、コンポーネントのフェッチ・サイズの値として設定された行数が戻されます。ページのレンダリング直後であるため、レンダー・レスポンス・フェーズのみがコンポーネントに対して実行され、対応するデータのフェッチおよび表示が可能になります。ユーザーのアクションにより後続のデータ・フェッチが実行される場合(別の行セットのために表をスクロールするなど)、別のPPRリクエストが実行されます。

コンテンツが使用可能なときに配信されるようにコンテンツ配信を構成すると、フレームワークでは最初のリクエストの間にデータの可用性をチェックし、使用可能であれば、そのデータがコンポーネントに送信されます。利用できない場合、データは遅延配信でロードされるため、別のPPRリクエスト時にロードされます。


パフォーマンスのヒント:

遅延の程度が高い遅いデータベース接続や、Webサービスなどのデータベース以外のデータ・ソースからのデータのフェッチなど、データ・フェッチで高コスト(遅い)の動作が予想される場合は、遅延配信を使用する必要があります。ページにコレクションベースのコンポーネント以外のコンポーネントが多数含まれている場合にも、遅延配信を使用します。遅延配信を使用すると、データが使用可能になる前に、初期ページのレイアウト・コンポーネントおよびその他のコンポーネントが最初にレンダリングされます。

ページでコレクションベースのコンポーネントが唯一のコンテキストである場合、あるいはコンポーネントから大量のデータが返される見込みがない場合は、即時配信を使用します。この場合、遅延配信を使用するよりレスポンス時間が早くなりますが(または、単に早いと感じられる場合もあります)、これは、2番目のリクエストがサーバーに送信されないためで、ユーザーのレスポンス時間が早くなり、サーバーのCPU使用率も向上します。ただし、フェッチ・ブロックとして構成された数の行のみが最初に戻されることに注意してください。遅延配信同様、ユーザーのアクションにより後続のデータ・フェッチが実行される場合は、次の行セットが配信されます。

最初のレンダリング時にデータが利用できる場合はすぐに使用し、データが最初に利用できない場合は遅延にフォールバックするなど、可能な場合は配信でさらなる柔軟な操作が可能です。


クライアントに表示されるのは、ブラウザに表示される際にページに収まる行数のみです。それ以上の行は、ユーザーがコンポーネントを垂直にスクロールしたとき(スクロールではなくページ区切りが設定されている場合は、ユーザーが別の行セットに移動したとき)にフェッチされます。コンポーネントを埋めるために1回でクライアントからサーバーにリクエストされる行数は、fetchSize属性により決定されます。表の場合のデフォルト値は25です。そのため、表の高さが低ければ、フェッチ・サイズ25はコンポーネントを埋めるのに十分です。ただし、コンポーネントの高さが高い場合、サーバーからのデータのリクエストは複数回になります。そのため、fetchSize属性は大きな数に設定しておく必要があります。たとえば、表の高さが600ピクセルで、各行の高さが18ピクセルの場合、表を埋めるのに少なくとも45行必要です。fetchSizeが25の場合、表を埋めるために、表はサーバーに対してリクエストを2回実行する必要があります。この例では、フェッチ・サイズを50に設定します。

ただし、フェッチ・サイズを大きくしすぎると、サーバーとクライアントの両方に影響を与えます。サーバーでは、データ・ソースから必要以上に行がフェッチされ、時間とメモリー使用量が増加します。クライアント側では、それらの行の処理とコンポーネントへのアタッチに時間がかかります。

デスクトップ・デバイスでは、ユーザーがデータの行をスクロールできるように、表にはスクロール・バーがデフォルトでレンダリングされます。かわりに、図10-8に示すように、scrollPolicy属性を使用して表がページ区切りになるようにして、特定の行のページにジャンプできるフッターを表示することもできます。

図10-8 ページ区切りの表

ナビゲーションを提供する表フッター

ビューポートが狭すぎて、フッター全体を表示できない場合は、図10-9に示すように、現在表示されているページとナビゲーション・ボタンのみを表示するコンパクトなフッターが表示されます。

図10-9 コンパクト・モードで表示されたページ区切りの表

コンパクト・モードで表示されたページ区切りの表

注意:

タブレット・デバイスでは、表はデフォルトでページ区切りで表示されるようにレンダリングされます。

表をページ区切りで表示するには、scrollPolicy属性とautoHeightRows属性をそれぞれpage0に設定し、表をフロー・コンテナ(子を拡大しないコンポーネント)の中に配置する必要があります。フロー・コンテナ・コンポーネントの詳細は、第8.2.1項「ジオメトリ管理およびコンポーネントの拡大」を参照してください。


スクロールするように構成された表の場合、ページに表示される行の数はfetchSize属性によって決まります。

displayRow属性を使用して、最初に表示されるデータのセットを構成することもできます。デフォルトで、データ・ソースの最初のレコードが一番上の行またはノードに表示され、後続のレコードはそれより下の行またはノードに表示されます。また、ソースの最後のレコードを最初に表示するように、コンポーネントを構成することもできます。この場合、最後のレコードはコンポーネントの下の行またはノードに表示され、ユーザーは上にスクロールして先行するレコードを表示できます。また、選択した行を表示するように、コンポーネントを構成することも可能です。これは、ユーザーがコンポーネントに移動したときに、複数のパラメータに基づいて、特定の行がプログラムで選択されるようにする場合に便利です。選択された行を表示するように構成した場合、その行は表の先頭に表示され、ユーザーは上または下にスクロールして他の行を表示できます。

10.1.2 行の選択

rowSelection属性を使用して、選択される行を、なし、単一行、または複数行のいずれかに構成できます(carouselコンポーネントの場合は複数選択はできません)。この設定により、選択された行でロジックを実行できます。たとえば、ユーザーが表の行またはツリーのノードを選択して、選択された行のデータが表示される別のページにナビゲートするコマンド・ボタンをクリックし、その値を編集できるようにするとします。


注意:

複数の選択を実行できるようにコンポーネントを構成した場合、ユーザーが行を1つ選択し、[Shift]キーを押して別の行を選択すると、間にあるすべての行が選択されます。この選択は、選択が複数のデータ・フェッチ・ブロックにまたがる場合でも保持されます。同様に、[Ctrl]キーを使用して、隣接していない行を選択することもできます。

たとえば、表が一度に25行のみフェッチするように構成されている場合に、ユーザーが100行選択すると、フレームワークにより選択が追跡されます。


コンポーネントで選択されている行(またはノード)が変更されると、コンポーネントにより選択イベントが起動されます。このイベントにより、選択解除された行や選択された行が報告されます。コンポーネントにより選択が宣言的に処理される際、選択された行でロジックを実行する必要がある場合は、それらの行にアクセスしてロジックを実行するコードを実装する必要があります。これは、マネージドBeanの選択リスナー・メソッドで実行できます。詳細は、10.2.8項「表の選択された行でのアクションの実行について」を参照してください。


パフォーマンスのヒント:

ユーザーは、マウスとスクロールバーを使用するか、キーボードの上下の矢印キーを使用して、表内を移動できます。デフォルトでは、ユーザーが行をクリックするとすぐに選択イベントが起動されます。つまり、ユーザーが矢印キーで行間を移動している場合は、ユーザーの移動に伴い、各行で選択イベントが起動されます。

ユーザーがキーを使用して表内を移動することが予想される場合は、delaySelectionEvent属性をtrueに設定すると、選択イベントが300ミリ秒遅れて起動されるようにできます。ユーザーが300ミリ秒以内に別の行に移動した場合、選択イベントは取り消されます。


10.1.3 表、ツリーおよびツリー表のデータの編集

表、ツリーまたはツリー表の実際のデータの表示に使用するコンポーネントを選択できます。たとえば、データを読取り専用にする場合は、データの表示にoutputTextコンポーネントを使用します。反対に、データを編集できるようにする場合にはinputTextコンポーネントを使用し、リストから選択する場合にはSelectOneコンポーネントを1つ使用します。これらのコンポーネントはすべて、列コンポーネントの子として配置されるか(表およびツリー表の場合)、nodeStampファセットに配置されます(ツリーの場合)。

値の編集が可能なコンポーネントを使用してデータを表示する場合、表、ツリーまたはツリー表で、すべての行を編集可能として一度に表示するか、現在アクティブな行以外をすべて読取り専用として表示するかを、editingMode属性を使用して選択できます。たとえば、図10-10は、行をすべて編集できる表を示しています。ページは、ページに追加されたコンポーネント(inputTextinputDateおよびinputComboBoxListOfValuesコンポーネントなど)を使用してレンダリングされます。

図10-10 すべての行を編集できる表

表の各セルを編集できます

図10-11に、同じ表(データの表示にinputTextinputDateおよびinputComboBoxListOfValuesコンポーネントを使用)を示しますが、アクティブな行のみに編集可能なコンポーネントを表示するように構成されています。ユーザーは、別の行をクリックして編集可能にできます(一度に編集可能にできるのは1つの行のみ)。ページを作成するために図10-10と同じ入力コンポーネントが使用されていても、編集可能でない行のデータの表示にoutputTextコンポーネントが使用されていることに注意してください。これらのコンポーネントが実際にレンダリングされるのは、アクティブな行のみです。

図10-11 表で一度に編集できるのは1行のみ

表で一度に編集できるのは1行のみです

現在アクティブな行は、表のactiveRowKey属性で決定されます。デフォルトでは、この属性の値は表で最初に表示される行です。表(またはツリーやツリー表)がリフレッシュされると、そのコンポーネントがスクロールされ、アクティブな行が表示されます(まだ表示されていない場合)。ユーザーが行をクリックしてその内容を編集すると、その行はアクティブな行になります。

編集できる行(またはノード)を1つのみにする場合、ユーザーがある行(またはノード)から次の行へ移動し、一度に1行のデータを送信(および検証)すると、表(またはツリーやツリー表)ではPPRが実行されます。すべての行を編集できるようにする場合、現在表示されている行またはノードを超えてスクロールするなど、PPRが実行されるイベントが発生するとデータが送信されます。


注意:

列には、編集可能なコンポーネントを複数使用しないでください。


編集可能なコンポーネントがすべて、クリックして編集するモードで表示されるわけではありません。たとえば、HTMLの入力要素を複数行表示するコンポーネントがこれに当たります。次のコンポーネントが含まれます。

  • SelectManyCheckbox

  • SelectManyListBox

  • SelectOneListBox

  • SelectOneRadio

  • SelectManyShuttle


パフォーマンスのヒント:

レンダリングおよびポストバック中のパフォーマンスを向上させるには、表での編集を1行のみに構成する必要があります。

一度に編集できる行を1行のみにすると、出力コンポーネントでは生成されるHTMLが入力コンポーネントよりも少ないため、ページがより早く表示されます。また、読取り専用行に対してはクライアント・コンポーネントが作成されません。ユーザーがある行から次の行へ移動すると、表(またはツリーやツリー表)でPPRが実行されるため、その行のデータのみが送信され、その結果、すべてのセルの編集が可能で、表内のすべての行の全データが一度に送信される表よりパフォーマンスが高くなります。編集できる行を1行のみにすると、単一の行のデータのみが検証用に送信されるため、より直感的な検証も可能になり、その行のエラーのみが表示されます。


10.1.4 表、ツリーおよびツリー表でのポップアップ・ダイアログの使用

表、ツリーまたはツリー表は、ユーザーのアクションに基づいてポップアップ・ダイアログが表示されるように構成できます。たとえば、ユーザーがセルまたはノード上にマウスを置いた場合に、選択された行の一部のデータが表示されるようにポップアップ・ダイアログを構成できます。ユーザーが表やツリー表の行、またはツリーのノードを右クリックした場合のために、ポップアップ・メニューを作成することも可能です。また、表やツリー表では、ユーザーが特定の行ではなく、表の任意の場所を右クリックした場合のために、ポップアップ・メニューを作成できます。

すべての表、ツリーおよびツリー表には、contextMenuファセットが含まれます。ポップアップ・メニューをこのファセットに配置すると、ユーザーが行を右クリックした場合に、関連するメニューが表示されます。サーバーでポップアップ・メニューがフェッチされると、コンポーネントにより、ポップアップ・メニューが表示されている行に対しての現行性が自動的に確立されます。現行性の確立とは、表のモデルの現行行が、ポップアップ・メニューが表示されている行を指すことです。これを実現するには、表示されるたびにメニューをフェッチできるように、メニューが含まれるpopupコンポーネントのcontentDelivery属性がlazyUncachedに設定されている必要があります。


ヒント:

選択された行に基づいて、ポップアップ・メニューにコンテンツが動的に表示されるようにするには、ポップアップ・コンテンツの配信をlazyUncachedに設定し、現在行を取得して、その現在行に基づいてデータを表示できるマネージドBeanのメソッドにsetPropertyListenerタグを追加します。

<af:tree value="#{fs.treeModel}" 
         contextMenuSelect="false" var="node" ..>
  <f:facet name="contextMenu">
    <af:popup id="myPopup" contentDelivery="lazyUncached">
      <af:setPropertyListener from="#{fs.treeModel.rowData}"
               to="#{dynamicContextMenuTable.currentTreeRowData}"
               type="popupFetch" />
      <af:menu>
       <af:menu text="Node Info (Dynamic)">
         <af:commandMenuItem actionListener=
           "#{dynamicContextMenuTable.alertTreeRowData}" 
           text=
     "Name - #{dynamicContextMenuTable.currentTreeRowData.name}" />
         <af:commandMenuItem actionListener=
           "#{dynamicContextMenuTable.alertTreeRowData}" 
           text=
     "Path - #{dynamicContextMenuTable.currentTreeRowData.path}" />
         <af:commandMenuItem actionListener=
           "#{dynamicContextMenuTable.alertTreeRowData}" 
           text="Date -
     #{dynamicContextMenuTable.currentTreeRowData.lastModified}" />
       </af:menu>
    </af:menu>
  </af:popup>
  </f:facet>
...
</af:tree>

バッキングBeanのコードは次のようになります。

public class DynamicContextMenuTableBean
{
  ...
  public void setCurrentTreeRowData(Map currentTreeRowData)
  {
    _currentTreeRowData = currentTreeRowData;
  }
 
  public Map getCurrentTreeRowData()
  {
    return _currentTreeRowData;
  }
 
  private Map _currentTreeRowData;
}

表およびツリー表には、bodyContextMenuファセットが含まれます。メニューが含まれるポップアップをこのファセットに追加すると、ユーザーが特定の行ではなく、表をクリックした場合に表示されます。

ポップアップ・メニューの作成の詳細は、13.2項「ポップアップ要素の宣言的作成」を参照してください。

10.1.5 クライアントのコレクション・コンポーネントへのアクセス

ADF Facesでは、コレクションベースのコンポーネントのコンテンツはサーバーでレンダリングされます。次のような場合には、クライアントがサーバー上のそのコンテンツにアクセスする必要があります。

  • クライアント側のアプリケーション・ロジックが、行固有のコンポーネントの状態を読み取る必要がある場合。たとえば、行の選択の変更に応じて、ページ内のその他のコンポーネント(通常はメニュー項目やツールバー・ボタン)の無効化や表示の状態をアプリケーションで更新する必要がある場合です。このロジックは、スタンプ設定されたinputHiddenコンポーネントを使用してクライアントに送信される、行固有のメタデータに依存している場合があります。これを有効化するために、アプリケーションでは、スタンプ設定されたコンポーネントから行固有の属性値を取得できる必要があります。

  • クライアント側のアプリケーション・ロジックが、行固有のコンポーネントの状態を変更する必要がある場合。たとえば、表の行にあるスタンプ設定されたコマンド・リンクをクリックすると、同じ行のその他のコンポーネントの状態が更新される場合です。

  • イベント処理動作を実装するために、ピアがコンポーネント・インスタンスにアクセスする必要がある場合(ピアの詳細は、3.1項「ADF Facesアーキテクチャの使用の概要」を参照してください)。たとえば、マウスのクリックに対応して、クライアント側のアクション・イベントを配信するには、AdfDhtmlCommandLinkPeerクラスが、イベント・ソースとして機能するコンポーネント・インスタンスを参照する必要があります。コンポーネントにも関連する状態が保持され、これには、disabledまたはpartialSubmitなど、イベント配信動作を制御する属性のみでなく、クライアント・リスナーも含まれます。

リッチ・クライアント・フレームワークでは、クライアント側でELがサポートされないのみでなく、クライアントへの表モデル全体の送信もサポートされていないため、クライアント側のコードは、値にアクセスするようスタンプ設定されたコンポーネントに依存できません。各行で同じコンポーネント・インスタンスを再利用するかわりに、各行に新しいJavaScriptクライアント・コンポーネントが作成されます(どの行にもコンポーネントが1つ作成される必要があると仮定しています)。

そのため、クライアント上の行固有のデータにアクセスするには、それ自体がスタンプ設定されたコンポーネントを使用して値にアクセスする必要があります。クライアント側のデータ・モデルを使用せずにこれを実現するには、クライアント側の選択変更リスナーを使用します。詳細な手順は、第10.12項「コレクションベースのコンポーネントからクライアント上の選択された値へのアクセス」を参照してください。

10.1.6 表、ツリーおよびツリー表コンポーネントのジオメトリ管理

デフォルトでは、子を拡大するコンポーネント(panelStretchLayout内部のpanelCollectionコンポーネントなど)に表、ツリーおよびツリー表を配置すると、表、ツリーおよびツリー表が既存の領域全体に合せて拡大されます。ただし、列を表全体に拡大するには、columnStretching属性を使用して、特定の列が未使用の領域全体に拡大されるように指定する必要があります。そうしないと、表は行の数に応じて垂直に拡大されます。図10-12に示すように、列は拡大されません。

図10-12 列以外が拡大される表

拡大された表

子を拡大しないコンポーネントに配置すると(たとえば、panelGroupLayout内部のpanelCollectionコンポーネントでverticalに設定など)、図10-13に示すように、デフォルトで表の幅が300pxに設定されます。

図10-13 拡大されない表

拡大されない表

子を拡大しないコンポーネントに表を配置する場合、autoHeightRows属性を使用すると、指定した行数を超えないように表の高さを抑えることができます。この属性を正の整数に設定すると、表の高さは設定した行数で決定されます。この数値がfetchSize属性より大きいと、fetchSize属性の行数のみが返されます。autoHeightRowsを-1(デフォルト)に設定すると、自動サイズ設定を無効にできます。

自動サイズ設定が役立つのは、子を拡大するコンポーネントと拡大しないコンポーネントの両方で同じ表を使用する場合です。たとえば、12行が表示可能な6列の表があるとします。子を拡大するコンポーネントで使用する場合は、表を利用可能な領域全体に拡大します。その表を子を拡大しないコンポーネントで使用する場合は、表の高さを修正できるようにします。ただし、表の高さを設定すると、他のコンポーネントに配置した場合に、その表は拡大されません。この問題を解決するには、autoHeightRows表は行の数に応属性を設定します(拡大するコンポーネントでは無視され、拡大しないコンポーネントでは適用されます)。


注意:

autoHeightRows属性のデフォルト値は、DEFAULT_DIMENSIONS web.xmlパラメータによって決まります。親が拡大可能な場合は必ず表コンポーネントが拡大され、そうでない場合はfetchSize属性のサイズになるようにするには、autoHeightRows属性ではなく、DEFAULT_DIMENSIONSパラメータを設定してください。autoHeightRows属性は、グローバル設定をオーバーライドする場合に設定します。

デフォルトでは、DEFAULT_DIMENSIONSは、autoHeightRowsの値が-1 (表は拡大されない)になるように設定されます。詳細は、第A.2.3.26項「レイアウトと表コンポーネントの形状管理」を参照してください。


10.2 表へのデータの表示

tableコンポーネントは、別のコンポーネントを使用して実際のデータを表示しています。tableコンポーネントの直接的な子は、columnコンポーネントである必要があります。表示されるそれぞれの列コンポーネントは、表の個別の列として表示されます。列コンポーネントには、コンテンツやイメージの表示、またはその他の機能の提供に使用されるコンポーネントが含まれます。列コンポーネントで使用可能な機能の詳細は、10.2.1項「列および列データ」を参照してください。

各列の子コンポーネントは、その列の各行のデータを表示します。列では、子コンポーネントは行ごとには作成されませんが、表では各行のレンダリングにスタンプ設定機能が使用されます。各子には、行ごとに一度スタンプが設定され、これがすべての行に対して繰り返されます。各行にスタンプが設定されると、現在行のデータが、EL式を使用して特定可能なプロパティにコピーされます。このプロパティに使用する名前を、表のvarプロパティを使用して指定します。表のレンダリングが完了したら、このプロパティは削除されるか前の値に戻ります。

このスタンプ設定動作のため、一部のコンポーネントが列内で機能しない場合があります。入力および出力コンポーネントなど、大部分のコンポーネントは問題なく機能します。セル内に複数のコンポーネントを使用する必要がある場合は、それらをpanelGroupLayoutコンポーネントでラップします。表内の表など、それ自体がスタンプ機能をサポートしているコンポーネントはサポートされていません。実行時に値が動的に決定されるコンポーネントの使用方法の詳細は、10.2.9項「表の選択コンポーネント値の動的な決定について」を参照してください。

表にdetailStampファセットを使用して、オプションで表示または非表示にできるデータを指定できます。このファセットにコンポーネントを追加すると、表の各行に、展開および縮小するためのアイコンが付いた追加の列が表示されます。ユーザーがアイコンをクリックして開くと、図10-14に示すように、ファセットに追加されたコンポーネントが表示されます。

図10-14 オプションで表示可能な追加のデータ

開くアイコンが閉じる状態に設定されている - 詳細が表示されていません。

ユーザーが開かれた状態のアイコンをクリックして閉じると、図10-15に示すように、コンポーネントが非表示になります。

図10-15 追加のデータを非表示にすることが可能

開くアイコンが開かれているため、行の詳細が表示されています

detailStampファセットの使用方法の詳細は、10.3項「表への非表示機能の追加」を参照してください。

10.2.1 列および列データ

列には、データの表示に使用されるコンポーネントが含まれます。前述したように、各項目の表示に必要な子コンポーネントは1つのみで、値は表のレンダリング時にスタンプ設定されます。列はソート可能で、ソートで大文字と小文字を区別するかどうかを構成できます(デフォルトでは大文字と小文字が区別されます)。

また、列にフィルタ要素を含めることもできます。ユーザーがフィルタに値を入力すると、フィルタに入力した値に一致するデータ・セットが戻されます。フィルタは、大文字と小文字を区別する、または大文字と小文字を区別しないように設定できます。これが許可されるように表が構成されている場合、ユーザーは列を並べ替えることもできます。列には、ヘッダー・ファセットとフッター・ファセットの両方があります。ヘッダー・ファセットは、列のヘッダー・テキスト属性のかわりに使用できるため、スタイル設定可能なコンポーネントを使用できます。フッター・ファセットは、列の下部に表示されます。たとえば、図10-16では、フッター・ファセットを使用して、2つの列の下部に合計が表示されています。戻された行数が表示可能な範囲を超えている場合、フッター・ファセットは表示されますが、ユーザーは最後の行までスクロールできます。

図10-16 列のフッター・ファセット

列のフッター・ファセット

10.2.2 表の書式設定

表コンポーネントには、ユーザーを支援する書式設定や視覚的な補助が多数用意されています。これらの機能を有効にし、どのように表示するかを指定できます。次にこれらの機能を示します。

  • 行の選択: デフォルトでは、ユーザーは実行時に行を選択できません。ページのその他の場所または別のページにおいて、行でアクションを実行するために、ユーザーが行を選択できるようにするには、rowSelection属性を設定して、表で行の選択を有効化します。表は、単一の行または複数の行を選択できるように構成できます。選択された行でプログラムを使用してアクションを実行する方法の詳細は、10.2.8項「表の選択された行でのアクションの実行について」を参照してください。

  • スクロール/ページ区切り: デスクトップ・デバイスでは、ユーザーはすべての行をスクロールできるように、デフォルトで表にスクロールバーがレンダリングされます。タブレット・デバイスでは、スクロールバーのかわりに表にページ番号が付けられ、ユーザーが特定の行のあるページにジャンプできるフッターが表示されます。デフォルトは、scrollPolicy属性を設定することで変更できます。

  • 表の高さ: 表の高さを絶対的(300ピクセルなど)に設定することも、autoHeightRows属性を使用して、一度に表示する行数に基づいて表の高さを決定することもできます。詳細は、第10.1.6項「表、ツリーおよびツリー表コンポーネントのジオメトリ管理」を参照してください。


    注意:

    表がpanelSplitterコンポーネントなどのレイアウト管理コンテナに配置されている場合は、コンテナによりサイズ設定され、autoHeightRowsは適用されません。


  • グリッド線: デフォルトで、ADF表コンポーネントには、水平および垂直の両方のグリッド線が描画されます。これらは、horizontalGridVisibleおよびverticalGridVisible属性を使用して個別に無効化できます。

  • バンディング: columnBandingInterval属性を使用して、行または列のグループが異なる背景色で交互に表示されます。これは、隣り合う行または列のグループを区別する際に役立ちます。デフォルトでは、バンディングは無効化されています。

  • 列グループ: 表の列は、列コンポーネントをネストさせることで、列グループにグループ化できます。各グループには、すべての列をリンクする独自の列グループ・ヘッダーを設定できます。

  • 編集可能セル: 表へのデータの表示に入力テキスト・コンポーネントを使用する場合は、すべてのセルを編集できるように表を構成することも、ユーザーが明示的にセルをクリックして編集するように構成することもできます。詳細は、10.1.3項「表、ツリーおよびツリー表のデータの編集」を参照してください。


    パフォーマンスのヒント:

    ユーザーがクリックした場合にのみセルの編集を可能にすると、表は最初はより早くロードされます。これは、表に大量のデータを表示する場合に便利です。


  • 列の拡大: 列の幅すべてを合せても表全体に満たない場合は、columnStretching属性を設定し、領域を埋めるために列を拡大するかどうか、拡大する場合はどの列を拡大するかを決定できます。列の最小幅を設定できるため、表の列が多い場合に、拡大を有効にすると、列は設定した最小幅よりも小さくなります。拡大する列ごとに幅の割合を設定し、拡大時に列が占める領域の量を決定できます。


    注意:

    列の最小幅の合計がビューポートの表示可能な領域以上の場合、表はビューポートの外側まで拡大し、ビューポートの外側にアクセスできるようにスクロールバーが表示されます。



    パフォーマンスのヒント:

    列の拡大はデフォルトで無効化されています。この機能を有効化すると、複雑な表(データ量の多い表や、列がネストしている表など)に使用した場合には、クライアントのレンダリング時間のパフォーマンスに影響があります。



    注意:

    ユーザーが表のスクロール可能なデータ本体にアクセスできなくなる可能性が高くなるため、行ヘッダーまたは固定されるように構成された列は拡大されません。


  • 列の選択: ユーザーにデータの列の選択を許可できます。行の選択同様、単一の列または複数の列を選択できるように構成できます。columnSelectionListenerを使用して、新しい列がユーザーによって選択された際に起動されるColumnSelectionEventに応答することもできます。このイベントにより、選択解除された列や選択された列が報告されます。

  • 列の並替え: ユーザーは、実行時に列ヘッダーをドラッグ・アンド・ドロップして列を並べ替えられます。デフォルトでは、列の並替えが許可されており、panelCollectionコンポーネントのメニュー項目で処理されます。詳細は、10.7項「表メニュー、ツールバーおよびステータス・バーの表示」を参照してください。

  • 列の固定: 列を固定し、スクロールされても見えなくならないように表を構成できます。列は、表の右側または左側に固定できます。これは、表のfreezeDirection属性で制御されます。列のfrozen属性を使用して、固定を開始する列を選択します。

10.2.3 列の書式設定

各列コンポーネントにも、ユーザーを支援する書式設定や視覚的な補助が多数用意されています。これらの機能を有効にし、どのように表示するかを指定できます。次にこれらの機能を示します。

  • 列のソート: ユーザーが、指定された列を基準とし、sortable属性を使用して昇順または降順にコンテンツをソートできるよう列を構成できます。列ヘッダーの特別なインジケータにより、ユーザーは列がソート可能であることがわかります。ユーザーがアイコンをクリックして、前にソートされていない列をソートすると、列のコンテンツは昇順でソートされます。次に同じヘッダーをクリックすると、コンテンツは降順でソートされます。

    ソートでは、デフォルトで大文字と小文字が区別されます。つまり、abcはソートされるとABCより前になります。sortStrength属性を使用すると、abcとABCが区別されずにソートされるように列を構成できます。

    表をソートできるようにするには、基礎となるデータ・モデルでもソートがサポートされている必要があります。詳細は、10.2.7項「プログラムを使用した表の列のソートの有効化について」を参照してください。

  • コンテンツの位置合せ: align属性を使用して、列内のコンテンツをstart、end、left、rightまたはcenterに位置合せできます。


    ヒント:

    アプリケーションで複数の読み方向がサポートされている場合は、leftおよびrightではなく、startおよびendを使用します。


  • 列の幅: width属性を使用して、列の幅をピクセル単位の絶対値として指定できます。列が拡大できるように構成すると、幅をパーセントとして設定することもできます。

  • 列のまたがり: colSpan属性を使用して、他の列にまたがる列を構成できます。ただし、通常は、spanの値にEL式を使用して、実際には列の特定のセルのみが複数列にまたがることができるようにします。

  • 行折返し: noWrap属性を使用し、行を越えて列のコンテンツを折り返すかどうかを定義できます。デフォルトでは、コンテンツは折り返されません。

  • 行ヘッダー: rowHeader属性を使用して、一番左の列を行ヘッダーに定義できます。その場合、一番左の列は列ヘッダーと同じ外観でレンダリングされますが、スクロールしてページから見えなくなることはありません。図10-17に、1列目が行ヘッダーとして構成されている場合に、表に部門がどのように表示されるかを示します。

    図10-17 表の行ヘッダー

    表の行ヘッダー

    行ヘッダー列の使用を選択し、行を選択できるように表を構成した場合、ユーザーが行の上にマウスを置くと、行ヘッダー列には図10-18に示すような選択矢印が表示されます。

    図10-18 行ヘッダーの選択アイコン

    行ヘッダーの選択アイコンとしての矢印

複数選択が可能な表の場合、ユーザーがマウスを押して行ヘッダーでドラッグし、隣接する行のブロックを選択できます。また、ユーザーが上下にドラッグすると、表は垂直に自動スクロールされます。


パフォーマンスのヒント:

行ヘッダーを使用すると、表がさらに複雑になり、パフォーマンスに悪影響が発生する場合があります。



ヒント:

列の並替えや列幅の変更など、ユーザーは実行時に表が表示される方法を変更できますが、アプリケーションがユーザーのカスタマイズを許可するように構成されていないかぎり、ユーザーがページを終了するとそれらの値は保持されません。詳細は、第33章「JSFページでのユーザー・カスタマイズの許可」を参照してください。


10.2.4 ページへの表の表示方法

「ADF Faces Tableの作成」ダイアログを使用して、JSFページに表を追加できます。このダイアログは、表に必要な各列へのcolumnコンポーネントの追加にも使用できます。また、EL式を使用して基礎となるモデルまたはBeanに表をバインドできます。


注意:

アプリケーションでFusionテクノロジ・スタックを使用する場合は、データ・コントロールを使用して表を作成でき、バインディングが実行されます。詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』の「ADFによるデータバインドされた表の作成」を参照してください。


ダイアログを完了して、表と列がページに追加されたら、プロパティ・インスペクタを使用して表または列の追加の属性を構成し、表イベントに対応するためにリスナーを追加できます。表のバインド先となるCollectionModelクラスを実装する必要があります。

ページに表を表示する手順:

  1. org.apache.myfaces.trinidad.model.CollectionModelクラスを拡張するJavaクラスを作成します。

    コレクション・コンポーネントでは、CollectionModelクラスを使用して基礎となるコレクションのデータにアクセスします。このクラスはJSFのDataModelクラスを拡張したものですが、索引ではなく行キーに基づいて基礎となるデータの変更をサポートしています。また、ソートなど、より高度な機能もサポートします。

    java.util.Listarrayおよびjavax.faces.model.DataModelなど、別のモデル・クラスも使用できます。このような別のクラスのいずれかを使用する場合は、コレクション・コンポーネントにより、インスタンスがCollectionModelクラスに自動的に変換されますが、機能は追加されません。CollectionModelクラスの詳細は、http://myfaces.apache.org/trinidad/trinidad-1_2/trinidad-api/apidocs/index.htmlにあるMyFaces TrinidadのJavadocを参照してください。

  2. コンポーネント・パレットの「共通コンポーネント」パネルから、「表」をドラッグ・アンド・ドロップし、「ADF Faces Tableの作成」ダイアログを開きます。

    ダイアログを使用して、既存のモデルに表をバインドします。表が有効なモデルにバインドされると、作成される列がダイアログにより自動的に表示されます。ダイアログを使用して列のheaderおよびvalue属性の値を編集し、データの表示に使用されるコンポーネントのタイプを選択します。または、手動で列を構成し、後日バインドすることもできます。ダイアログの使用方法の詳細は、[F1]を押すか「ヘルプ」をクリックします。

  3. プロパティ・インスペクタで、「共通」セクションを開きます。すでに表をモデルにバインドしてある場合は、value属性を設定します。このセクションを使用して、表固有の次の属性を設定できます。

    • rowSelection: 行を選択可能にする場合に値を設定します。有効な値はnonesinglemultipleおよびmultipleNoSelectAllです。


      注意:

      rowSelection属性がmultipleに設定されており、その表に行ヘッダーも含まれている場合は、行ヘッダーの列ヘッダーをクリックすることにより、すべての行と列を選択できます。ユーザーがすべての列と行を選択できないようにする場合は、rowSelectionmultipleNoSelectAllに設定します。


      選択された行でプログラムを使用してアクションを実行する方法の詳細は、10.2.8項「表の選択された行でのアクションの実行について」を参照してください。

    • columnSelection: 列を選択可能にする場合に値を設定します。有効な値はnonesingleおよびmultipleです。

  4. 「列」セクションを開きます。「ADF Faces Tableの作成」ダイアログを使用して表をバインドしてある場合、これらの設定を完了する必要があります。このセクションを使用して、表のバインドの変更、各行のデータへのアクセスに使用される変数名の変更、および各列に使用される表示ラベルやコンポーネントの変更を実行できます。


    ヒント:

    リストされている以外のコンポーネントを使用する場合は、プロパティ・インスペクタで任意のコンポーネントを選択し、それを手動で変更します。

    1. 構造ウィンドウで、ダイアログにより作成されたコンポーネントを右クリックします。

    2. ポップアップ・メニューから「変換」を選択します。

    3. リストから必要なコンポーネントを選択します。プロパティ・インスペクタを使用して、新しいコンポーネントを構成します。



    ヒント:

    列に複数のコンポーネントを表示する場合は、その他のコンポーネントを手動で追加し、それらをpanelGroupLayoutコンポーネントでラップします。これは次のように行います。

    1. 構造ウィンドウで、1つ目のコンポーネントを右クリックし、前に挿入または後に挿入を選択します。挿入するコンポーネントを選択します。

    2. デフォルトで、コンポーネントは縦に表示されます。1つの列内に複数のコンポーネントを隣接させて表示するには、[Shift]キーを押して、構造ウィンドウで両方のコンポーネントを選択します。選択内容を右クリックし、「囲む」を選択します。

    3. panelGroupLayoutを選択します。


  5. 「外観」セクションを開きます。このセクションを使用し、次に示す表固有の属性を設定して、表の外観を設定します。

    • width: 表の幅を指定します。割合またはピクセル数で幅を指定できます。デフォルト設定は300ピクセルです。列を拡大するように表を構成する場合(columnStretching属性を使用)は、幅をパーセントに設定する必要があります。


      ヒント:

      表が、子を拡大するコンポーネントの子である場合、この幅の設定はオーバーライドされ、表はコンテナに合うように自動的に拡大されます。コンポーネントが拡大される方法の詳細は、8.2.1項「ジオメトリ管理およびコンポーネントの拡大」を参照してください。


    • columnStretching: 列の幅すべてを合せても表全体に満たない場合は、この属性を設定し、領域を埋めるために列を拡大するかどうか、拡大する場合はどの列を拡大するかも決定できます。


      注意:

      子を拡大するコンポーネントの中に表が配置されている場合、自動的に拡大されるのは表のみです。表に合うように列を拡大する場合、列の拡大は手動で構成する必要があります。



      注意:

      ユーザーが表のスクロール可能なデータ本体にアクセスできなくなる可能性が高くなるため、行ヘッダーまたは固定されるように構成された列は拡大されません。



      パフォーマンスのヒント:

      列の拡大はデフォルトで無効化されています。この機能を有効化すると、クライアントにおける複雑な表のレンダリング時間のパフォーマンスに影響する場合があります。


      列の拡大を次のいずれかの値に設定できます。

      • blank: 空の列を自動的に挿入して拡大する場合に使用します(表の幅全体が行の背景色になります)。

      • 具体的な名前が付けられた列: 表に現在ある列を選択して拡大する列にできます。

      • last: 最後の列を、ウィンドウ内の使用されていない領域に合せて拡大する場合に使用します。

      • none: 何も拡大されないデフォルトのオプションです。パフォーマンスを最適化する場合に使用します。

      • multiple: パーセント値がwidth属性に設定されたすべての列は、その他の列がそれらの(拡大されない)幅にレンダリングされると、そのパーセントまで拡大されます。パーセント値は合計で重み付けされます。たとえば、3つの列のwidth属性を50%に設定すると、各列は、それ以外のすべての列がレンダリングされた後の残りの領域の1/3ずつになります。


      ヒント:

      ユーザーは実行時に列幅の値を変更できますが、アプリケーションが変更の永続性を使用するように構成されていないかぎり、ユーザーがページを終了するとそれらの値は保持されません。変更の永続性の有効化および使用方法の詳細は、第33章「JSFページでのユーザー・カスタマイズの許可」を参照してください。


    • horizontalGridVisible: 水平のグリッド線を描画するかどうかを指定します。

    • verticalGridVisible: 垂直のグリッド線を描画するかどうかを指定します。

    • rowBandingInterval: 色のバンディングの目的で、連続する何行で行グループを形成するかを指定します。デフォルトでは、これは0に設定されており、すべての行が同じ背景色で表示されます。別の色を使用する場合は、これを1に設定します。

    • columnBandingInterval: 列のバンディングが行われる間隔を指定します。この値により、表の列バンディングの表示が制御されます。たとえば、columnBandingIntervalが1の場合、表内にバンディングされた列が交互に表示されます。

    • filterVisible: 入力されたフィルタ基準に一致する行のみが表示されるように、表にフィルタを追加できます。フィルタ処理を許可するように表を構成する場合、大文字と小文字を区別する、または大文字と小文字を区別しないようにフィルタを設定できます。詳細は、10.4項「表でのフィルタ処理の有効化」を参照してください。

    • ScrollPolicy: デスクトップ・デバイスでは、デフォルトで表にスクロールバーがレンダリングされ、ユーザーはすべての行をスクロールできます。タブレット・デバイスでは、スクロールバーのかわりに表にページ番号が付けられ、ユーザーが特定の行のあるページにジャンプできるフッターが表示されます。このデフォルトの動作を維持するには、値をautoに設定します。表に必ずスクロールバーが表示されるようにするには、値をscrollに設定します。表で行が必ず一連のページとして表示され、各ページに移動するナビゲーションがフッターに表示されるようにするには、値をpageに設定します。


      注意:

      表をページ区切りで表示するには、scrollPolicy属性とautoHeightRows属性をそれぞれpage0に設定し、表をフロー・コンテナ(子を拡大しないコンポーネント)の中に配置する必要があります。これらの条件が満たされない場合、表にはスクロールバーが表示されます。フロー・コンテナ・コンポーネントの詳細は、第8.2.4項「ジオメトリ管理コンポーネント使用のヒント」を参照してください。


    • テキスト属性: アクセシビリティを目的とした表のサマリーや説明だけでなく、行を表示できない場合に表示されるテキストを決定するテキスト文字列を定義できます。

  6. 「動作」セクションを開きます。このセクションを使用し、次に示す表固有の属性を設定して、表の動作を構成します。

    • disableColumnReordering: デフォルトでは、panelCollectionコンポーネントにデフォルトで含まれるメニュー・オプションを使用して、実行時に列を並べ替えられます。これは、ユーザーが列の順序を変更できないように変更できます。(panelCollectionコンポーネントには、表、ツリーおよびツリー表のデフォルトのメニューとツールバー・ボタンが用意されています。詳細は、10.7項「表メニュー、ツールバーおよびステータス・バーの表示」を参照してください。)


      注意:

      ユーザーは列の順序を変更できますが、アプリケーションがユーザーのカスタマイズを許可するように構成されていないかぎり、ユーザーがページを終了するとそれらの値は保持されません。詳細は、第33章「JSFページでのユーザー・カスタマイズの許可」を参照してください。


    • FetchSize: 各データ・フェッチで戻されるブロックのサイズを設定します。デフォルトは25です。


      ヒント:

      表に合せるには何行必要であるかを判断するには、表の高さを取得して各行の高さで割ることで、fetchSize属性の値を決定する必要があります。fetchSize属性の値が小さすぎると、表を埋めるためにサーバーと何度もやりとりすることになります。値が大きすぎると、サーバーでは、データ・ソースから必要以上に行がフェッチされ、時間とメモリー使用量が増加します。クライアント側では、それらの行の処理とコンポーネントへのアタッチに時間がかかります。詳細は、10.1.1項「コンテンツの配信」を参照してください。


    • ContentDelivery: データを送信するタイミングを指定します。contentDelivery属性がimmediateに設定されている場合、コンポーネントのレンダリングと同時にデータがフェッチされます。contentDelivery属性がlazyに設定されている場合は、後続のリクエスト中にデータがフェッチされてクライアントに送信されます。属性がwhenAvailable(デフォルト)に設定されている場合は、データが利用可能かどうかレンダラでチェックされます。その場合は、コンテンツはすぐに配信されますそうでない場合は、遅延配信が使用されます。詳細は、10.1.1項「コンテンツの配信」を参照してください。

    • AutoHeightRows: 表に初期状態で表示する行の数を指定します。返された行の数がこの値を超えている場合は、スクロールバーが表示されます。表がfetchSizeと同じサイズになるようにするには、0に設定します。子を拡大するように構成された親コンテナに合せて表が拡大されるようにするには、-1を設定します(表の拡大の詳細は、第10.1.6項「表、ツリーおよびツリー表コンポーネントのジオメトリ管理」を参照)。それ以外の場合は、fetchSizeの現在の設定より小さい特定の数に設定してください。


      注意:

      autoHeightRows属性の設定について、次の点に注意してください。

      • inlineStyle属性の高さを指定しても影響を与えることはなく、AutoHeightRowsの値によってオーバーライドされます。

      • inlineStyle属性でmin-heightまたはmax-heightを指定することは推奨されず、autoHeightRows属性とは互換性がありません。

      • コンポーネントをpanelSplitterのようなレイアウト管理コンポーネントに配置すると、このコンテナによりサイズが指定されます(自動のサイズ指定は発生しません)。



      注意:

      autoHeightRows属性のデフォルト値は、DEFAULT_DIMENSIONS web.xmlパラメータによって決まります。親が拡大可能な場合は必ず表コンポーネントが拡大され、そうでない場合はfetchSize属性のサイズになるようにするには、autoHeightRows属性ではなく、DEFAULT_DIMENSIONSパラメータをautoに設定してください。

      DEFAULT_DIMENSIONSパラメータをautoに設定し、子を拡大しない親の中に表を配置する場合、autoHeightRows属性をオーバーライドする値がなければ、表の幅はAFStretchWidthスタイル・クラスから取得されます。この場合、表の幅はデフォルトで子の列コンポーネントを収容できるように拡大されます。

      autoHeightRows属性は、グローバル設定をオーバーライドする場合に設定します。

      デフォルトでは、DEFAULT_DIMENSIONSは、autoHeightRowsの値が-1 (表は拡大されない)になるように設定されます。詳細は、第A.2.3.26項「レイアウトと表コンポーネントの形状管理」を参照してください。


    • displayRow: 最初に表示される際に表に表示する行を指定します。使用可能な値は、表の上部に最初の行を表示する場合はfirst、表の下部に最後の行を表示する場合はlast(ユーザーが先行する行を表示するには上にスクロールする必要があります)、表で最初に選択された行を表示する場合はselectedです。


      注意:

      この属性が正常に機能するには、表モデルの合計の行数が把握されている必要があります。


    • displayRowKey: 最初に表示される際に表に表示する行キーを指定します。値が文字列ではない場合があるため、属性は宣言的にではなくプログラムで設定する必要があります。この属性を指定すると、displayRow属性がオーバーライドされます。


      注意:

      この属性が正常に機能するには、表モデルの合計の行数が把握されている必要があります。


    • editingMode: 編集可能なコンポーネントに、すべての行を編集可能にするか(editAll)、ユーザーが行をクリックした場合に編集可能にするか(clickToEdit)を指定します。詳細は、10.1.3項「表、ツリーおよびツリー表のデータの編集」を参照してください。


      ヒント:

      clickToEditを選択すると、アクティブな行のみを編集できます。この行は、activeRowKey属性で決定されます。デフォルトでは、表が最初にレンダリングされると、アクティブな行が最初に表示可能な行になります。ユーザーが別の行をクリックすると、その行はアクティブな行になります。この動作は、activeRowKey属性(「その他」セクションにあります)に異なる値を設定することで変更できます。


    • contextMenuSelect: ポップアップ・メニューを開くために右クリックする際に、行を選択するかどうかを指定します。trueに設定すると、行が選択されます。ポップアップ・メニューの詳細は、第13章「ポップアップ・ダイアログ、メニューおよびウィンドウの使用方法」を参照してください。

    • filterModel: filterVisibleとともに使用します。詳細は、10.4項「表でのフィルタ処理の有効化」を参照してください。

    • 様々なリスナー: 表で対応するイベントが起動された場合に実行されるメソッドにリスナーをバインドします(columnSelectionListenerは「その他」セクションにあります)。詳細は、第5章「イベントの処理」を参照してください。

  7. 「その他」セクションを開き、次の設定を行います。

    • activeRowKey: clickToEditを選択すると、アクティブな行のみを編集できます。この行は、activeRowKey属性で決定されます。デフォルトでは、表が最初にレンダリングされると、アクティブな行が最初に表示可能な行になります。ユーザーが別の行をクリックすると、その行はアクティブな行になります。この動作は、activeRowKey属性に異なる値を設定することで変更できます。

    • columnResizing: エンド・ユーザーが実行時に列幅のサイズを変更できるようにするかどうかを指定します。無効に設定されている場合、列の幅はページのレンダリング後に1回設定され、ユーザーはそれらの幅を変更できなくなります。


      ヒント:

      ユーザーは実行時に列幅の値を変更できますが、アプリケーションが変更の永続性を使用するように構成されていないかぎり、ユーザーがページを終了するとそれらの幅の値は保持されません。変更の永続性の有効化および使用方法の詳細は、第33章「JSFページでのユーザー・カスタマイズの許可」を参照してください。


    • FreezeDirection: 列を固定可能にする場合は、列を表の先頭(LTRロケールの左側)と表の末尾(LTRロケールの右側)のどちらから固定するかを指定します。固定を開始する列を、該当の列のfrozen属性を使用して構成する必要があります。

      たとえば、最初の3列を固定する場合を考えます。表のfreezeDirectionstartに設定し、3番目の列のfrozentrueに設定します。

      最後の4列を固定する場合は、freezeDirectionendに設定し、最後から4番目の列のfrozentrueに設定します。

    • SelectionEventDelay: ユーザーが上下の矢印キーを使用して表内を移動することが予想される場合は、trueに設定します。

      ユーザーは、マウスとスクロールバーを使用するか、上下の矢印キーを使用して、表内を移動できます。デフォルトでは、ユーザーが行をクリックするとすぐに選択イベントが起動されます。つまり、ユーザーが矢印キーで行間を移動している場合は、ユーザーの移動に伴い、各行で選択イベントが起動されます。

      ユーザーがキーを使用して表内を移動することが予想される場合は、delaySelectionEvent属性をtrueに設定すると、選択イベントが300ミリ秒遅れて起動されるようにできます。ユーザーが300ミリ秒以内に別の行に移動した場合、選択イベントは取り消されます。

  8. 構造ウィンドウで列を選択します。プロパティ・インスペクタで、「共通」セクションを開いて、列固有の次の属性を設定します。

    • headerText: 列のヘッダーに表示するテキストを指定します。outputTextコンポーネントを含むheaderファセットを追加する場合と等しい出力内容が生成されるため便利です。outputText以外のコンポーネントを使用する場合は、かわりに列のheaderファセットを使用する必要があります(詳細は手順13を参照してください)。headerファセットを追加すると、headerText属性の値は列ヘッダーにレンダリングされません。

    • align: この列の位置合せを指定します。左から右への表示では、左揃え、右揃え、中央揃えに、それぞれstartendおよびcenterが使用されます。表示が左から右であるか右から左であるかに関係なく、左揃えまたは右揃えのセルが必要な場合には、値leftまたはrightを使用できます。デフォルト値はnullで、これはスキンに依存し、行のヘッダー列およびデータ列の対比で異なることを示します。スキンの詳細は、第20章「スタイルおよびスキンを使用した外観のカスタマイズ」を参照してください。

    • sortable: 列をソート可能にするかどうかを指定します。ソート可能な列には、クリックするとその列のプロパティで表がソートされるヘッダーがあります。列をソート可能にするには、sortable属性をtrueに設定し、この列のプロパティによるソートが、基礎となるモデルでサポートされている必要があることに注意してください。詳細は、10.2.7項「プログラムを使用した表の列のソートの有効化について」を参照してください。


      注意:

      列の選択が有効な場合は、列ヘッダーをクリックすると、列がソートされずに選択されます。この場合、昇順/降順のソート・インジケータをクリックすると、列をソートできます。


    • SortStrength: ソート時に重要とみなされる差異のレベルを指定します。次のいずれかを選択します。

      • Primary: ソートでは文字自体が考慮されます。大文字/小文字とアクセントは無視されます。abcÁBCábcおよびABCは、abcÁBCábcABCの順(出現順)にソートされます。これは、大文字と小文字を区別しない場合に指定します。

      • Secondary: ソートでは、文字が考慮された後、アクセントがあれば、それが考慮されます。大文字/小文字は無視されます。abcÁBCábcおよびABCは、abcABCÁBCábcとソートされます。アクセントのないロケールでは、結果的に大文字と小文字を区別しない検索が行われます。

      • Tertiary: ソートでは、文字が考慮されてからアクセントが考慮され、次に大文字/小文字が考慮されます。abcÁBCábcおよびABCは、abcABCábcÁBCとソートされます。アクセントのないロケールでは、結果的に大文字と小文字を区別する検索が行われます。

      • Identical: 文字、アクセント、大文字/小文字、および他のあらゆる差異(句読点付きの単語など)が考慮されます。abcab-cÁBCábcおよびABCは、abcABCábcÁBCab-cとソートされます。これがデフォルトです。

    • filterable: 列をフィルタ処理可能にするかどうかを指定します。フィルタ処理可能な列には、列ヘッダーの上部にフィルタ・フィールドが配置されます。列をフィルタ処理可能にするには、この属性をtrueに設定し、表にfilterModel属性を設定する必要があることに注意してください。リーフ列のみがフィルタ処理可能で、フィルタ・コンポーネントは、列ヘッダーが存在する場合にのみ表示されます。この列のsortProperty属性は、filterModelクラスのfilterProperty属性のキーとして使用する必要があります。


      注意:

      フィルタ処理が有効化されている(filterable=true)列には、フィルタ基準入力フィールドとして使用する入力コンポーネントを指定できます。これを実行するには、列にフィルタ・ファセットを追加し、入力コンポーネントを追加します。詳細は、10.4項「表でのフィルタ処理の有効化」を参照してください。


  9. 「外観」セクションを開きます。このセクションを使用し、次に示す列固有の属性を使用して、列の外観を設定します。

    • displayIndex: 列の表示順序索引を指定します。列を並べ替えることが可能で、displayIndex属性に基づいて表に表示されます。displayIndex属性値が設定されていない列は、データ・ソースでの順序に基づいて最後に表示されます。親列の外にある子の列を並べ替えることはできないため、displayIndex属性はトップレベルの列にのみ適用されます。

    • width: 列の幅を指定します。

    • minimunWidth: 列幅の最低ピクセル数を指定します。ユーザーが列のサイズ変更を試行すると、この最小幅が強制されます。また、列がフレキシブルな場合にも、この最小幅より小さいサイズには縮小されません。ピクセル幅が定義されていて最小幅の方が大きい場合、最小幅は2つのうち小さい方の値になります。デフォルトで、最小幅は10ピクセルです。

    • showRequired: 対応する属性にデータが必要な場合に、列ヘッダーにアスタリスクを表示するかどうかを指定します。

    • headerNoWrapおよびnoWrap: コンテンツをヘッダーおよび列内で折り返すかどうかを指定します。

    • rowHeader: 列を表の行ヘッダーにする場合は、trueに設定します。


      パフォーマンスのヒント:

      行ヘッダーを使用すると、表がさらに複雑になり、パフォーマンスに悪影響が発生する場合があります。


  10. 「動作」セクションを開きます。このセクションを使用し、次に示す列固有の属性を使用して、列の動作を構成します。

    • sortProperty: この列によって表示されるプロパティを指定します。これは、フレームワークによって列のデータのソートに使用されるプロパティです。

    • frozen: スクロールする際に列がページから見えなくならないように、列を固定するかどうかを指定します。固定列までの表の列は、ヘッダーでロックされ、その他の列とともにスクロールされません。親を固定せずに子の列を単独で固定することはできないため、frozen属性はトップレベルの列にのみ適用されます。


      パフォーマンスのヒント:

      固定列を使用すると、表がさらに複雑になり、パフォーマンスに悪影響が発生する場合があります。


    • selected: trueに設定すると、最初のレンダリング時に列が選択されます。

  11. 列が後続の列にまたがるようにする場合は、「その他」セクションを開いてColSpanを設定します。これには、その列がまたがる列の数を設定するか、表の最後までまたがる場合はALLを設定できます。その列すべてが他の列にまたがるわけではない場合は、1つ以上の特定のセルに解決されるEL式を使用できます。

    例10-2に、ツリー表コンポーネントで親ノードのみがすべての列にまたがるようにcolSpanを設定する方法を示します。

    例10-2 親ノードが表の末尾までまたがるcolSpanの設定

    <af:column id="c1" sortable="true" sortProperty="Dname" 
               colSpan="#{testBean.container ? 'ALL' : '1'}"
               headerText="DepartmentName">
      <af:outputText value="#{node.Dname}" id="ot2"/>
    </af:column>
    

    例10-3に、対応するマネージドBeanコードを示します。

    例10-3 列のまたがりを設定するためのマネージドBeanのコード

    public class TestBean 
    {
      public boolean isContainer() 
      {
        return _treeTable.isContainer();
      }
    }
    
  12. 既存の表に列を追加するには、構造ウィンドウで表を右クリックし、ポップアップ・メニューから「表の中に挿入」「列」を選択します。

  13. 表にファセットを追加するには、表を右クリックして、ポップアップ・メニューからファセット - 表を選択し、追加するファセットのタイプを選択します。その後、ファセットに直接コンポーネントを追加できます。


    ヒント:

    ファセットに使用できる直接の子は1つのみです。ファセットに複数のコンポーネントを表示する場合は、まずグループ・コンポーネント(panelGroupLayoutなど)を挿入し、次にグループ・コンポーネントの子として複数のコンポーネントを挿入します。


  14. 列にファセットを追加するには、列を右クリックして、ポップアップ・メニューからファセット - 列を選択し、追加するファセットのタイプを選択します。その後、ファセットに直接コンポーネントを追加できます。


    ヒント:

    ファセットに使用できる直接の子は1つのみです。ファセットに複数のコンポーネントを表示する場合は、まずグループ・コンポーネント(panelGroupLayoutなど)を挿入し、次にグループ・コンポーネントの子として複数のコンポーネントを挿入します。


  15. 列にコンポーネントを子として追加し、データを表示します。

    コンポーネントの値は、表のvar属性および表示する属性の変数値セットにバインドする必要があります。たとえば、File Explorerアプリケーションの表では、var属性の値としてfileが使用されており、1列目に各行のファイル名が表示されています。そのため、ディレクトリ名の表示に使用される出力コンポーネントの値は、#{file.name}です。


    ヒント:

    列の直接の子が入力コンポーネントの場合は、その幅を列幅に適切な幅に設定してください。幅が親列にとって広すぎる大きさに設定されていると、ブラウザにより、テキスト入力カーソルが必要以上に大きく拡大され、隣接する列を隠してしまう可能性があります。たとえば、inputTextコンポーネントのサイズが80ピクセルで、その親列のサイズが20ピクセルに設定されている場合、その表の入力カーソルは、隣接する列のクリック可能領域を覆ってしまいます。

    入力コンポーネントが列の直接の子ではない場合に、サイズが自動的に設定されるようにするには、contentStyle="width:auto"を設定します。


10.2.5 ページに表を追加する場合の処理

JDeveloperを使用してページに表を追加すると、JDeveloperにより、各属性の列のある表が作成されます。表をモデルにバインドすると、列にはモデルの属性が反映されます。まだモデルにバインドしていない場合は、JDeveloperにより、デフォルト値を使用して列が作成されます。表作成ダイアログでの作業中に、または後からプロパティ・インスペクタを使用して、デフォルト値を変更(列の追加/削除、列ヘッダーの変更など)できます。

例10-4に、File Explorerアプリケーション内の表の省略形のページ・コードを示します。

例10-4 File Explorerアプリケーション内のADF Facesの表

<af:table id="folderTable" var="file"
          value="#{explorer.contentViewManager.
                                    tableContentView.contentModel}"
           binding="#{explorer.contentViewManager.
                                    tableContentView.contentTable}"
           emptyText="#{explorerBundle['global.no_row']}"
           rowselection="multiple"
           contextMenuId=":context1" contentDelivery="immediate"
           columnStretching="last"
           selectionListener="#{explorer.contentViewManager.
                              tableContentView.tableFileItem}"
           summary="table data">
  <af:column width="180" sortable="true" sortStrength="identical" 
             sortProperty="name" 
             headerText="" align="start">
    <f:facet name="header">
      <af:outputText value="#{explorerBundle['contents.name']}"/>
    </f:facet>
    <af:panelGroupLayout>
      <af:image source="#{file.icon}"
                inlineStyle="margin-right:3px; vertical-align:middle;"
                shortDesc="file icon"/>
      <af:outputText value="#{file.name}" noWrap="true"/>
    </af:panelGroupLayout>
  </af:column>
  <af:column width="70" sortable="true" sortStrength="identical"
             sortProperty="property.size">
    <f:facet name="header">
      <af:outputText value="#{explorerBundle['contents.size']}"/>
    </f:facet>
    <af:outputText value="#{file.property.size}" noWrap="true"/>
  </af:column>
...
  <af:column width="100">
    <f:facet name="header">
      <af:outputText value="#{explorerBundle['global.properties']}"/>
    </f:facet>
    <af:commandLink text="#{explorerBundle['global.properties']}"
                    partialSubmit="true"
                    action="#{explorer.launchProperties}"
                    returnListener="#{explorer.returnFromProperties}"
                    windowWidth="300" windowHeight="300"
                    useWindow="true"></af:commandLink>
  </af:column>
</af:table>

10.2.6 実行時の処理: データ配信

表を含むページがリクエストされ、コンテンツ配信がlazyに設定されている場合、ページでは最初は標準のライフサイクルが実行されます。ただし、そのリクエスト中にデータがフェッチされるのではなく、独立した特別なPPRリクエストが実行されます。ページのレンダリング直後であるため、レンダー・レスポンス・フェーズのみが実行され、対応するデータがフェッチおよび表示されます。ユーザーのアクションにより後続のデータ・フェッチが実行される場合(表のスクロールなど)、別のPPRリクエストが実行されます。図10-19に、2番目のPPRリクエスト中の表を含むページを示します。

図10-19 2番目のPPRリクエストでデータをフェッチする表

PPRリクエストでデータをフェッチする表

ユーザーがソート可能な列のヘッダーをクリックすると、tableコンポーネントによりSortEventイベントが生成されます。このイベントにはgetSortCriteriaプロパティがあり、これを使用して、ソートの強さとともに表のソートに使用する必要のある基準が返されます。表は、基礎となるCollectionModelインスタンスにsetSortCriteria()メソッドをコールしてこのイベントに対応し、登録済の任意のSortListenerインスタンスをコールします。

10.2.7 プログラムを使用した表の列のソートの有効化について

表の列のソートを有効にできるのは、基礎となるモデルでソートがサポートされている場合のみです。モデルがCollectionModelインスタンスの場合は、次のメソッドを実装する必要があります。

  • public boolean isSortable(String propertyName)

  • public List getSortCriteria()

  • public void setSortCriteria(List criteria)

2番目と3番目のメソッドの基準は、ソートの強さをサポートするorg.apache.myfaces.trinidad.model.SortCriterionのインスタンスです。

詳細は、MyFaces TrinidadのWebサイト(http://myfaces.apache.org/trinidad/index.html)を参照してください。

モデルがCollectionModelインスタンスではない場合、モデルは表コンポーネントによりラップされ、org.apache.myfaces.trinidad.model.SortableModelインスタンスになります。SortableModelは、CollectionModelを拡張する、すべてのソート機能を実装した具体クラスです。


注意:

自動サポートでは、1つの列のみのソートが提供されます。複数列のソートはサポートされていません。


10.2.8 表の選択された行でのアクションの実行について

コレクションベースのコンポーネントでは、ユーザーが1つ以上の行を選択し、その行に対してなんらかのアクションを実行できます(carouselコンポーネントでは複数選択はサポートされません)。

コンポーネントの選択状態が変更されると、選択イベントが起動されます。selectionEventイベントは、選択解除された行と選択された行をレポートします。

コンポーネントの選択イベントをリスニングするには、selectionListener属性を使用するか、addselectionListener()メソッドで表にリスナーを追加して、コンポーネントにリスナーを登録します。これにより、リスナーは選択された行にアクセスし、それらの行に対してアクションを実行できます。

RowKeySetオブジェクトは、現在の選択内容、つまり選択されている1つ以上の行であり、コンポーネントのgetSelectedRowKeys()メソッドをコールすることで取得できます。プログラムを使用して選択内容を変更するには、次のいずれかを実行します。

  • RowKeySetオブジェクトにrowKeyオブジェクトを追加するか、RowKeySetオブジェクトから削除します。

  • コンポーネントに対してsetRowIndex()またはsetRowKey()メソッドをコールして、特定の行を現在行にします。その後、RowKeySetオブジェクトに対してadd()またはremove()メソッドをコールして、その行を選択内容に追加するか、選択内容から削除できます。

例10-5に表の一部を示します(この部分では、ユーザーが複数の行を選択し、「削除」ボタンをクリックしてそれらの行を削除できます)。アクション・リスナーは、mybeanマネージドBeanのperformDeleteメソッドにバインドされます。

例10-5 行の選択

<af:table binding="#{mybean.table}" rowselection="multiple" ...>
  ...
</af:table>
<af:commandButton text="Delete" actionListener="#{mybean.performDelete}"/>

例10-6に、選択されたすべての行を反復し、それぞれにmarkForDeletionメソッドをコールするアクション・メソッドperformDeleteを示します。

例10-6 rowKeyオブジェクトの使用

public void performDelete(ActionEvent action)
{
  UIXTable table = getTable();
  Iterator selection = table.getSelectedRowKeys().iterator();
  Object oldKey = table.getRowKey();
  while(selection.hasNext())
  {
    Object rowKey = selection.next();
    table.setRowKey(rowKey);
    MyRowImpl row = (MyRowImpl) table.getRowData();
    //custom method exposed on an implementation of Row interface.
    row.markForDeletion();
  }
  // restore the old key:
  table.setRowKey(oldKey);
}
 
// Binding methods for access to the table.
public void setTable(UIXTable table) { _table = table; }
public UIXTable getTable() { return _table; }
private UIXTable _table;

10.2.9 表の選択コンポーネント値の動的な決定について

表にselectOneコンポーネントを使用する場合がありますが、各行でコンポーネントに異なる選択内容が表示される必要があります。そのため、実行時に項目のリストを動的に決定する必要があります。

個々の項目にスタンプを設定するにはforEachコンポーネントを使用する必要があると考える可能性がありますが、forEachCollectionModelインスタンスと連携しないため機能しません。また、表で使用されるようなコンポーネント管理のEL変数を使用するEL式にはバインドできません。forEachコンポーネントはJSFタグの実行ステップで関数を実行しますが、表では次に示すコンポーネントのエンコーディング・ステップで実行します。そのため、forEachコンポーネントは表の準備ができる前に実行され、反復関数は実行されません。

selectOneコンポーネントの場合、直接の子はitemsコンポーネントであることが必要です。itemsコンポーネントは行変数(<f:items value="#{row.Items}"/>など)に直接バインドできますが、こうすると、基礎となるモデルを変更できなくなります。

かわりに、例10-7に示すように、項目のリストを作成するマネージドBeanを作成します。

例10-7 項目のリストを戻すマネージドBean

public List<SelectItem> getItems()
{
   // Grab the list of items
   FacesContext context = FacesContext.getCurrentInstance();
   Object rowItemObj =  context.getApplication().evaluateExpressionGet(
      context, "#{row.items}", Object.class);
   if (rowItemObj == null)
     return null;
    // Convert the model objects into items 
   List<SomeModelObject> list =  (List<SomeModelObject>) rowItemObj;
   List<SelectItem> items = new ArrayList<SelectItem>(list.size());
   for (SomeModelObject entry : list)
   {
     items.add(new SelectItem(entry.getValue(), entry.getLabel());public
    }
    // Return the items
    return items;
}

例10-8に示すように、ページの1つのコンポーネントからリストにアクセスできます。

例10-8 JSFページからの項目へのアクセス

<af:table var="row">
  <af:column>
    <af:selectOneChoice value="#{row.myValue}">
      <f:Items value="#{page_backing.Items}"/>
    </af:selectOneChoice>
  </af:column>
</af:table>

10.2.10 イテレータ・タグの使用について

表は使用しないが、同じスタンプ設定機能が必要な場合には、イテレータ・タグを使用できます。たとえば、定期的な表要素のリストを表示し、各要素に対して名前、アトミック番号、記号およびグループを表示するとします。例10-9に示すように、イテレータ・タグを使用できます。

例10-9 イテレータ・タグの使用

<af:iterator var="row" first="3" rows="3" varStatus="stat"     
             value="#{periodicTable.tableData}" >
  <af:outputText value="#{stat.count}.Index:#{stat.index} of
                                   #{stat.model.rowCount}"/>
  <af:inputText label="Element Name" value="#{row.name}"/>
  <af:inputText label="Atomic Number" value="#{row.number}"/>
  <af:inputText label="Symbol" value="#{row.symbol}"/>
  <af:inputText label="Group" value="#{row.group}"/>
</af:iterator>

各子には、必要に応じて何度でもスタンプ設定できます。反復は、first属性で指定された索引から開始され、row属性で指定された索引まで行われます。row属性が0に設定されている場合、反復は基礎となるデータにそれ以上要素がなくなるまで続けられます。

10.3 表への非表示機能の追加

表にdetailStampファセットを使用して、表示または非表示にできるデータを指定できます。このファセットにコンポーネントを追加すると、表に、切替えアイコンが付いた追加の列が表示されます。ユーザーがアイコンをクリックすると、ファセットに追加されたコンポーネントが表示されます。ユーザーが再度切替えアイコンをクリックすると、コンポーネントが非表示になります。図10-20に、コンテンツがdetailStampファセットに追加された際に表示される追加の列を示します。


注意:

detailStampファセットを使用する表がスクリーン・リーダー・モードでレンダリングされると、そのファセットのコンテンツがポップアップ・ウィンドウに表示されます。アクセシビリティの詳細は、第22章「アクセス可能なADF Facesページの開発」を参照してください。


図10-20 detailStampファセットが表示されていない表

表示されていないdetailStampファセット

図10-21に、1行目のdetailStampファセットが表示されている同じ表を示します。

図10-21 表示されているdetailStampファセット

表示されているdetailStampファセット

注意:

列を固定できるように表を設定している場合、detailStampファセットを表示すると固定機能が働かなくなります。つまり、詳細が表示されている間、ユーザーは列を固定できません。


10.3.1 detailStampファセットの使用方法

detailStampファセットを使用するには、表示または非表示にするデータにバインドされているコンポーネントをファセットに挿入します。

detailStampファセットを使用する手順:

  1. コンポーネント・パレットで、ファセットに表示するコンポーネントをdetailStampファセット・フォルダにドラッグします。図10-22に、構造ウィンドウのdetailStampファセット・フォルダを示します。

    図10-22 構造ウィンドウのdetailStampファセット

    構造ウィンドウのdetailStampファセット

    ヒント:

    構造ウィンドウにファセット・フォルダが表示されない場合は、表を右クリックしてファセット - 表詳細スタンプを選択します。


  2. 表示する属性が現在のレコードに固有の場合は、現在のレコードのデータの表示に表の変数が使用されるように、(単純にコンポーネントが属性にバインドされる)JSFコードを置き換えます。

    例10-10に、選択した行の詳細が表示されている図10-21に示されているdetailStampファセットの表示に使用された省略形のコードを示します。

    例10-10 detailStampファセットのコード

    <af:table rowSelection="multiple" var="test1"
              value="#{tableTestData}"
      <f:facet name="detailStamp">
        <af:panelFormLayout rows="4" labelWidth="33%" fieldWidth="67%"
                            inlineStyle="width:400px">
        <af:inputText label="Name" value="#{test1.name}"/>
          <af:group>
            <af:inputText label="Size" value="#{test1.size}"/>
            <af:inputText label="Date Modified" value="#{test1.inputDate}"/>
            <af:inputText label="Created by"/>
          </af:group>
        </af:panelFormLayout>
      </f:facet>
    </af:table>
    

注意:

アプリケーションでFusionテクノロジ・スタックを使用する場合は、データ・コントロールからdetailStampファセットに属性をドラッグ・アンド・ドロップします。コードを変更する必要はありません。


10.3.2 実行時の処理: 行データの公開

ユーザーが行の詳細を表示または非表示にすると、表によりrowDisclosureEventイベントが生成されます。イベントは、詳細を切り替える(開くまたは閉じる)よう表に通知します。

rowDisclosureEventイベントには関連付けられたリスナーがあります。表のrowDisclosureListener属性は、マネージドBeanのメソッドにバインドできます。このメソッドは、必要な後処理を実行するためのrowDisclosureEventイベントへのレスポンスとして起動されます。

10.4 表でのフィルタ処理の有効化

値がフィルタに一致する行のみを表に表示するために使用できるフィルタを表に追加できます。有効化されて、表示に設定されている場合、検索可能な各列の上に検索条件入力フィールドが表示されます。

たとえば、図10-23の表は、Location値が1700の行のみを表示するようにフィルタ処理されています。

図10-23 フィルタ処理された表

フィルタ処理された表には問合せに一致する行のみが表示されています

フィルタ処理された表の検索はQuery-by-Exampleに基づいており、QBEテキストまたは日付入力フィールド書式を使用します。検索基準の変更では>および<=などの演算子の文字を入力できるようにするため、入力バリデータは無効になっています。たとえば、数値列の検索条件として>1500を入力できます。ワイルドカード文字もサポートされています。検索は、大文字と小文字を区別する、または大文字と小文字を区別しないようにできます。列でQBEがサポートされていない場合、検索条件入力フィールドはその列にレンダリングされません。

フィルタ処理機能では、データを表にフィルタ処理するためのモデルが使用されます。表のfilterModel属性オブジェクトは、FilterableQueryDescriptorクラスのインスタンスにバインドする必要があります。


注意:

アプリケーションでFusionテクノロジ・スタックを使用する場合は、データ・コントロールを使用して表を作成でき、フィルタ処理が作成されます。詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』の「ADFによるデータバインドされた表の作成」の章を参照してください。


例10-11では、フィルタ入力フィールドを有効にするために表のfilterVisible属性がtrueに設定されていて、filterModelインスタンスの列を識別するために列にsortProperty属性が設定されています。各列要素では、filterable属性がtrueに設定されています。

例10-11 フィルタ処理が有効にされている表コンポーネント

<af:table value="#{myBean.products}" var="row"
               ...
          filterVisible="true"
               ...
          rowselection="single">
               ...
  <af:column sortProperty="ProductID" filterable="true" sortable="true"
    <af:outputText value="#{row.ProductID}">
               ...
  </af:column>
  <af:column sortProperty="Name" filterable="true" sortable="true"
    <af:outputText value="#{row.Name}"/>
               ...
  </af:column>
  <af:column sortProperty="warehouse" filterable="true" sortable="true"
    <af:outputText value="#{row.warehouse}"/>
               ...
  </af:column>
</af:table>

10.4.1 表へのフィルタ処理機能の追加方法

表にフィルタ処理機能を追加するには、まずフィルタ処理機能を提供するクラスを作成します。次に表をそのクラスにバインドし、フィルタ処理機能を使用するよう表と列を構成します。フィルタ処理機能を使用する表では、headerText属性に値が設定されているか、フィルタ処理される列のheaderファセットにコンポーネントが含まれている必要があります。これにより、フィルタ・コンポーネントが表示されます。また、filterModelクラスではsortProperty属性が使用されるため、列もソート可能に構成されている必要があります。

表にフィルタ処理機能を追加する手順:

  1. FilterableQueryDescriptorクラスのサブクラスであるJavaクラスを作成します。このクラスの詳細は、ADF FacesのJavadocを参照してください。

  2. 10.2項「表へのデータの表示」で説明されているように、表を作成します。

  3. 構造ウィンドウで表を選択し、プロパティ・インスペクタで次の属性を設定します。

    • filterVisible: 検索可能な列の上にフィルタ条件入力フィールドを表示する場合はtrueに設定します。

    • filterModel: 手順1で作成したFilterableQueryDescriptorクラスのインスタンスにバインドします。


    ヒント:

    フィルタにinputTextコンポーネント以外のコンポーネント(inputDateコンポーネントなど)を使用する場合は、filterVisibletrueに設定するかわりに、filterファセットに必要なコンポーネントを追加できます。これは次のように行います。

    1. 構造ウィンドウで、フィルタ処理する列を右クリックし、「af:columnの中に挿入」「JSF Core」フィルタ・ファセットを選択します。

    2. コンポーネント・パレットから、ファセットにコンポーネントをドラッグ・アンド・ドロップします。

    3. コンポーネントの値を、手順1で作成したFilterableQueryDescriptorクラス内の対応する属性に設定します。たとえば、値には、行に使用する変数を考慮する必要があります。

      #{af:inputDate label="Select Date" id="name"
                           value="row.filterCriteria.date"}
      

  4. 構造ウィンドウで表の列を選択し、プロパティ・インスペクタで表の各列に対して次の設定を行います。

    • filterable: trueに設定します。

    • filterFeatures: caseSensitiveまたはcaseInsensitiveに設定します。指定されない場合、大文字と小文字の区別はモデルによって決定されます。

10.5 ツリーへのデータの表示

ADF Facesのツリー・コンポーネントは、組織図や階層ディレクトリ構造などの階層データを表示します。これらのタイプのデータには、一連のトップレベル・ノードがあり、構造の各要素では、展開してその他の要素を格納できます。たとえば、組織図では、階層の任意の数の従業員が任意の数の直属の部下を持つことができます。ツリー・コンポーネントを使用すると、従業員の直属の部下が子ノードとして表示される階層を表示できます。

ツリー・コンポーネントでは、複数のルート要素がサポートされています。データは構造を表す形式で表示され、各要素が適切なレベルにインデントされて階層内でのレベルを示します。ユーザーは階層の一部を展開および縮小できます。図10-24に、File Explorerアプリケーションのディレクトリの表示に使用されるツリーを示します。

図10-24 File Explorerアプリケーションのツリー・コンポーネント

ADF Facesのツリー・コンポーネント

ADF Facesのツリー・コンポーネントでは、基礎となる階層のデータにアクセスするためのモデルを使用します。特定のモデル・クラスはoracle.adf.view.rich.model.TreeModelで、10.2項「表へのデータの表示」で説明されているように、CollectionModelを拡張します。

ツリーをサポートする独自のツリー・モデルを作成する必要があります。ツリー・モデルは行のコレクションです。現在行に子の行が含まれている場合にtrueを返すisContainer()メソッドがあります。現在行の子にアクセスするには、enterContainer()メソッドをコールします。このメソッドをコールすると、TreeModelインスタンスが子の行のコレクションに変わります。親のコレクションに戻すには、exitContainer()メソッドをコールします。

例10-12に示すように、TreeModelクラスの作成時には、oracle.adf.view.rich.model.ChildPropertyTreeModelクラスが便利です。

例10-12 TreeModelの作成

List<TreeNode> root = new ArrayList<TreeNode>();
for(int i = 0; i < firstLevelSize; i++)
{
  List<TreeNode> level1 = new ArrayList<TreeNode>();
  for(int j = 0; j < i; j++)
  {
    List<TreeNode> level2 = new ArrayList<TreeNode>();
    for(int k=0; k<j; k++)
    {
      TreeNode z = new TreeNode(null, _nodeVal(i,j,k));  
      level2.add(z);
    }
    TreeNode c = new TreeNode(level2, _nodeVal(i,j));
    level1.add(c);
  }
  TreeNode n = new TreeNode(level1, _nodeVal(i));
  root.add(n);
}
ChildPropertyTreeModel model = new ChildPropertyTreeModel(root, "children");
private String _nodeVal(Integer... args)
{
  StringBuilder s = new StringBuilder();
  for(Integer i : args)
    s.append(i);
  return s.toString();
}

注意:

アプリケーションでFusionテクノロジ・スタックを使用する場合は、データ・コントロールを使用してツリーを作成でき、モデルが作成されます。詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』の「マスター/ディテール・データの表示」の章を参照してください。


ツリーは、表の操作と同じような方法で操作できます。次の操作を実行できます。

表と同様、ツリーでも、個々のノードのコンテンツを表示するためにスタンプ設定機能が使用されます。ツリーには、各ノードのデータの表示に使用されるコンポーネントのホルダーであるnodeStampファセットが含まれます。各ノードが一度ずつ、すべてのノードで繰り返しレンダリング(スタンプ設定)されます。各ノードにスタンプが設定されると、現在のノードのデータが、EL式を使用して特定可能なプロパティにコピーされます。このプロパティに使用する名前を、ツリーのvarプロパティを使用して指定します。ツリーのレンダリングが完了したら、このプロパティは削除されるか前の値に戻ります。

このスタンプ設定動作のため、ADF Facesツリーで子としてサポートされるのは、特定タイプのコンポーネントのみです。動作が設定されていないすべてのコンポーネントは、大部分がValueHolderまたはActionSourceインタフェースを実装するコンポーネントとしてサポートされています。

例10-13では、ツリーに表示されるデータを識別する変数nodeを使用して各要素のデータを参照しています。nodeStampファセットは、node変数からさらにプロパティを取得して、各要素のデータを表示します。

例10-13 ツリーへのデータの表示

<af:tree var="node">
  <f:facet name="nodeStamp">
    <af:outputText value="#{node.firstname}"/>
  </f:facet>
</af:tree>

ツリーにもpathStampファセットが含まれます。このファセットは、nodeStampファセットがツリーのコンテンツのレンダリング方法を決定するのと同じように、「階層セレクタ」ダイアログのコンテンツのレンダリング方法を決定します。pathStampファセット内部のコンポーネントは、単純なoutputTextimageおよびoutputFormattedタグの組合せにできますが、「階層セレクタ」ポップアップではユーザー入力は許可されていないため、入力コンポーネント(任意のEditableValueHolderコンポーネント)にすることはできません。このファセットが指定されていない場合、「階層セレクタ」アイコンはレンダリングされません。

たとえば、pathStampファセットにイメージおよびoutputTextコンポーネントを含めると、ツリーにより、「階層セレクタ」ダイアログの各ノード・レベルにイメージとoutputTextコンポーネントがレンダリングされます。値へのアクセスには同じEL式を使用します。たとえば、outputTextコンポーネントのパスの各ノードに名前を表示する場合、EL式は<af:outputText value="#{node.firstname}"/>になります。


ヒント:

panelCollectionコンポーネントにより作成されたデフォルトのツールバー・ボタンの動作方法の決定には、pathStampファセットも使用されます。ボタンを使用する場合は、ノード値にバインドされたコンポーネントを追加します。panelCollectionコンポーネントの使用方法の詳細は、10.7項「表メニュー、ツールバーおよびステータス・バーの表示」を参照してください。


10.5.1 ツリーへのデータの表示方法

ツリーを作成するには、ページにツリー・コンポーネントを追加し、表示および動作プロパティを構成します。

ページにツリーを追加する手順:

  1. 例10-12に示すように、org.apache.myfaces.trinidad.model.TreeModelクラスを拡張するJavaクラスを作成します。

  2. コンポーネント・パレットの「共通コンポーネント」パネルから、「ツリー」をドラッグ・アンド・ドロップし、「ツリーの挿入」ダイアログを開きます。必要に応じてツリーを構成します。ダイアログの使用方法のヘルプを参照するには、「ヘルプ」をクリックするか、[F1]を押します。

  3. プロパティ・インスペクタで、「データ」セクションを開いて次の属性を設定します。

    • value: ツリーをバインドするオブジェクトのEL式を指定します。手順1で作成したように、org.apache.myfaces.trinidad.model.TreeModelのインスタンスであることが必要です。

    • var: 各ノードを表す変数名を指定します。

    • varStatus: オプションで、コンポーネントの状態の判断に使用可能な変数を入力します。レンダー・レスポンス・フェーズ中に、ツリーによりモデル行が反復され、各ノードがレンダリングされます。指定された任意のノードに対して、varStatus属性で次の情報を指定します。

      • model: CollectionModelインスタンスへの参照

      • index: 現在行の索引

      • rowKey: 現在のノードの一意キー

  4. 「外観」セクションを開き、次の属性を設定します。

    • displayRow: 最初に表示される際にツリーに表示するノードを指定します。使用可能な値は、最初のノードを表示する場合はfirst、最後のノードを表示する場合はlast、ツリーの最初に選択されたノードを表示する場合はselectedです。デフォルトは、firstです。

    • displayRowKey: 最初に表示される際にツリーに表示する行キーを指定します。この属性はプログラムのみを使用して設定する必要があります。この属性を指定すると、displayRow属性がオーバーライドされます。

    • summary: オプションで、ツリーによって表示されるデータのサマリーを入力します。

  5. 「動作」セクションを開き、次の属性を設定します。

    • initiallyExpanded: コンポーネントが初めてレンダリングされる際に、すべてのノードを開いておく場合はtrueに設定します。

    • editingMode: ツリーへのデータの表示に使用された編集可能なコンポーネントで、すべてのノードを編集可能にするか(editAll)、ユーザーがノードをクリックした場合に編集可能にするか(clickToEdit)を指定します。詳細は、10.1.3項「表、ツリーおよびツリー表のデータの編集」を参照してください。

    • contextMenuSelect: 右クリックしてポップアップ・メニューを開く際に、ノードを選択するかどうかを決定します。trueに設定すると、ノードが選択されます。ポップアップ・メニューの詳細は、第13章「ポップアップ・ダイアログ、メニューおよびウィンドウの使用方法」を参照してください。

    • rowSelection: ノードを選択可能にする場合に値を設定します。有効な値はnonesingleまたはmultipleです。選択されたノードでプログラムを使用してアクションを実行する方法の詳細は、10.5.5項「プログラムを使用したノードの選択について」を参照してください。

    • ContentDelivery: データを送信するタイミングを指定します。contentDelivery属性がimmediateに設定されている場合、コンポーネントのレンダリングと同時にデータがフェッチされます。contentDelivery属性がlazyに設定されている場合は、後続のリクエスト中にデータがフェッチされてクライアントに送信されます。属性がwhenAvailable(デフォルト)に設定されている場合は、データが利用可能かどうかレンダラでチェックされます。その場合は、コンテンツはすぐに配信されますそうでない場合は、遅延配信が使用されます。詳細は、10.1.1項「コンテンツの配信」を参照してください。

    • fetchSize: データ・フェッチ・ブロックの行数を指定します。詳細は、10.1.1項「コンテンツの配信」を参照してください。

    • selectionListener: オプションで、選択イベントを処理するリスナーにEL式を入力します。詳細は、10.5.5項「プログラムを使用したノードの選択について」を参照してください。

    • focusListener: オプションで、フォーカス・イベントを処理するリスナーにEL式を入力します。

    • rowDisclosureListener: オプションで、ノードの表示イベントを処理するリスナー・メソッドにEL式を入力します。

  6. 「拡張」セクションを開き、次の属性を設定します。

  7. ツリーの高さのサイズを自動的に設定する場合は、「その他」セクションを開き、AutoHeightRowsをノードの最大値に設定して、スクロール・バーが表示される前に表示します。デフォルト値は-1です(どのような数値であっても自動サイズ設定は行われません)。値を0に設定して、fetchSizeと同じ値にできます。


    注意:

    autoHeightRows属性の設定について、次の点に注意してください。

    • inlineStyle属性の高さを指定しても影響を与えることはなく、AutoHeightRowsの値によってオーバーライドされます。

    • inlineStyle属性でmin-heightまたはmax-heightを指定することは推奨されず、autoHeightRows属性とは互換性がありません。

    • コンポーネントをpanelSplitterのようなレイアウト管理コンポーネントに配置すると、このコンテナによりサイズが指定されます(自動のサイズ指定は発生しません)。詳細は、第10.1.6項「表、ツリーおよびツリー表コンポーネントのジオメトリ管理」を参照してください。


  8. コンポーネントを追加してツリーにデータを表示するには、コンポーネント・パレットからnodeStampファセットに必要なコンポーネントをドラッグします。図10-25に、File Explorerアプリケーションのディレクトリの表示に使用されたツリーのnodeStampファセットを示します。

    図10-25 構造ウィンドウのnodeStampファセット

    構造ウィンドウのnodeStampファセット

    コンポーネントの値は、ツリーのvar属性および表示する属性の変数値セットにバインドする必要があります。たとえば、File Explorerアプリケーションのツリーでは、var属性の値としてfolderが使用されており、各ノードのディレクトリ名が表示されています。そのため、ディレクトリ名の表示に使用される出力コンポーネントの値は、#{folder.name}です。


    ヒント:

    ファセットに使用できる子コンポーネントは1つのみです。そのため、ノードごとに複数のコンポーネントを使用する場合は、図10-25に示すように、ファセットの直接の子にできるグループ・コンポーネント内にコンポーネントを配置します。


10.5.2 ページにツリーを追加する場合の処理

ページにツリーを追加すると、JDeveloperによりnodeStampファセットが追加され、ツリーのノードにスタンプが設定されます。例10-14に、File Explorerアプリケーション内のディレクトリ構造を表示するツリーの省略形のコードを示します。

例10-14 JSPページ内のADF Facesツリーのコード

<af:tree id="folderTree" 
         var="folder"
         binding="#{explorer.navigatorManager.foldersNavigator
                                             .foldersTreeComponent}"
         value="#{explorer.navigatorManager.foldersNavigator.
                                              foldersTreeModel}"
         disclosedRowKeys="#{explorer.navigatorManager.foldersNavigator.
                                              foldersTreeDisclosedRowKeys}"
         rowSelection="single" 
         contextMenuId=":context2"
         selectionListener="#{explorer.navigatorManager.foldersNavigator.
                                              showSelectedFolderContent}">
  <f:facet name="nodeStamp">
    <af:panelGroupLayout>
      <af:image id="folderNodeStampImg" source="#{folder.icon}"
                inlineStyle="vertical-align:middle; margin-right:3px;
                             shortDesc="folder icon"/>
      <af:outputText id="folderNodeStampText" value="#{folder.name}"/>
    </af:panelGroupLayout>
  </f:facet>
</af:tree>

10.5.3 実行時に行われる処理: ツリー・コンポーネント・イベント

ツリーは、階層でのレベルを示すためにノードがインデントされている形式で表示されます。ユーザーはクリックしてノードを開き、子ノードを表示できます。ユーザーは開いた状態のノードをクリックして閉じることもできます。ユーザーがこれらのアイコンのいずれかをクリックすると、コンポーネントによりRowDisclosureEventイベントが生成されます。このイベントに対応する処理を実行するには、カスタムのrowDisclosureListenerメソッドを登録します。詳細は、10.5.4項「プログラムを使用したノードの開閉について」を参照してください。

ユーザーがノードを選択または選択解除すると、ツリー・コンポーネントによりselectionEventイベントが起動されます。選択されたノードに基づいてツリー・コンポーネントで後処理を実行するカスタムのselectionListenerインスタンスを登録できます。詳細は、10.5.5項「プログラムを使用したノードの選択について」を参照してください。

10.5.4 プログラムを使用したノードの開閉について

RowDisclosureEventイベントには、閉じた状態のすべてのノード用のRemovedSetオブジェクトと、開いた状態のすべてのノード用のAddedSetオブジェクトの2つのRowKeySetオブジェクトがあります。コンポーネントは、追加されたセットの全ノードの下位のサブツリーを開き、削除されたセットの全ノードの下位のサブツリーを閉じます。

例10-15に示すように、カスタムのrowDisclosureListenerメソッドは、ツリー・コンポーネントで後処理を実行できます。

例10-15 rowDisclosureListenerを含むツリー表コンポーネント

<af:treeTable id="folderTree" var="directory" value="#{fs.treeModel}"
     binding="#{editor.component}" rowselection="multiple"
     columnselection="multiple" focusRowKey="#{fs.defaultFocusRowKey}"
     selectionListener="#{fs.Table}"
     contextMenuId="treeTableMenu"
     rowDisclosureListener="#{fs.handleRowDisclosure}">

例10-16に、行公開イベントを処理するバッキングBeanメソッドを示します。例は、ツリー・ノードの展開を示しています。ツリー・ノードを縮小する場合は、getRemovedSetを使用します。

例10-16 rowDisclosureEvent用バッキングBeanメソッド

public void handleRowDisclosure(RowDisclosureEvent rowDisclosureEvent)
  throws Exception {
    Object rowKey = null;
    Object rowData = null;
    RichTree tree = (RichTree) rowDisclosureEvent.getSource();
    RowKeySet rks = rowDisclosureEvent.getAddedSet();
 
    if (rks != null) {
        int setSize = rks.size();
        if (setSize > 1) {
            throw new Exception("Unexpected multiple row disclosure  
                                 added row sets found.");
        }
        
        if (setSize == 0) {
           // nothing in getAddedSet indicates this is a node
           // contraction, not expansion. If interested only in handling
           // node expansion at this point, return.
           return;
        }
 
        rowKey = rks.iterator().next();
        tree.setRowKey(rowKey);
        rowData = tree.getRowData();
 
        // Do whatever is necessary for accessing tree node from
        // rowData, by casting it to an appropriate data structure
        // for example, a Java map or Java bean, and so forth.
   }
} 

ツリーおよびツリー表では、oracle.adf.view.rich.model.RowKeySetクラスのインスタンスを使用して、どのノードが開かれているかを追跡します。このインスタンスは、コンポーネントのdisclosedRowKeys属性として格納されます。例10-17に示すように、このインスタンスを使用して、階層内のノードの開いた状態または閉じた状態をプログラムで制御できます。RowKeySetインスタンスに含まれるノードは開かれ、その他すべてのノードは閉じられます。addAll()メソッドによりすべての要素がセットに追加され、removeAll()メソッドによりすべてのノードがセットから削除されます。

例10-17 disclosedRowKeys属性を含むツリー・コンポーネント

<af:tree var="node"
         inlineStyle="width:90%; height:300px"
         id="displayRowTable"
         varStatus="vs"
         rowselection="single"
         disclosedRowKeys="#{treeTableTestData.disclosedRowKeys}"
         value="#{treeTableTestData.treeModel}">

例10-18に、公開された行キーを処理するバッキングBeanメソッドを示します。

例10-18 行キーを処理するためのバッキングBeanメソッド

public RowKeySet getDisclosedRowKeys()
{
  if (disclosedRowKeys == null)
  {
    // Create the PathSet that we will use to store the initial
    // expansion state for the tree
      RowKeySet treeState = new RowKeySetTreeImpl();
      // RowKeySet requires access to the TreeModel for currency.
      TreeModel model = getTreeModel();
      treeState.setCollectionModel(model);
      // Make the model point at the root node
      int oldIndex = model.getRowIndex();
      model.setRowKey(null);
      for(int i = 1; i<=19; ++i)
      {
        model.setRowIndex(i);
        treeState.setContained(true);
      }
      model.setRowIndex(oldIndex);
      disclosedRowKeys = treeState;
  }
  return disclosedRowKeys;
}

10.5.5 プログラムを使用したノードの選択について

ツリーおよびツリー表コンポーネントを使用すると、単一のノードのみまたは複数のノードを選択できるようになります。コンポーネントで複数の選択が許可されている場合、ユーザーは[Ctrl]を押しながらクリックする操作、および[Shift]を押しながらクリックする操作で複数のノードを選択できます。

ユーザーがノードを選択または選択解除すると、ツリー・コンポーネントによりselectionEventイベントが起動されます。このイベントには、選択解除されたすべてのノード用のRemovedSetオブジェクトと、選択されたすべてのノード用のAddedSetの2つのRowKeySetオブジェクトがあります。

ツリーおよびツリー表コンポーネントは、クラスoracle.adf.view.rich.model.RowKeySetのインスタンスを使用して選択されたノードを追跡します。このインスタンスは、コンポーネントのselectedRowKeys属性として格納されます。このインスタンスを使用して、階層内のノードの選択状態をプログラムで制御できます。RowKeySetインスタンスに含まれるノードは選択されているとみなされ、その他すべてのノードは選択解除されているとみなされます。addAll()メソッドによりすべてのノードがセットに追加され、removeAll()メソッドによりすべてのノードがセットから削除されます。ツリーおよびツリー表ノードの選択は、表の行の選択と同じように機能します。表の行選択のサンプル・コードは、10.2.8項「表の選択された行でのアクションの実行について」を参照してください。

10.6 ツリー表へのデータの表示

ADF Facesのツリー表コンポーネントでは、表形式で階層データが表示されます。ツリー表コンポーネントでは、階層の各ツリー・ノードのデータの列を表示できるため、ツリー表コンポーネントの表示はツリー・コンポーネントの表示より複雑です。コンポーネントには、階層のノードの開閉だけでなく、メイン・ツリー内のサブツリーにフォーカスするメカニズムもあります。図10-26に、File Explorerアプリケーションで使用されるツリー表を示します。ツリー・コンポーネント同様、ツリー表でも、コレクションのファイル間の階層関係を表示できます。また、表コンポーネントと同じように、各ファイルの属性値も表示できます。

図10-26 File Explorerアプリケーションのツリー表

File Explorerアプリケーションのツリー表

ツリー表コンポーネントの直下の子は、表コンポーネントと同じように、列コンポーネントであることが必要です。表とは異なり、ツリー表コンポーネントには、階層のノードの1次識別子を含む列が配置されるnodeStampファセットがあります。treeTableコンポーネントでは、Treeコンポーネントと同じスタンプ設定動作がサポートされています(詳細は、10.5項「ツリーへのデータの表示」を参照してください)。

たとえば、(図10-26に示す)File Explorerアプリケーションの1次識別子はファイル名です。これは、nodeStampファセットに含まれる列です。タイプ「サイズ」などのその他の列は、1次識別子の属性値を表示し、ツリー表コンポーネントの直接の子です。このツリー表では、nodeStampファセット列の各ノードのデータ、および子の列の各コンポーネントのデータにスタンプを設定するために使用される変数の値としてnodeが使用されています。例10-19に、File Explorerアプリケーション内のツリー表の省略形のコードを示します。

例10-19 treeTableの行へのスタンプ設定

<af:treeTable id="folderTreeTable" var="file"
              value="#{explorer.contentViewManager.treeTableContentView.
                                                   contentModel}"
              binding="#{explorer.contentViewManager.treeTableContentView.
                                                   contentTreeTable}"
              emptyText="#{explorerBundle['global.no_row']}"
              columnStretching="last"
              rowSelection="single"
              selectionListener="#{explorer.contentViewManager.
                                   treeTableContentView.treeTableSelectFileItem}"
              summary="treeTable data">
  <f:facet name="nodeStamp">
    <af:column headerText="#{explorerBundle['contents.name']}"
               width="200" sortable="true" sortProperty="name">
      <af:panelGroupLayout>
        <af:image source="#{file.icon}"
                  shortDesc="#{file.name}"
                  inlineStyle="margin-right:3px; vertical-align:middle;"/>
        <af:outputText id="nameStamp" value="#{file.name}"/>
      </af:panelGroupLayout>
    </af:column>
  </f:facet>
  <f:facet name="pathStamp">
    <af:panelGroupLayout>
      <af:image source="#{file.icon}"
                shortDesc="#{file.name}"
                inlineStyle="margin-right:3px; vertical-align:middle;"/>
      <af:outputText value="#{file.name}"/>
    </af:panelGroupLayout>
  </f:facet>
  <af:column headerText="#{explorerBundle['contents.type']}">
    <af:outputText id="typeStamp" value="#{file.type}"/>
  </af:column>
  <af:column headerText="#{explorerBundle['contents.size']}">
    <af:outputText id="sizeStamp" value="#{file.property.size}"/>
  </af:column>
  <af:column headerText="#{explorerBundle['contents.lastmodified']}"
             width="140">
    <af:outputText id="modifiedStamp"
                   value="#{file.property.lastModified}"/>
  </af:column>
</af:treeTable>

ツリー表コンポーネントでは、表とツリーの両方と同じ多くの属性がサポートされています。これらの属性の詳細は、10.2項「表へのデータの表示」および10.5項「ツリーへのデータの表示」を参照してください。

10.6.1 ツリー表へのデータの表示方法

ツリー表を作成するには、ツリー表の挿入ウィザードを使用します。ウィザードが完了したら、プロパティ・インスペクタを使用して、ツリー表の追加の属性を構成します。

ページにツリー表を追加する手順:

  1. コンポーネント・パレットの「共通コンポーネント」パネルから、ページに「ツリー表」をドラッグ・アンド・ドロップし、ツリー表の挿入ウィザードを開きます。ウィザードを完了することで表を構成します。ヘルプを参照するには、[F1]を押すか「ヘルプ」をクリックします。

  2. プロパティ・インスペクタを使用して、その他の属性を構成します。


    ヒント:

    ツリー表の属性は、表およびツリー・コンポーネントの属性と同じです。属性の構成の詳細は、10.2.4項「ページへの表の表示方法」および10.5.1項「ツリーへのデータの表示方法」を参照してください。


10.7 表メニュー、ツールバーおよびステータス・バーの表示

panelCollectionコンポーネントを使用して、表、ツリーおよびツリー表にメニュー、ツールバーおよびステータス・バーを追加できます。panelCollectionコンポーネントを使用するには、表、ツリーまたはツリー表コンポーネントをpanelCollectionコンポーネントの直接の子として追加します。panelCollectionコンポーネントには、デフォルトのメニューとツールバー・ボタンが用意されています。

図10-27に、ツリー表コンポーネントを含む、File ExplorerアプリケーションのpanelCollectionコンポーネントを示します。ツールバーには、ツリー表で実行可能なアクション(ノードの開閉など)を提供するメニュー、ユーザーがツリー表を連結解除できるボタン、およびユーザーがツリー表に表示された行を変更できるボタンが含まれます。ツールバーに特定のツールバー項目を表示しないように構成できます。たとえば、ユーザーがツリーまたは表を連結解除できるようにするボタンを無効にできます。メニュー、ツールバーおよびツールバー・ボタンの詳細は、第14章「メニュー、ツールバーおよびツールボックスの使用方法」を参照してください。

図10-27 メニューおよびツールバーのあるツリー表のパネル・コレクション

メニューおよびツールバーのあるpanelCollection

他のファセットでは、panelCollectionコンポーネントには、メニュー・コンポーネントを保持するmenuファセット、ツールバー・コンポーネント用のtoolbarファセット、別のツールバー・コンポーネント・セット用のsecondaryToolbarファセット、およびステータス項目用のstatusbarファセットが含まれています。

デフォルトのトップレベルのメニューおよびツールバー項目は、panelCollectionコンポーネントの子として使用されているコンポーネントにより異なります。

例10-20に、panelCollectionコンポーネントにどのようにメニューおよびツールバーが含まれるかを示します。

例10-20 表、メニューおよびツールバーを含むpanelCollectionコンポーネント

<af:panelCollection
    binding="#{editor.component}">  
  <f:facet name="viewMenu">
    <af:group>
      <af:commandMenuItem text="View Item 1..."/>
      <af:commandMenuItem text="View Item 2.."/>
      <af:commandMenuItem text="View Item 3..." disabled="true"/>
      <af:commandMenuItem text="View Item 4"/>
    </af:group>
  </f:facet>

  <f:facet name="menus">
    <af:menu text="Actions">
      <af:commandMenuItem text="Add..." />
      <af:commandMenuItem text="Create.." />
      <af:commandMenuItem text="Update..." disabled="true"/>
      <af:commandMenuItem text="Copy"/>
      <af:commandMenuItem text="Delete"/>              
      <af:commandMenuItem text="Remove" accelerator="control A"/>
      <af:commandMenuItem text="Preferences"/>
    </af:menu>
  </f:facet>
  <f:facet name="toolbar">
    <af:toolbar>
      <af:commandToolbarButton shortDesc="Create" icon="/new_ena.png">
      </af:commandToolbarButton>
      <af:commandToolbarButton shortDesc="Update" icon="/update_ena.png">
      </af:commandToolbarButton>
      <af:commandToolbarButton shortDesc="Delete" icon="/delete_ena.png">
      </af:commandToolbarButton>
    </af:toolbar>
  </f:facet>
  <f:facet name="secondaryToolbar">
  </f:facet>
  <f:facet name="statusbar">
    <af:toolbar>
      <af:outputText id="statusText" ... value="Custom Statusbar Message"/>
    </af:toolbar>
  </f:facet>
  <af:table rowselection="multiple" columnselection="multiple" 
                        ...
  <af:column 
                        ...
  </af:column>

ヒント:

panelCollectionコンポーネント内で、メニューを連結解除可能にできます。詳細は、14.2項「メニュー・バーでのメニューの使用方法」を参照してください。ユーザーが次の操作をする可能性がある場合は、連結解除メニューの使用を検討してください。

  • ページで類似のコマンドを繰り返し実行する場合。

  • 大規模な表、ツリー表またはツリーにおいて、異なる行のデータで類似のコマンドを実行する場合。

  • 長くて幅の広い表やツリー表、およびツリーでデータを表示する場合。ユーザーは一度クリックすることで、表示または非表示にする列やブランチを選択できます。

  • 長くて幅の広い表、ツリー表またはツリーでデータを書式設定する場合。


10.7.1 表、ツリーまたはツリー表を含むpanelCollectionの追加方法

panelCollectionコンポーネントを追加してから、panelCollectionコンポーネントに表、ツリーまたはツリー表を追加します。その後、メニューおよびツールバーを追加および変更できます。

集約表示のコンポーネントを含むpanelCollectionコンポーネントを作成する手順:

  1. コンポーネント・パレットの「レイアウト」パネルから、ページに「パネル・コレクション」をドラッグ・アンド・ドロップします。表、ツリーまたはツリー表をそのコンポーネントの子として追加します。

    または、ページに表、ツリーまたはツリー表がすでに存在している場合は、コンポーネントを右クリックして「囲む」を選択します。次に「パネル・コレクション」を選択して、panelCollectionコンポーネントでコンポーネントを囲みます。

  2. オプションで、特定のツールバーとメニュー項目を無効にして、panelCollectionツールバーをカスタマイズします。これを実行するには、構造ウィンドウでpanelCollectionコンポーネントを選択します。プロパティ・インスペクタで、featuresOff属性を設定します。表10-1に、有効な値およびツールバーへのそれぞれの影響を示します。

    表10-1 featuresOff属性の有効値

    表示されない項目

    statusBar

    ステータス・バー

    viewMenu

    「表示」メニュー

    formatMenu

    「書式設定」メニュー

    columnsMenuItem

    「表示」メニューの「列」メニュー

    columnsMenuItem:colId

    例:
    columnsMenuItem:col1, col2

    「列」メニューのIDに一致する列

    たとえば、左側の値には、IDがcol1およびcol2の列は表示されません。

    freezeMenuItem

    「表示」メニューの「固定」メニュー項目

    detachMenuItem

    「表示」メニューの「連結解除」メニュー項目

    sortMenuItem

    「表示」メニューの「ソート」メニュー項目

    reorderColumnsMenuItem

    「表示」メニューの「列の並替え」メニュー項目

    resizeColumnsMenuItem

    「書式設定」メニューの「列のサイズ変更」メニュー項目

    wrapMenuItem

    「書式設定」メニューの「折返し」メニュー項目

    showAsTopMenuItem

    ツリーの「表示」メニューの「先頭として表示」メニュー項目

    scrollToFirstMenuItem

    ツリーの「表示」メニューの「最初にスクロール」メニュー項目

    scrollToLastMenuItem

    ツリーの「表示」メニューの「最後にスクロール」メニュー項目

    freezeToolbarItem

    「固定」ツールバーの項目

    detachToolbarItem

    「連結解除」ツールバーの項目

    wrapToolbarItem

    「折返し」ツールバーの項目

    showAsTopToolbarItem

    「先頭として表示」ツールバーの項目

    wrap

    「折返し」メニューおよびツールバーの項目

    freeze

    「固定」メニューおよびツールバーの項目

    detach

    「連結解除」メニューおよびツールバーの項目


  3. コンポーネントにカスタムのメニューおよびツールバーを追加します。

    • メニュー: menuファセットにmenuコンポーネントを追加します。

    • ツールバー: toolbarまたはsecondaryToolbarファセットにtoolbarコンポーネントを追加します。

    • ステータス項目: statusbarファセットに項目を追加します。

    • ビュー・メニュー: viewMenuファセットにcommandMenuItemコンポーネントを追加します。複数項目の場合は、多数のcommandMenuItemコンポーネントのコンテナとしてgroupコンポーネントを使用します。

    コンポーネント・パレットから、ファセットにコンポーネントをドラッグ・アンド・ドロップします。たとえば、menuファセットにメニューをドロップし、同じファセットに「メニュー項目」をドロップしてメニュー・リストを作成します。メニューおよびツールバーの詳細は、第14章「メニュー、ツールバーおよびツールボックスの使用方法」を参照してください。

10.8 リストへのコレクションの表示

複数の列を持つ表を使用するかわりに、listViewおよびlistItemコンポーネントを使用すると、1つの列のみを持つ表のような単純な形式で構造化データを表示できます。図10-28に、1つのlistItemコンポーネントを持ち、それを使用して各行にエラー・アイコン、タスク情報およびアクション・ボタンを表示するlistViewコンポーネントを示します。

図10-28 1つのlistItemコンポーネントを持つlistViewコンポーネント

listItemコンポーネントを持つlistView

図10-29に示すように、表示するデータを列を使用してグループ化するかわりに、1つのlistItemコンポーネントに保持された複数のレイアウト・コンポーネントおよびその他のコンポーネントの組合せによって実際のデータが表示されます。この例では、listItemコンポーネントに1つの大きなpanelGroupLayoutコンポーネントが含まれ、子を水平に表示するように設定されています。子として別のpanelGroupLayoutコンポーネントが3つあり、これらを使用して表における列のように子をグループ化しています。これらのpanelGroupLayoutコンポーネントも、それぞれの子を水平に表示するように設定されています。これらのレイアウト・コンポーネントの2番目には、1つのpanelGroupLayoutコンポーネントが含まれ、子コンポーネント(この場合は3つのoutputTextコンポーネント)を垂直に表示するように設定されています。

図10-29 データを表示する複数のコンポーネントを含むlistItemコンポーネント

多くの子コンポーネントを含むlistItemコンポーネント

例10-21に、対応するコードを示します。

例10-21 listViewコンポーネント

<af:listView id="listView" binding="#{editor.component}"
                           var="item" varStatus="vs" partialTriggers="::pprLV"
                           value="#{demolistView.taskModel}"
                           selection="multiple">
  <af:listItem id="lvi">
    <af:showPopupBehavior popupId="::ctxtMenu"
                          triggerType="contextMenu"/>
    <af:panelGroupLayout id="panelGroupLayout1"
                         layout="horizontal"
                         styleClass="AFStretchWidth">
      <af:panelGroupLayout id="panelGroupLayout2"
                           layout="horizontal"
                           inlineStyle="margin-left:20px; width:45px"
                           halign="center" valign="middle">
        <af:image rendered="#{vs.index %6 ==1}"
                  source="/images/error.png" id="i1"
                  shortDesc="Error at Line #{vs.index + 1}"/>
      </af:panelGroupLayout>
      <af:panelGroupLayout id="panelGroupLayout3" layout="horizontal"
                           inlineStyle="width:100%">
        <af:panelGroupLayout id="panelGroupLayout5"
                             layout="vertical"
                             inlineStyle="min-width:300px">
          <af:outputText id="outputText1" value="#{item.taskName}"
                         styleClass="taskName"/>
          <af:outputText id="outputText2"
                         value="#{item.projectDesc}"
                         styleClass="taskProjectDesc"/>
          <af:outputText id="outputText3" value="#{item.created}"
                         styleClass="taskCreated"/>
        </af:panelGroupLayout>
      </af:panelGroupLayout>
      <af:panelGroupLayout id="panelGroupLayout4"
                           layout="horizontal" halign="end"
                           valign="middle"
                           inlineStyle="margin-right:20px">
        <af:commandButton id="cb1" text="Action"
                      shortDesc="Click To Invoke Action for Item #{vs.index + 1}">
          <af:showPopupBehavior popupId="::popupDialog"
                               alignId="cb1" align="afterStart"/>
        </af:commandButton>
      </af:panelGroupLayout>
    </af:panelGroupLayout>
  </af:listItem>
</af:listView>

listViewコンポーネントをコレクションにバインドします。その後、コンポーネントは各アイテムに値をスタンプ設定し、1つのlistItemコンポーネントを繰り返しレンダリングします。各アイテムにスタンプが設定されると、現在の行のデータが、listViewコンポーネントのvar属性を使用するEL式を使用して特定可能なプロパティにコピーされます。リストのレンダリングが完了したら、このプロパティは削除されるか前の値に戻ります。

この例では、listViewの値はdemolistView.taskModelオブジェクトにバインドされています。このオブジェクトのプロパティには、varプロパティ(itemに設定されている)を使用してアクセスできます。たとえば、タスク名を表示する場合は、outputTextコンポーネントの値はitem.taskNameに設定されます。

また、listViewコンポーネントには、制限付きの2レベルの階層を表示することもできます。階層を表示するには、listViewCollectionModelではなくTreeModelにバインドする必要があります。TreeModelは、1つのルート・レベルと1つの子レベルを持つことができます(TreeModelクラスの詳細は、第10.5項「ツリーへのデータ表示」を参照)。

ツリーの場合と同様に、listViewも、スタンプ設定を使用して個々のノードの値を表示し、ノードの親グループの表示に使用されるコンポーネントのホルダーとなるファセット(groupHeaderStampという名前のファセット)を使用します。ただし、listViewで許可されるのは2レベルのみであるため、groupHeaderStampファセットには、ルート・レベルのみの表示に使用されるコンポーネントが含まれます。

図10-30に、ルートがアルファベット文字、リーフ・ノードが従業員オブジェクトという単純な階層を表示するlistViewコンポーネントを示します。

図10-30 listViewコンポーネントの単純な階層

listViewコンポーネントの単純な階層

例10-22に示すように、従業員オブジェクトの表示に使用されるコンポーネントはlistItemコンポーネント内に配置され、アルファベット文字の表示に使用されるコンポーネントはgroupHeaderStampファセットのlistItemコンポーネント内に配置されています。

例10-22 listViewコンポーネントのgroupHeaderStampファセット

<af:listView id="listView" binding="#{editor.component}"
             var="item" varStatus="vs" groupDisclosurePolicy="noDisclosure"
             value="#{demolistView.ABTreeModel}">
  <af:listItem id="listItem1">
    <af:panelGroupLayout id="pgl3" layout="vertical">
      <af:outputText id="ot2" value="#{item.ename}" styleClass="ABName"/>
      <af:outputText id="ot3" value="#{item.job}" styleClass="ABJob"/>
    </af:panelGroupLayout>
  </af:listItem>
  <f:facet name="groupHeaderStamp">
    <af:listItem id="listItem2" styleClass="ABHeader">
      <af:outputText id="ot1" value="#{item.alphabetHeading}"/>
    </af:listItem>
  </f:facet>
</af:listView>

listViewコンポーネントに階層を表示する場合は、図10-31に示すように、ヘッダーで子コンポーネントを表示または非表示にできるように構成できます。

図10-31 閉じるヘッダーを表示するように構成されたlistViewコンポーネント

ヘッダーを閉じられるlistViewコンポーネント

デフォルトでは、listViewコンポーネントはすべての子を表示するように構成されます。groupDisclosurePolicy属性を使用すると、これを変更できます。

ユーザーがグループの開閉を行うと、RowDisclosureEventが起動されます。groupDisclosureListenerを使用すると、プログラムからノードを開閉できます。詳細は、10.5.4項「プログラムを使用したノードの開閉について」を参照してください。

ユーザーが行またはノードを選択または選択解除すると、SelectionEventが起動されます。selectionListenerを使用すると、プログラムでイベントに応答できます。詳細は、10.2.8項「表の選択された行でのアクションの実行について」を参照してください。

10.8.1 リストへのコレクションの表示方法

リストを作成するには、CollectionModelインスタンスにバインドされたlistViewコンポーネントと、1つのlistItemコンポーネントを使用します。単純な親子のヘッダーを表示する場合は、groupHeaderStampファセット内に2つ目のlistItemコンポーネントを配置します。次に、レイアウト・コンポーネントとその他のテキスト・コンポーネントを追加して、実際のデータを表示します。

リストにコレクションを表示するには:

  1. リストのバインド先となるモデルのJavaクラスを作成します。リストにヘッダー付きのグループを表示する場合、org.apache.myfaces.trinidad.model.TreeModelクラスを拡張するモデルを使用する必要があります。それ以外の場合は、org.apache.myfaces.trinidad.model.CollectionModelクラスを拡張します。


    ヒント:

    java.util.Listarrayjavax.faces.model.DataModelなど、別のモデル・クラスも使用できます。このような別のクラスのいずれかを使用する場合は、listViewコンポーネントにより、インスタンスがCollectionModelクラスに自動的に変換されますが、機能は追加されません。CollectionModelクラスの詳細は、http://myfaces.apache.org/trinidad/trinidad-1_2/trinidad-api/apidocs/index.htmlにあるMyFaces TrinidadのJavadocを参照してください。


  2. コンポーネント・パレットの「ADF Faces」パネルから、ページに「リスト・ビュー」をドラッグ・アンド・ドロップします。

  3. プロパティ・インスペクタで「その他」セクションを開き、次のように設定します。

    • Value: 手順1で作成したモードにリストをバインドするためのEL式を指定します。

    • var: 各ノードを表す変数名を指定します。

    • First: リストに表示する最初の行として設定する行を指定します。

    • FetchSize: 各データ・フェッチで戻されるブロックのサイズを設定します。デフォルトは25です。

    • Rows: 行範囲に表示する行の数を指定します。デフォルトでは、この値は25 (fetchSize属性と同じ値)です。

    • selectedRowKeys: オプションで、最初に選択されるノードのキーを入力します。詳細は、10.5.5項「プログラムを使用したノードの選択について」を参照してください。

    • Selection: 行を選択可能にするための値(つまりrowSelection属性)を設定します。有効な値はnone、singleおよびmultipleです。選択された行でプログラムを使用してアクションを実行する方法の詳細は、10.2.8項「表の選択された行でのアクションの実行について」を参照してください。

  4. listViewコンポーネントの子として、「リスト・アイテム」をドラッグ・アンド・ドロップします。

  5. レイアウトとその他のコンポーネントをlistViewコンポーネントにドラッグ・アンド・ドロップして、目的の構成を作成します。例については、図10-29および例10-21を参照してください。

  6. listViewコンポーネントに単純な階層を表示する場合は、groupHeaderStampファセットに「リスト・アイテム」をドラッグ・アンド・ドロップします。図10-32に、構造ウィンドウのgroupHeaderStampファセットを示します。

    図10-32 構造ウィンドウのgroupHeaderStampファセット

    リストの子であるgroupHeaderStampファセット
  7. listItemコンポーネントに「出力テキスト」をドラッグ・アンド・ドロップしてヘッダー・テキストを表示し、必要に応じてoutputTextコンポーネントを構成します。

10.9 カルーセルでのイメージの表示

図10-33に示すように、イメージを回転カルーセルに表示できます。ユーザーは、下部にあるスライダを使用するか、補助イメージの1つをクリックしてそのイメージを前面に移動することにより、前面のイメージを変更できます。

図10-33 ADF Facesカルーセル

カルーセル・コンポーネント

デフォルトで、カルーセルは水平に表示されます。水平方向のカルーセル内にあるオブジェクトは中央揃えで配置され、カルーセル自体はコンテナで水平に配置されます。

参照カード・ファイルの表示など、必要に応じて、垂直に表示されるようにカルーセルを構成できます。デフォルトでは、図10-34に示すように、垂直方向のカルーセル内にあるオブジェクトは中央揃えで配置され、カルーセル自体は垂直に配置されます。カルーセルの位置合せ属性を使用して、位置合せを変更できます。

図10-34 垂直カルーセル・コンポーネント

垂直カルーセル・コンポーネント

ベスト・プラクティス:

一般に、カルーセルは子を拡大する親コンポーネントに配置する必要があります(panelSplitterpanelStretchLayoutなど)。子を拡大するコンポーネントにカルーセルを配置しない場合、カルーセルは幅500px、高さ300pxのデフォルト・サイズで表示されます。これらのサイズは変更できます。


図10-33に示すように、カルーセル・コンポーネントは循環モードで表示できます。また、図10-35に示すように、現在のイメージのみを表示するようにカルーセルを構成できます。

図10-35 1つのイメージのみ表示できるカルーセル

1つのイメージのみ表示されているカルーセル

イメージの参照に使用されるコントロールを構成することもできます。次の項目に移動する矢印や前の項目に移動する矢印を持つ、複数のイメージにまたがるスライダを表示できます(図10-33を参照)。次の項目に移動するボタンや前の項目に移動するボタンのみを表示する(図10-35を参照)か、次の項目に移動するボタンや前の項目に移動するボタンをスライダ・カウンタとともに表示する(図10-36を参照)ことができます。

図10-36 スライダ・カウンタのある、次の項目や前の項目に移動するボタン

次および前ボタンのみあるカルーセル

デフォルトでは、カルーセルが循環モードで表示するように構成されている場合、補助アイテム(現在、中央に表示されていないアイテム)にポインタを置くと、そのアイテムが枠で囲まれ選択可能であることが示されます(この枠は、アプリケーションがSkyrosまたはFusion FX v1.2以降のスキンを使用している場合にのみ、表示されることに注意してください)。図10-37に示すように、アイテムが移動し、最大サイズで表示されるように、カルーセルを構成できます。

図10-37 マウスを置いた場所に移動する補助アイテム

マウスを置いた場所に移動する補助アイテム

循環モードに設定した場合、イメージ間のスペースも構成できます。また、補助イメージのサイズも構成できます。デフォルトでは、イメージ間のスペースは先行イメージのサイズの0.45倍に設定されています。この結果、隣合うイメージは重なります。また、補助イメージのサイズは0.8に設定されているため、各イメージは先行イメージの0.8倍になります(図10-33を参照)。この設定を変更すると、カルーセルの外観を変更できます。たとえば、カルーセルをスライドのように表示する場合、イメージ間のスペースを1.1に設定し、補助アイテムのサイズは1に設定します。これによって、図10-38に示すように、補助アイテムはすべて同じサイズになります。

図10-38 スライドのように表示されるカルーセルの構成

スライドのように表示されるカルーセルの構成

carouselItemコンポーネントは、カルーセルにオブジェクトとそのオブジェクトのタイトルを表示します。carouselコンポーネントをコレクションにバインドします。その後、コンポーネントは各アイテムに値をスタンプ設定し、1つのcarouselItemコンポーネントを繰り返しレンダリングします。各アイテムがスタンプ設定されると、現在のアイテムのデータが、carouselコンポーネントのvar属性を使用するEL式によって対応可能なプロパティにコピーされます。カルーセルのレンダリングが完了したら、このプロパティは削除されるか前の値に戻ります。カルーセルにはnodeStampファセットが含まれます。これは、各アイテムのテキストと短い説明を表示するために使用されるcarouselItemコンポーネントのホルダーであり、各アイテムに表示されるイメージに対する親コンポーネントでもあります。

たとえば、図10-33に示すADF FacesデモのcarouselItem JSFページには、各ADF Facesコンポーネントのイメージを表示するcarouselコンポーネントが含まれます。demoCarouselItem(CarouselBean.java)マネージドBeanには、これらの各コンポーネントのリストが含まれます。carouselコンポーネントのvalue属性は、そのリストを表すそのBeanのitemsプロパティにバインドされます。カルーセルのコンポーネントのvar属性は、表示する各アイテムの値を保持するために使用されます。carouselItemコンポーネントとimageコンポーネントの両方がこれを使用し、各アイテムの正しい値を取得します。例10-23に、カルーセルのJSFページ・コードを示します。カルーセルでのスタンプの動作の詳細は、ツリーへのデータの表示に関する項を参照してください。

例 10-23 carouselコンポーネントのJSFページ・コード

<af:carousel id="carousel" binding="#{editor.component}"
             var="item"
             value="#{demoCarousel.items}"
             carouselSpinListener="#{demoCarousel.handleCarouselSpin}">
  <f:facet name="nodeStamp">
    <af:carouselItem id="crslItem" text="#{item.title}" shortDesc="#{item.title}">
      <af:image id="img" source="#{item.url}" shortDesc="#{item.title}"/>
    </af:carouselItem>
  </f:facet>
</af:carousel>

carouselItemコンポーネントは、子コンポーネントのみ拡大します。単一のimageコンポーネントをcarouselItemの内部に配置した場合、イメージはその項目に割り当てられた正方形に合せて拡大されます(ユーザーがカルーセルをスピンすると、これらのサイズが縮小または拡大されます)。


ベスト・プラクティス:

imageコンポーネントは、拡大されたときの動作を変更するジオメトリ管理コントロールを提供しません。拡大されたときにイメージが適切な縦横比を保つためには、同じ幅と高さのイメージを使用する必要があります。


carouselコンポーネントでは、CollectionModelクラスを使用して基礎となるコレクションのデータにアクセスします。このクラスは、JSF DataModelクラスを拡張し、行キーのサポートを追加します。DataModelクラスでは、行は索引によって完全に識別されます。ただし、基になるデータが変更された場合に問題を回避するために、CollectionModelクラスが索引ではなく行キーに基づいています。

java.util.Listarrayおよびjavax.faces.model.DataModelなど、別のモデル・クラスも使用できます。他のいずれかのクラスを使用する場合は、carouselコンポーネントにより、インスタンスがCollectionModelクラスに自動的に変換されますが、機能は追加されません。CollectionModelクラスの詳細は、http://myfaces.apache.org/trinidad/trinidad-1_2/trinidad-api/apidocs/index.htmlにあるMyFaces TrinidadのJavadocを参照してください。


注意:

アプリケーションでFusionテクノロジ・スタックを使用する場合は、項目を表すデータ・ソースに対するADFビジネス・コンポーネントを作成でき、作成するとモデルが作成されます。その後、カルーセルを宣言的に作成でき、そのカルーセルは自動的にそのモデルにバインドされます。詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』のADF Facesカルーセル・コンポーネントの使用に関する項を参照してください。


カルーセル・コンポーネントは仮想化されており、サーバーのコンポーネントに対して使用可能なすべてのアイテムがクライアントに配信されて表示されるわけではありません。データ・ソースから一度に一定数の行をフェッチするようにカルーセルを構成します。レンダリング時にすぐにデータをコンポーネントに配信することも、コンポーネントのシェルがレンダリングされた後に遅延フェッチすることもできます。デフォルトでは、カルーセルは初期リクエストのデータを遅延してフェッチします。ページにこれらのコンポーネントが1つ以上含まれる場合、ページでは最初は標準のライフサイクルが実行されます。ただし、カルーセルはその初期リクエスト時にデータをフェッチするかわりに、特殊な部分ページ・レンダリング(PPR)リクエストをコンポーネントで別途実行し、カルーセルのフェッチ・サイズの値として設定される項目数が返されます。ページのレンダリング直後であるため、レスポンスのレンダリング・フェーズのみがカルーセルに対して実行され、対応するデータのフェッチおよび表示が可能になります。後続のデータ・フェッチが発生した場合(別のイメージ・セットのカルーセルを回転させた場合など)、別のPPRリクエストが実行されます。


パフォーマンスのヒント:

ページにカルーセルより多くのコンポーネントが含まれる場合は、遅延配信を使用する必要があります。遅延配信を使用すると、データが使用可能になる前に、初期ページのレイアウト・コンポーネントおよびその他のコンポーネントが最初にレンダリングされます。

即時配信は、カルーセルがページの唯一のコンテキストである場合、またはカルーセルが大きな項目セットを返さないと予想される場合に使用します。この場合、遅延配信を使用する場合よりも、レスポンス時間は早くなります(または、単に速いと感じられるだけの場合もあります)。2番目のリクエストがサーバーに送信されないため、ユーザーのレスポンス時間が速くなり、サーバーのCPU使用率も向上します。ただし、フェッチ・ブロックとして構成されたアイテムの数のみが最初に返されることに注意してください。遅延配信と同様に、ユーザーのアクションにより後続のデータ・フェッチが実行される場合は、次のアイテム・セットが配信されます。


スライダ・コントロールでは、ユーザーはコレクションをナビゲートできます。通常、スライダのサムは総オブジェクト数の中の現在のオブジェクト番号(たとえば、20個中の6番目など)を表示します。オブジェクトの総数が大きすぎて計算できない場合、スライダ上のサムには現在のオブジェクト番号のみ表示されます。たとえば、カルーセルが会社の従業員ディレクトリに使用される場合などです。デフォルトでは、ディレクトリで全従業員の顔写真を表示する場合、時間をかけてデータベースを呼び出さなければ、正確に94,409名の従業員のデータがシステム内に存在することを把握できません。

カルーセルとともに他のコンポーネントを使用できます。たとえば、ツールバーまたはメニュー・バーを追加し、ユーザーが現在のオブジェクトに対するアクションを実行できるボタンまたはメニュー項目をそれらに追加できます。

10.9.1 カルーセルの作成方法

カルーセルを作成するには、まず、表示するイメージを含むデータ・モデルを作成する必要があります。次に、carouselコンポーネントをそのモデルにバインドし、carouselItemコンポーネントをカルーセルのnodeStampファセットに挿入します。最後に、imageコンポーネント(またはimageコンポーネントを含むその他のコンポーネント)をcarouselItemコンポーネントに子として挿入します。

カルーセルを作成する手順:

  1. 表示するイメージのコレクションを提供するデータ・モデルを作成します。データ・モデルは、ListArrayDataModelまたはCollectionModelです。コレクションがCollectionModel以外の場合、フレームワークはそれをCollectionModelに自動的に変換します。CollectionModelクラスの詳細は、http://myfaces.apache.org/trinidad/trinidad-1_2/trinidad-api/apidocs/index.htmlにあるMyFaces TrinidadのJavadocを参照してください。

    データ・モデルは、カルーセルに表示する各イメージについて次の情報を提供する必要があります。

    • イメージのURL

    • カルーセルのイメージの下に表示されるタイトル

    • ユーザーがイメージ上にカーソルを置いたときに表示するテキストに使用される短い説明

    たとえば、ADF Facesデモ・アプリケーションのCarouselBean.javaおよびCarouselMediaBean.javaクラスを参照してください。

  2. コンポーネント・パレットの「共通コンポーネント」パネルから、ページに「カルーセル」をドラッグ・アンド・ドロップします。

  3. プロパティ・インスペクタで、「共通」セクションを開いて次の設定を行います。

    • Orientation: デフォルトでは、カルーセルは水平に表示されます。図10-34に示すように垂直に表示する場合は、verticalを選択します。horizontalに設定した場合は、halign属性を使用して、項目を整列する方法を構成する必要があります。verticalに設定した場合は、valign属性を使用して、項目を整列する方法を設定します。

    • Halign: 垂直カルーセルの項目を表示する方法を指定します。有効な値は次のとおりです。

      • Center: 同じ中心点を持つように項目を位置合せします。これがデフォルトです。

      • End: 右端が整列するように項目を位置合せします(ブラウザが左から右の言語で表示される場合)。

      • Start: 左端が整列するように項目を位置合せします(ブラウザが左から右の言語で表示される場合)。

    • Valign: 水平カルーセルの項目を表示する方法を指定します。有効な値は次のとおりです。

      • Bottom: 下端が整列するように項目を位置合せします。

      • Middle: 同じ中央点を持つように項目を位置合せします。これがデフォルトです。

      • Top: 上端が整列するように項目を位置合せします。

    • Value: カルーセルをモデルにバインドします。

  4. 「データ」セクションを開き、次の属性を設定します。

    • Var: 個々の項目データにアクセスするためにELで使用される変数を入力します。

    • VarStatus: カルーセルのステータスにアクセスするためにELで使用される変数を入力します。varStatusの共通プロパティは次のとおりです。

      • model: コンポーネントのCollectionModelを返します。

      • index: ゼロ・ベースの項目索引を返します。

  5. 「外観」セクションを開き、アイテムが返されない場合に表示するテキストにEmptyTextを設定します。リソース・バンドルを使用する場合は、ドロップダウン・メニューを使用して「テキスト・リソースの選択」を選択します。

  6. 「動作」セクションを開き、次の設定を行います。

    • FetchSize: 各データ・フェッチで戻されるブロックのサイズを設定します。

    • ContentDelivery: データを送信するタイミングを指定します。contentDelivery属性がimmediateに設定されている場合、カルーセルのレンダリングと同時に項目がフェッチされます。contentDelivery属性がlazyに設定されている場合は、後続のリクエスト中に項目がフェッチされてクライアントに送信されます。

    • CarouselSpinListener: カルーセルが回転されたときにロジックを実行する必要がある場合に、カルーセルの回転を処理するハンドラ・メソッドにバインドします。例10-24に、回転が行われたときに詳細パネルを再描画するCarouselBeanのハンドラ・メソッドを示します。

      例10-24 CarouselSpinEventのハンドラ

        public void handleCarouselSpin(CarouselSpinEvent event)
        {
          RichCarousel carousel = (RichCarousel)event.getComponent();
          carousel.setRowKey(event.getNewItemKey());
          ImageInfo itemData = (ImageInfo)carousel.getRowData();
          _currentImageInfo = itemData;
       
          // Redraw the detail panel so that we can update the selected details.
          RequestContext rc = RequestContext.getCurrentInstance();
          rc.addPartialTarget(_detailPanel);
        }
      
  7. 「拡張」セクションを開き、CurrentItemKeyを設定します。カルーセルが最初にレンダリングされるときに表示する項目を指定します。値は、CollectionModelの項目の主キー(またはそれと同等)である必要があります。

  8. 「その他」セクションを開き、次の設定を行います。

    • AuxiliaryOffset: 先行イメージからどのくらいイメージが離れているかを決定する数値を設定します。デフォルト値は0.45です。

    • AuxiliaryPopOut: hoverを設定すると、補助イメージにマウスを置いたときに補助イメージが最大サイズでレンダリングされます。デフォルトはoffです。

    • AuxiliaryScale: 先行イメージと比較した各イメージのサイズを決定する数値を設定します。1に設定すると、すべてのイメージが同じサイズになります。1より小さい値を設定すると、各イメージは少しずつ小さくなり、1より大きい値を設定すると、大きくなります。デフォルトでは、設定は0.8です。各イメージは先行イメージの80%の大きさになります。

    • ControlArea: カルーセル・イメージの参照に使用するコントロールを指定します。有効な値は次のとおりです。

      • full: スライダは現在のイメージよりも大きくなり、次の項目に移動するボタンと前の項目に移動するボタンを表示します。

      • small: スライダのサイズは現在のイメージのサイズになり、次の項目に移動するボタンと前の項目に移動するボタンを表示します。

      • compact: 次の項目に移動するボタンと前の項目に移動するボタンのみが表示されます。

      • none: スライダおよびコントロールは表示されません。

    • DisplayItems: circularを選択すると、カルーセルに複数のイメージが表示されます。カルーセルに一度に1つのイメージを表示する場合は、oneByOneを選択します。

  9. コンポーネント・パレットから「カルーセル・アイテム」CarouselコンポーネントのnodeStampファセットにドラッグします。

    カルーセルのvar属性に設定された変数値を使用して、CarouselItemコンポーネントの属性をデータ・モデルのプロパティにバインドします。たとえば、例10-23のカルーセルは、itemvar属性の値として使用します。このため、carouselItemtext属性の値はitem.titleになります(titleが、データ・モデルのカルーセル項目に使用されるテキストへのアクセスに使用されるプロパティである場合)。

  10. コンポーネント・パレットからイメージをドラッグし、carouselItemに子としてドロップします。

    カルーセルのvar属性に設定された変数値を使用して、imageコンポーネントの属性をデータ・モデルのプロパティにバインドします。たとえば、例10-23のカルーセルは、itemvar属性の値として使用します。このため、imagesource属性の値はitem.urlになります(urlがイメージへのアクセスに使用されるプロパティである場合)。

    機能を増やす場合は、イメージ・コンポーネントを他のコンポーネントで囲むことができます。たとえば、図10-39に、イメージがpanelGroupLayoutコンポーネントで囲まれ、clientListenerを使用してメニューとナビゲーション・バーを表示するJavaScript関数をコールするカルーセルを示します。

    図10-39 より複雑なカルーセルのレイアウトの使用

    カルーセル項目にはメニューとナビゲーションがある

    例10-25に、対応するページ・コードを示します。

    例10-25 カルーセルのより複雑なレイアウト

    <af:carouselItem id="mainItem" text="#{item.title}" shortDesc="#{item.title}">
      <af:panelGroupLayout id="itemPgl" layout="vertical">
        <af:image id="mainImg" source="#{item.url}" shortDesc="#{item.title}"
                               styleClass="MyImage">
          <af:clientListener method="handleItemOver" type="mouseOver"/>
          <af:clientListener method="handleItemDown" type="mouseDown"/>
          <af:showPopupBehavior triggerType="contextMenu" popupId="::itemCtx"/>
        </af:image>
      <af:panelGroupLayout id="overHead" styleClass="MyOverlayHeader"
                           layout="vertical" clientComponent="true">
        <af:menuBar id="menuBar">
          <af:menu id="menu" text="Menu">
            <af:commandMenuItem id="menuItem1" text="Menu Item 1"/>
            <af:commandMenuItem id="menuItem2" text="Menu Item 2"/>
            <af:commandMenuItem id="menuItem3" text="Menu Item 3"/>
          </af:menu>
        </af:menuBar>
      </af:panelGroupLayout>
      <af:panelGroupLayout id="overFoot" styleClass="MyOverlayFooter"
                           layout="vertical" clientComponent="true"
                           halign="center">
        <af:panelGroupLayout id="footHorz" layout="horizontal">
          <f:facet name="separator">
            <af:spacer id="footSp" width="8"/>
          </f:facet>
          <af:commandImageLink . . .
                              />
          <af:outputText id="pageInfo" value="Page 1 of 1"/>
          <af:commandImageLink . . .
                             />
          </af:panelGroupLayout>
        </af:panelGroupLayout>
      </af:panelGroupLayout>
    </af:carouselItem>
    

    パフォーマンスのヒント:

    カルーセルの構造が単純なほど、実行が高速になります。


10.9.2 カルーセル・コンポーネントと各種ブラウザについて

一部のブラウザでは、カルーセルの項目の装飾がより豊富になります。たとえば、図10-40に示すように、SafariとGoogle Chromeには、カルーセルの項目の周囲にわずかに影が表示され、現行でない項目はより明るい色でオーバーレイされ、補助項目が現在の項目でないことがわかりやすくなります。

図10-40 Google Chromeに表示されるカルーセル・コンポーネント

Google Chromeでのカルーセル

図10-41に、Internet Explorerでの同じコンポーネントを示します。

図10-41 Microsoft Internet Explorerに表示されたカルーセル・コンポーネント

Internet Explorerでのカルーセル

10.10 行を値として渡す

コレクションから行全体を値として渡すことが必要になる場合があります。これを実行するには、表で行を表すために使用された変数、またはツリーでノードを表すために使用された変数を渡し、pageFlowスコープのプロパティに値として渡します。これにより、別のページでその値にスコープからアクセスできます。setPropertyListenerタグを使用すると、これを実行できます(使用の手順を含め、setPropertyListenerタグの詳細は、4.8項「ページ間の値の受渡し」を参照してください)。

たとえば、例10-26に示すように、従業員が表示された単一選択の表を含むマスター・ページがあり、ユーザーが行を1つ選択してコマンド・ボタンをクリックすると、その行のデータを編集するための新しいページにナビゲートできるようにするとします。EL変数名empは、表の1行(従業員)を表すために使用されます。commandButtonコンポーネントのaction属性値は、ユーザーによる「Employee Detail」ページへのナビゲートを可能にする静的な文字列結果showEmpDetailです。setPropertyListenerタグにはfrom値(変数emp)が使用され、toの値に格納されます。

例10-26 setPropertyListener and pageFlowScopeの使用

<af:table value="#{myManagedBean.allEmployees}" var="emp"
          rowSelection="single">
  <af:column headerText="Name">
    <af:outputText value="#{emp.name}"/>
  </af:column>
  <af:column headerText="Department Number">
    <af:outputText value="#{emp.deptno}"/>
  </af:column>
  <af:column headertext="Select">
    <af:commandButton text="Show more details" action="showEmpDetail">
      <af:setPropertyListener from="#{emp}" 
                              to="#{pageFlowScope.empDetail}" 
                              type="action"/>
    </af:commandButton>
  </af:column>
</af:table> 

ユーザーが従業員行のコマンド・ボタンをクリックすると、リスナーが実行され、表の現在行(従業員)に対応する#{emp}の値が取得されます。取得された行オブジェクトは、#{pageFlowScope.empDetail} EL式を使用してpageFlowScopeempDetailプロパティとして格納されます。静的結果によりアクション・イベントが実行され、ユーザーは詳細ページにナビゲートされます。詳細ページでは、例10-27に示すように、outputTextコンポーネントは、pageFlowScope.empDetailオブジェクトから値を取得します。

例10-27 pageFlowScopeオブジェクトの取得

<h:panelGrid columns="2">
  <af:outputText value="Firstname:"/>
  <af:inputText value="#{pageFlowScope.empDetail.name}"/>
  <af:outputText value="Email:"/>
  <af:inputText value="#{pageFlowScope.empDetail.email}"/>
  <af:outputText value="Hiredate:"/>
  <af:inputText value="#{pageFlowScope.empDetail.hiredate}"/>
  <af:outputText value="Salary:"/>
  <af:inputText value="#{pageFlowScope.empDetail.salary}"/>
</h:panelGrid> 

10.11 表、ツリーまたはツリー表からのデータのエクスポート

表、ツリーまたはツリー表、またはDVTプロジェクト・ガント・チャートの表領域からデータをMicrosoft Excelのスプレッドシートにエクスポートできます。ユーザーが表をエクスポートできるようにするには、コマンド・ボタンやコマンド・リンクなどのアクション・ソースを作成し、exportCollectionActionListenerコンポーネントを追加して、エクスポートするデータを関連付けます。すべての行がエクスポートされるように、またはユーザーが選択した行のみがエクスポートされるように表を構成できます。


ヒント:

DVTピボット・テーブルからデータをエクスポートすることもできます。詳細は、27.9項「ピボット・テーブルからのエクスポート」を参照してください。


たとえば、図10-42に、ユーザーがExcelのスプレッドシートにデータをエクスポートできるコマンド・ボタン・コンポーネントが含まれるADF Facesデモの表を示します。

図10-42 データをエクスポートするためのコマンド・ボタンがある表

コマンド・ボタンを使用するとデータをエクスポートできます

ユーザーがコマンド・コンポーネントをクリックすると、リスナーにより、すべての行のExcelへのエクスポートが処理されます。図10-42に示すように、ユーザーが選択する行のみがエクスポートされるように、exportCollectionActionListenerコンポーネントを構成することも可能です。


注意:

次のものしかエクスポートできません。

  • 値ホルダー・コンポーネント(inputoutputコンポーネントなど)の値。

  • selelctOneChoiceおよびselectOneListboxコンポーネントで使用されるselectItemコンポーネントの値(他の選択コンポーネント内のselectItemコンポーネントの値はエクスポートされません)。

  • コマンド・コンポーネントのtext属性の値。

  • imageおよびiconコンポーネントのshortDesc属性の値。


ブラウザ、およびリスナーの構成によって異なりますが、図10-43に示すように、ユーザーがスプレッドシートを開くか保存することができるダイアログがブラウザによって開かれるか、ブラウザにスプレッドシートが表示されます。たとえば、ユーザーがMicrosoft Internet Explorerでページを表示していて、exportCollectionActionListenerコンポーネントにファイル名が指定されていない場合、ファイルはブラウザに表示されます。Mozilla Firefoxでは、ダイアログが開かれます。

図10-43 Excelへのエクスポート・ダイアログ

Excelへのエクスポート・ダイアログ

ユーザーがファイルの保存を選択した場合、図10-44に示すように、後からExcelで開くことができます。ユーザーがファイルを開くことを選択した場合、その後の動作はブラウザにより異なります。たとえば、ユーザーがMicrosoft Internet Explorerでページを表示している場合、ブラウザ・ウィンドウにスプレッドシートが表示されます。ユーザーがMozilla Firefoxでページを表示している場合は、スプレッドシートがExcelで開かれます。

図10-44 Excelにエクスポートされたデータファイル

データがExcelで表示されています

注意:

ファイルがファイルの拡張子で指定された形式と異なる旨の警告がExcelで表示される場合があります。この警告は無視して問題ありません。


10.11.1 表、ツリーまたはツリー表データの外部形式へのエクスポート方法

ボタン、リンクまたはメニュー項目などのコマンド・コンポーネントを作成し、そのコンポーネントにexportCollectionActionListenerを追加します。その後、exportCollectionActionListenerコンポーネントのexportedId属性を、データをエクスポートするコレクション・コンポーネントIDに設定して、エクスポートするデータ・コレクションを関連付けます。

開始する前に:

ページに表、ツリーまたはツリー表が存在している必要があります。ない場合は、この章の指示に従って表、ツリーまたはツリー表を作成します。たとえば、表を追加するには、10.2項「表へのデータの表示」を参照してください。


ヒント:

ユーザーがエクスポートする行を選択できるようにするには、選択が許可されるよう表を構成します。詳細は、10.2.2項「表の書式設定」を参照してください。


外部形式にコレクション・データをエクスポートする手順:

  1. コンポーネント・パレットの「共通コンポーネント」パネルから、ボタンなどのコマンド・コンポーネントをページにドラッグ・アンド・ドロップします。


    ヒント:

    表、ツリーまたはツリー表にコマンド・コンポーネントのあるツールバーを作成する場合は、コレクション・コンポーネントをpanelCollectionコンポーネントで囲みます。このコンポーネントにより、ツールバー機能が追加されます。詳細は、10.7項「表メニュー、ツールバーおよびステータス・バーの表示」を参照してください。


    コマンド・コンポーネントのデフォルトのラベルを、意味のある名前(Export to Excelなど)に変更することが必要な場合があります。

  2. コンポーネント・パレットの「操作」パネルから、「エクスポート・コレクション・アクション・リスナー」をコマンド・コンポーネントの子としてドラッグします。

  3. 「エクスポート・コレクション・アクション・リスナー」ダイアログで、次の設定を行います。

    • exportedId: エクスポートする表、ツリーまたはツリー表のIDを指定します。手動で入力するか、ドロップダウン・メニューを使用して「編集」を選択します。「プロパティの編集」ダイアログを使用して、コンポーネントを選択します。

    • type: excelHTMLに設定します。

  4. exportCollectionActionListenerコンポーネントが選択された状態で、プロパティ・インスペクタで次の設定を行います。

    • filename: エクスポートするコンテンツの選択したファイル名を指定します。この属性を設定すると、通常は「ファイルの保存」ダイアログが表示されますが、最終的にはブラウザにより異なります。この属性を設定しない場合、通常、コンテンツはブラウザにインライン表示されます(可能な場合)。

    • title: エクスポートするドキュメントのタイトルを指定します。タイトルが表示されるかどうかや、どのように表示されるかは、Excelに依存します。

    • exportedRows: 表のすべての行をエクスポートするか、ユーザーが選択した行のみをエクスポートするかを指定します。表でdetailStampファセットが使用されている場合は、データをエクスポートするかどうかを選択できます(detailStampファセットの詳細は、10.3項「表への非表示機能の追加」を参照してください)。次のいずれかを設定します。

      • all: すべての行が自動的に選択され、エクスポートされます。

      • selected: ユーザーが選択した行のみがエクスポートされます。

      • allWithoutDetails: detailStampファセットのデータを除くすべての行が選択され、エクスポートされます。

      • selectedWithoutDetails: ユーザーが選択した行のみがエクスポートされます(detailStampファセットのデータを除く)。

例10-28に、表およびそのexportCollectionActionListenerコンポーネントのコードを示します。exportedId値が、表のid値に設定されていることに注意してください。

例10-28 exportCollectionActionListenerを使用した表のエクスポート

<af:table contextMenuId="thePopup" selectionListener="#{fs.Table}"
          rowselection="multiple" columnselection="multiple"
          columnBandingInterval="1"
          binding="#{editor.component}" var="test1" value="#{tableTestData}"
          id="table" summary="table data">
  <af:column>
  . . .
  </af:column>
</af:table>
<af:commandButton text="Export To Excel" immediate="true">
  <af:exportCollectionActionListener type="excelHTML" exportedId="table"
                               filename="export.xls" title="ADF Faces Export"/>

10.11.2 実行時の処理: 行の選択がエクスポートされるデータに与える影響

エクスポートされるデータは、選択したキーの順序ではなく、索引順でエクスポートされています。つまり、選択した行のエクスポートを可能にして、ユーザーが8、4、2(という順序で)行を選択すると、行はExcelに2、4、8という順序でエクスポートされて表示されます。

10.12 コレクションベースのコンポーネントからクライアント上の選択された値へのアクセス

リッチ・クライアント・フレームワークでは、クライアント側でELがサポートされないのみでなく、クライアントへのコレクション・モデル全体の送信もサポートされていないため、JavaScriptを使用してクライアント上の値にアクセスする必要がある場合、クライアント側のコードは、値にアクセスするようスタンプ設定されたコンポーネントに依存できません。各行で同じコンポーネント・インスタンスを再利用するかわりに、完全に解決されるEL式を使用して、各行に新しいJavaScriptコンポーネントが作成されます(どの行にもコンポーネントが1つ作成される必要があると仮定しています)。

そのため、クライアント上の行固有のデータにアクセスするには、それ自体がスタンプ設定されたコンポーネントを使用して値にアクセスする必要があります。クライアント側のデータ・モデルを使用せずにこれを実現するには、クライアント側の選択変更リスナーを使用します。

10.12.1 スタンプ設定されたコンポーネントの選択内容から値へのアクセス方法

コレクションベースのコンポーネントからクライアント上の値にアクセスするには、まずコンポーネントにクライアント表現があることを確認する必要があります。次に、クライアントに選択変更リスナーを登録し、そのリスナー・ハンドルで選択された行を判別して、その行のスタンプ設定された関連するコンポーネントを検索できるようにし、スタンプ設定されたコンポーネントを使用して行固有の名前を判別し、最後に、必要に応じて選択されたデータと通信する必要があります。

スタンプ設定されたコンポーネントから選択された値にアクセスする手順:

  1. ページの構造ウィンドウで、スタンプ設定された行に関連付けられたコンポーネントを選択します。たとえば、例10-29の表では、outputTextコンポーネントを使用してスタンプ設定された行が表示されています。

    例10-29 スタンプ設定された行にoutputTextコンポーネントが使用されている表コンポーネント

    <af:table var="row" value="#{data}" rowSelection="single">
      <af:column headerText="Name">
        <af:outputText value="#{row.name}"/>
      </af:column>
    </af:table>
    

    コンポーネントに次の設定を行います。

    • プロパティ・インスペクタの「共通」セクションを開き、Id属性を使用してコンポーネントに一意のIDを設定します(まだ定義されていない場合)。

    • 「拡張」セクションを開き、ClientComponent属性をTrueに設定します。

  2. コンポーネント・パレットの「操作」パネルから、client Listenerを表の子としてドラッグ・アンド・ドロップします。

  3. 「クライアント・リスナーの挿入」ダイアログで、「メソッド」フィールドに関数名(次の手順でこの関数を実装します)を入力し、「タイプ」ドロップダウンからselectionを選択します。

    たとえば、関数としてmySelectedRowを入力した場合、JDeveloperにより、例10-30に太字で示されたコードが入力されます。

    例10-30 選択を登録するためのclientListenerの使用

    <af:table var="row" value="#{data}" rowSelection="single">
      <af:clientListener type="selection" method="mySelectedRow"/>
      ...
    </af:table>
    

    このコードにより、mySelectedRow関数は、選択内容が変更されるたびにコールされます。

  4. JavaScriptライブラリで、前の手順で入力された関数を実装します。この関数により、次の操作が実行されます。

    • 選択された行を把握します。これを行うには、リスナーに渡されるイベント・オブジェクトを使用します。選択イベントの場合、イベント・オブジェクトのタイプはAdfSelectionEventです。このタイプを使用すると、getAddedSet()経由で新たに選択された行キーにアクセスできるようになり、選択された各行キーのプロパティが含まれるPOJSO(プレーンの古いJavaScriptオブジェクト)が返されます。このオブジェクトにアクセスしたら、for inループを使用して行キーを反復できます。たとえば、例10-31のコードでは、最初の行キー(この場合は唯一の行キー)が抽出されます。

      例10-31 for inループを使用した行キーの反復

      function showSelectedName(event)
      {
        var firstRowKey;
        var addRowKeys=event.getAddedSet();
      
        for(var rowKey in addedRowKeys)
        {
          firstRowKey=rowKey;
          break;
        }
      }
      
    • 選択済の行に関連付けられているスタンプ設定されたコンポーネントを検索します。クライアント側のコンポーネントAPI AdfUIComponentは、findComponent()メソッドを公開し、このメソッドでは、コンポーネントのIDを取得し、AdfUIComponentインスタンスを検索して返します。スタンプ設定されたコンポーネントを使用する際は、IDだけでなく、行キーも使用してコンポーネントを検索する必要があります。これをサポートするために、AdfUITableクラスには、IDと行キーの両方を取得するfindComponent()のオーバーロードのメソッドが用意されています。

      選択イベントの場合、コンポーネントはイベントのソースです。そのため、イベントのソースから表を取得し、その表を使用してIDおよび行キーでインスタンスを検索します。例10-32に、これを示します(この例では、nameStampが表のIDです)。

      例10-32 選択された行を指定したスタンプ設定されたコンポーネント・インスタンスの検索

      // We need the table to find our stamped component.
      // Fortunately, in the case of selection events, the
       // table is the event source.
       var table = event.getSource();
       
       // Use the table to find the name stamp component by id/row key:
       var nameStamp = table.findComponent("nameStamp", firstRowKey);
      
  5. コンポーネントを使用するために必要なその他のコードを追加します。スタンプ設定されたコンポーネントを検出したら、その他のコンポーネントの場合と同じように通信できます。たとえば、例10-33に、スタンプ設定されたコンポーネントを使用してname属性の行固有の値(例10-29で示したスタンプ設定された値)を取得し、アラートに名前を表示する方法を示します。

    例10-33 スタンプ設定されたコンポーネントの行の名前の取得

    if (nameStamp)
      {    // This is the row-specific name
        var name = nameStamp.getValue();
    
        alert("The selected name is: " + name);
      }
    

例10-34にJavaScriptの全コードを示します。

例10-34 選択された行の値へのアクセスに使用されるJavaScript

function showSelectedName(event)
{
  var firstRowKey;
  var addedRowKeys = event.getAddedSet();

  for (var rowKey in addedRowKeys)
  {
    firstRowKey = rowKey;
    break;
  }
  // We need the table to find our stamped component.
  // Fortunately, in the case of selection events, the
  // table is the event source.
  var table = event.getSource();
 
  // We use the table to find the name stamp component by id/row key:
  var nameStamp = table.findComponent("nameStamp", firstRowKey);
 
  if (nameStamp)
  {
    // This is the row-specific name
    var name = nameStamp.getValue();
 
     alert("The selected name is: " + name);
  }
}

10.12.2 選択された値へのアクセスについて

行キーはサーバーでトークン化され、クライアントの行キーには、サーバーの行キーとの類似点はありません。たとえば、クライアント側のAPI(AdfSelectionEvent.getAddedSet()など)によって処理される行キーのみが有効です。

また、対応する行がスクロールされて画面から見えなくなっていて、クライアントで使用できない場合には、AdfUITable.findComponent(id, rowKey)メソッドによりnullが戻される可能性があることに注意してください。AdfUITable.findComponent()メソッドの戻り値にnullがないか必ず確認してください。