ヘッダーをスキップ
Oracle® Fusion Middleware Oracle ADF FacesによるWebユーザー・インタフェースの開発
12c (12.1.2)
E48096-02
  目次へ移動
目次

前
 
次
 

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

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

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

12.1 コレクションベース・コンポーネントについて

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

構造化データを、複数の行と1つの列からなる単純な表として表示するにはListViewコンポーネントを使用し、複数の列に表示するにはADF Faces tableコンポーネントを使用します。階層データは、ADF Facesのツリー・コンポーネントを使用してツリー構造として表示することも、ADF Facesのツリー表コンポーネントを使用して表形式で表示することもできます。イメージのコレクションはカルーセル・コンポーネントに表示できます。図12-1に、ADF Facesのコレクションベース・コンポーネントを示します。

図12-1 ADF Facesのコレクションベース・コンポーネント

ADF Facesの表、ツリーおよびツリー表

ヒント:

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

<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:outputText label="Element Name" value="#{row.name}"/>
  <af:outputText label="Atomic Number" value="#{row.number}"/>
  <af:outputText label="Symbol" value="#{row.symbol}"/>
  <af:outputText label="Group" value="#{row.group}"/>
</af:iterator>

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


12.1.1 コレクションベース・コンポーネントのユースケースと例

コレクションベース・コンポーネントは、構造化データの表示に使用されます。たとえば、図12-2に示すように、File Explorerアプリケーションの表タブでは、選択されたディレクトリのコンテンツの表示に表が使用されています。

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

File Explorerの表コンポーネント

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

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

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

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

図12-4 File Explorerアプリケーションのツリー表

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

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

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

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

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

ツールバーを保持するpanelCollection

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

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

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

4行のlistViewコンポーネント

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

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

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

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

図12-8 ADF Facesカルーセル

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

12.1.2 コレクションベース・コンポーネントの追加機能

コレクションベース・コンポーネントを実装する前に、ADF Facesのその他の機能を理解しておくと役立ちます。また、ページにコレクションベース・コンポーネントを追加した後で、検証やアクセシビリティなどの機能を追加することが必要になる場合があります。表およびツリー・コンポーネントで使用できる他の機能へのリンクを次に示します。

  • ツールバーのカスタマイズ: 表およびツリー表コンポーネントのメニュー、ツールバーおよびステータス・バーを提供するpanelCollectionコンポーネントに含まれるツールバーをカスタマイズできます。メニュー、ツールバー、ツールバー・ボタンの詳細は、第16章「メニュー、ツールバーおよびツールボックスの使用方法」を参照してください。

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

  • アクティブ・データ: アプリケーションでアクティブ・データを使用する場合は、データ・ソースのデータが変更されるたびに、表およびツリーのデータを自動的に更新できます。詳細は、『Oracle Application Development FrameworkによるFusion Webアプリケーションの開発』の「アクティブ・データ・サービスの使用方法」の章を参照してください。


    注意:

    アクティブ・データを使用し、アプリケーションでADFビジネス・コンポーネントを使用する場合は、表が次の条件に適合する必要があります。

    • 表またはツリーが、単一の属性のみ含む同種データにバインドされていること。

    • 表でフィルタを使用しないこと。

    • ツリー・コンポーネントのnodeStampファセットに、単一のoutputTextタグが含まれ、他のタグが含まれていないこと。


  • イベント: コレクションベース・コンポーネントは、サーバー側とクライアント側両方のイベントを起動します。これに対する応答としてアプリケーションでなんらかのロジックを実行できます。詳細は、第6章「イベントの処理」を参照してください。

  • 部分ページ・レンダリング: ページ上の他のコンポーネントで実行されたアクションに基づいて、コレクションベース・コンポーネントをリフレッシュして新しいデータを表示することができます。詳細は、5.3項「最適化されたライフサイクルの使用」を参照してください。

  • パーソナライズ: コンポーネントの表示方法は実行時にユーザーが変更できますが(列の並替えや列幅の変更など)、ユーザーがそのページから移動した後もその値を維持するには、ユーザーのカスタマイズを許可するようにアプリケーションが構成されている必要があります。詳細は、第35章「JSFページでのユーザー・カスタマイズの許可」を参照してください。

  • アクセシビリティ: コンポーネントをアクセス可能にできます。詳細は、第33章「アクセス可能なADF Facesページの開発」を参照してください。

  • 自動データ・バインディング: アプリケーションでFusionテクノロジ・スタックを使用する場合は、ADFビジネス・コンポーネントがどのように構成されているかに基づいて、バインドされた表およびツリーを自動的に作成できます。詳細は、『Oracle ADF FacesによるWebユーザー・インタフェースの開発』の「ADFによるデータバインドされた表の作成」および「マスター/ディテール・データの表示」の章を参照してください。

12.2 コレクションベース・コンポーネントの共通機能

コレクションベース・コンポーネントには、データの配信方法やデータの表示と編集の方法など、多数の共通する機能があります。これらのコンポーネントを使用する前に、この共有機能と、その構成方法を理解することが重要です。

12.2.1 行およびノードへのデータの表示

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

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

例12-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クラスを拡張し、行キーおよびソートのサポートを追加します。DataModelクラスでは、行は索引によって完全に識別されます。他のユーザーが行を追加したことにより、ある行を削除するユーザー・リクエストで異なる行が削除されてしまうなど、あるリクエストから次のリクエストまでに基礎となるデータが変更される場合、この識別方法が原因で問題が発生する可能性があります。これを回避するため、CollectionModelクラスは索引ではなく行キーに基づいています。

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 ADF FacesによるWebユーザー・インタフェースの開発』の「ADFによるデータバインドされた表の作成」の章を参照してください。


12.2.2 コンテンツの配信

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

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

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


注意:

アプリケーションでFusionテクノロジ・スタックが使用されない場合は、whenAvailableのサポートをCollectionModel実装に明示的に追加する必要があります。たとえば、Facesデモ・アプリケーションのWhenAvailableData.javaマネージドBeanを参照してください。

アプリケーションでFusionテクノロジ・スタックを使用する場合は、作成されたCollectionModel実装でこれらのAPIが自動的に使用されます。



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

データのフェッチにコスト(時間)がかかると予想されるときは、遅延配信を使用する必要があります。たとえば、データベース接続が低速で待機時間が長い場合や、データベース以外の低速のデータ・ソース(たとえばWebサービス)からデータをフェッチする場合です。ページに表、ツリーまたはツリー表以外のコンポーネントが複数含まれる場合も、遅延配信を使用する必要があります。遅延配信を使用すると、データが使用可能になる前に、初期ページのレイアウト・コンポーネントおよびその他のコンポーネントが最初にレンダリングされます。

即時配信は、表、ツリーまたはツリー表がページの唯一のコンテキストである場合、またはコンポーネントが大きなデータ・セットを返さないと予想される場合に使用する必要があります。この場合、ユーザー・レスポンス時間がより高速で、サーバーCPU利用率がより高ければ、2番目のリクエストはサーバーに移動しないため、レスポンス時間は遅延配信を使用する場合よりも高速になります(または、場合によっては高速に感じます)。ただし、フェッチ・ブロックとして構成された行数のみが最初に返されます。遅延配信と同様に、ユーザーのアクションが後続のデータ・フェッチの原因となる場合は、次の行セットが配信されます。

使用可能な場合、配信は、データが初期レンダリング時に使用可能な場合には即時を使用し、データが最初は使用可能でない場合は遅延にフォールバックするという追加の柔軟性を提供します。


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

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

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

図12-9 ページ区切りの表

全270ページの表の1ページ目、ページ・ナビゲーション用のアイコンあり

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

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

表の1ページ目、前後移動のボタンあり

注意:

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

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


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


注意:

デフォルトでは、スクロールバーを使用するように表が構成されている場合に、iOSオペレーティング・システムでスクロールバーが表示されるのはコンテンツにマウスを置いたときのみとなります。他のオペレーティング・システムでもこれと同じ動作となるようにアプリケーションを構成するには、web.xmlファイルにあるoracle.adf.view.rich.table.scrollbarBehaviorパラメータを設定します。詳細は、A.2.3.30項「表におけるスクロールバーの動作」を参照してください。


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


注意:

JavaScriptを使用して、表またはツリーを動的にサイズ変更することはできません。表、ツリーおよびツリー表の高さは初めてレンダリングされるときに設定され、JavaScript APIを使用して変更することはできません。


12.2.3 行の選択

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


注意:

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

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


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


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

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

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


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

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

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

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

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

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

図12-12 一度に1行のみを編集できる表

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

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

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


注意:

ツリーと表は、ブラウザのコピー・アンド・ペーストをサポートしています。コピー可能なテキスト・フィールドにマウスを置くと、カーソルがI字状になります。マウスをクリックしてテキストをコピーすると、その行が選択された状態になります。


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

  • SelectManyCheckbox

  • SelectManyListBox

  • SelectOneListBox

  • SelectOneRadio

  • SelectManyShuttle


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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

図12-13 表は拡大されるが列は拡大されない

拡大された表

子を拡大しないコンポーネント(たとえば、verticalに設定されたpanelGroupLayoutコンポーネントの内部のpanelCollectionコンポーネント)に配置されたときは、デフォルトでは、図12-14に示すように、表の幅は300px (27.27em単位。11pxフォント設定で換算すると300px)に設定され、デフォルトのフェッチ・サイズは25行を返すように設定されます。

図12-14 表は拡大されない

表は拡大されない

子を拡大しないコンポーネントに表を配置する場合は、autoHeightRows属性を使用して、指定した行数より多く表示されないように表の高さを制御できます。この属性を正の整数に設定した場合、表の高さは行セットの数によって決定されます。その数値がfetchSize属性より大きい場合は、fetchSize属性の行数のみ返されます。autoHeightRowsを-1(デフォルト)に設定して、自動サイズ設定をオフにできます。

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


注意:

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

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


12.3 表へのデータの表示

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

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

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

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

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

縮小に設定された展開アイコン - 詳細は表示されない

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

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

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

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

12.3.1 列および列データ

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

列にはフィルタリング要素を入れることもできます。ユーザーがフィルタに値を入力すると、フィルタに入力した値に一致するデータ・セットが返されます。フィルタは、大文字と小文字を区別する、または大文字と小文字を区別しないように設定できます。これが許可されるように表が構成されている場合、ユーザーは列を並べ替えることもできます。

列には、ヘッダー・ファセットとフッター・ファセットの両方があります。ヘッダー・ファセットは、列のヘッダー・テキスト属性のかわりに使用できるため、スタイル設定可能なコンポーネントを使用できます。フッター・ファセットは、列の下部に表示されます。たとえば、図12-17では、フッター・ファセットを使用して、2つの列の下部に合計が表示されています。戻された行数が表示可能な範囲を超えている場合、フッター・ファセットは表示されますが、ユーザーは最後の行までスクロールできます。

図12-17 列のフッター・ファセット

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

12.3.2 表の書式設定

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

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

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

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


    注意:

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



    注意:

    JavaScriptを使用して、表を動的にサイズ変更することはできません。表の高さは初めてレンダリングされるときに設定され、JavaScript APIを使用して変更することはできません。


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

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

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

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


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

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


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


    注意:

    列の最小幅の合計がビューポートの表示可能領域以上である場合、表はビューポートの外部に拡張され、ビューポートの外部にアクセスするためのスクロールバーが表示されます。



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

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



    注意:

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


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

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

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

12.3.3 列の書式設定

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

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

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

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

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


    ヒント:

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


  • 列の幅: width属性を使用して、列の幅をピクセル単位の絶対値として指定できます。列を拡大可能として構成する場合、幅を割合として設定することもできます。

  • 列のまたがり: colSpan属性を使用して、他の列にまたがる列を構成できます。ただし、通常は、spanの値にEL式を使用して、実際には列の特定のセルのみが複数列にまたがることができるようにします。たとえば、図12-18に示すツリー表では、そのノードが親ノードである場合のみに、右にあるすべての行にまたがるようにcolSpanの値が設定されています。

    図12-18 複数列にまたがるのはノードが親のときのみ

    複数列にまたがるのはノードが親のときのみ
  • 行折返し: noWrap属性を使用し、行を越えて列のコンテンツを折り返すかどうかを定義できます。デフォルトでは、コンテンツは折り返されません。

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

    図112-19 表の行ヘッダー

    表の行ヘッダー

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

    図12-20 行ヘッダーの選択アイコン

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

複数選択が許可される表では、ユーザーはマウスをクリックして行ヘッダーをドラッグし、連続した行ブロックを選択できます。また、ユーザーが上または下にドラッグすると、表が垂直に自動スクロールします。

加えて、エラーが発生した結果としてその行のコンポーネントに対するメッセージが生成された場合は、重大度を表すアイコンが行ヘッダーに表示されます。複数のメッセージが存在する場合は、重大度が最も高いアイコンが表示されます。図12-21で行ヘッダーにエラーのアイコンが表示されているのは、入力された日付が正しくないからです。

図12-21 行ヘッダーに表示されるメッセージ・アイコン

エラーのある表の行と重大度を示すアイコン

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

行ヘッダーを使用すると表の複雑さが増し、パフォーマンスに悪影響が及ぶことがあります。



ヒント:

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


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

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


注意:

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


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

始める前に:

属性が機能に与える影響に関する知識が役立つ場合があります。詳細は、12.3項「表へのデータの表示」を参照してください。

他のADF Faces機能を使用して追加できる機能について理解することが役立つ場合もあります。詳細は、12.1.2項「コレクションベース・コンポーネントの追加機能」を参照してください。

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

  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. 「コンポーネント」ウィンドウの「データ・ビュー」パネルから、「表」をページにドラッグ・アンド・ドロップします。

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


    注意:

    inputTextコンポーネントを使用してCharacter Large Object (CLOB)を表示する場合は、CLOBを文字列に変換するカスタム・コンバータを作成する必要があります。変換の詳細は、第7章の「カスタムADF Facesコンバータの作成」を参照してください。


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

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


      注意:

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


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

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

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


    ヒント:

    リストに表示されていないコンポーネントを使用する場合は、「プロパティ」ウィンドウで任意のコンポーネントを選択してから、手動で変更してください。

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

    2. リストから必要なコンポーネントを選択します。これで、「プロパティ」ウィンドウを使用して新しいコンポーネントを構成できます。



    ヒント:

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

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

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

    3. panelGroupLayoutを選択します。


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

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


      ヒント:

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


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


      注意:

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



      注意:

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



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

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


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

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

      • 名前が指定された列: 現在表にある列を拡大する列として選択できます。

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

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

      • multiple: width属性にパーセント値が設定されたすべての列がそのパーセント値まで拡大されます。これは、他の列が(拡大されない)幅にレンダリングされた後に行われます。割合値は合計で加重されます。たとえば、これらの列のwidth属性を50%に設定した場合、各列は、他のすべての列がレンダリングされた後の残り領域の1/3を占めます。


      ヒント:

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


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

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

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

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

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

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


      注意:

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


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

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

    • ColumnResizing: エンド・ユーザーが実行時に列の幅をサイズ変更できるようにするかどうかを指定します。disabledに設定した場合、列の幅はページがレンダリングされた後で設定され、ユーザーはそれらの幅を変更できません。


      ヒント:

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


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


      注意:

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


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


      ヒント:

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


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

    • AutoHeightRows: 表に初期状態で表示する行の数を指定します。返された行の数がこの値を超えている場合は、スクロールバーが表示されます。表がfetchSizeと同じサイズになるようにするには、0に設定します。表の親コンテナが子を拡大するように構成されている場合に親コンテナいっぱいに表が拡大されるようにするには、-1を設定します(表の拡大の詳細は、12.2.7項「表、ツリーおよびツリー表コンポーネントのジオメトリ管理」を参照)。それ以外の場合は、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.29項「レイアウトと表コンポーネントの形状管理」を参照してください。


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


      注意:

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


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


      ヒント:

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


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

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

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

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

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

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


      注意:

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


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

    • BlockRowNavigationOnError: 検証エラーが存在する行からユーザーが移動できるようにする場合に指定します。alwaysに設定すると、行の検証エラーが発生したときは常に、ユーザーが別の行に移動することは禁止されます。neverに設定すると、ユーザーが別の行への移動を禁止されることはなくなります。auto (デフォルト)に設定すると、ユーザーが移動できるかどうかはフレームワークによって決定されます。

      たとえば、表の値がそのページ上の別のコンポーネントとの間で共有されていることがあります。1つの表で、ユーザーが多数のレコードを表示できるようになっているとします。特定のレコードが選択されたときに、その情報がフォーム内に表示されます。ユーザーがそのフォームでデータを変更したことが原因でエラーが発生した場合に、ユーザーが表をスクロールしてそのレコードから移動することができないようにするとします。この例の場合は、BlockRowNavigationOnErrorを「always」に設定します。

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

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

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

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

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

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

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

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

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

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


      注意:

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


    • SortStrength: ソート時に重要とみなされる差異のレベルを指定します。次の1つを選択します(これらの値は、Java Collatorオブジェクトでの値と同じです)。

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

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

      • Tertiary: 文字を考慮してソートされ、その後でアクセント記号、大文字と小文字の違いの順に考慮されます。abcÁBCábcABCをソートするとabcABCábcÁBCとなります。アクセントのないロケールでは、結果的に大文字と小文字を区別する検索が行われます。

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

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


      注意:

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


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

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

    • Width: 列の幅を指定します。表で列の拡大を使用する場合は、幅の割合を入力する必要があります。

      列の拡大では、列の幅の割合が重みとして扱われます。たとえば、すべての列が50%の幅で、3つを超える列がある場合、各列には領域が均等に割り当てられますが、依然としてminWidth属性に設定された値が適用されます。

      割合としての幅は領域の実際の割合ではなく重みであるため、表で列の拡大がオンになっていて、1列のみが割合の幅で拡大されるものとしてリストされている場合、その列は、残りの列のピクセル幅で指定されていない、表の残り領域をすべて使用します。

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

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

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

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


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

      行ヘッダーを使用すると表の複雑さが増し、パフォーマンスに悪影響が及ぶことがあります。


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

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

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


      注意:

      デフォルトでは、この列とそれよりも左の列が固定されます。つまり、この列とそれよりも左にある列はスクロールされません。これを変更するには、表コンポーネントのfreezeDirection属性をendに設定します。デフォルトでは、startに設定されています。



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

      固定された列を使用すると表の複雑さが増し、パフォーマンスに悪影響が及ぶことがあります。


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

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

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

    例12-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>
    

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

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

    public class TestBean 
    {
      public boolean isContainer() 
      {
        return _treeTable.isContainer();
      }
    }
    
  14. 既存の表に列を追加するには、「構造」ウィンドウで表を右クリックし、「表の中に挿入」「列」を選択します。

  15. 表にファセットを追加するには、表を右クリックして「ファセット - 表」を選択し、追加するファセットのタイプを選択します。その後、ファセットに直接コンポーネントを追加できます。


    ヒント:

    JSPまたはJSPX上のファセットに配置できる子コンポーネントは1つのみであるため、複数の子コンポーネントを追加する場合は、これらの子コンポーネントを1つのコンテナ(たとえばpanelGroupLayoutコンポーネントやgroupコンポーネント)の中にラップする必要があります。Faceletページ上のファセットには、複数のコンポーネントを配置できます。


  16. 列にファセットを追加するには、列を右クリックして「ファセット - 列」を選択し、追加するファセットのタイプを選択します。その後、ファセットに直接コンポーネントを追加できます。


    ヒント:

    JSPまたはJSPX上のファセットに配置できる子コンポーネントは1つのみであるため、複数の子コンポーネントを追加する場合は、これらの子コンポーネントを1つのコンテナ(たとえばpanelGroupLayoutコンポーネントやgroupコンポーネント)の中にラップする必要があります。Faceletページ上のファセットには、複数のコンポーネントを配置できます。


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

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


    ヒント:

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

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


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

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

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

例12-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>

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

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

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

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

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

12.3.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つの列のみソートします。複数列のソートはサポートされていません。


12.3.8 表の選択された行でのアクションの実行に関する必知事項

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

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

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

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

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

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

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

例12-5 行の選択

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

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

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

public void performDelete(ActionEvent action)
{
  UIXTable table = getTable();
  Iterator selection = table.getSelectedRowKeys().iterator();
  Object oldKey = table.getRowKey();
  try
  {
    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();
    }
  }
  finally
  {
    // restore the old key:
    table.setRowKey(oldKey);
  }
}

12.3.9 表の選択コンポーネント値の動的な決定に関する必知事項

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

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

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

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

例12-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;
}

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

例12-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>

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

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


注意:

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


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

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

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

図12-24 表示されているdetailStampファセット

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

ファセットのrendered属性にEL式を使用して、切替えアイコンと詳細を表示するかどうかを決定できます。たとえば、ショッピング・カート・ページでdetailStampファセットを使用して、ギフト・ラッピング情報を表示するとします。ただし、すべての注文アイテムにギフト・ラッピング情報があるわけではないため、注文アイテムに表示する情報がある場合にのみ切替えアイコンを表示します。表示する情報があるかどうかを決定するメソッドをマネージドBeanに作成し、rendered属性をそのメソッドにバインドできます。図12-25に、表示する情報がある行に対してのみアイコンが表示されている同じ表を示します。

図12-25 条件付きdetailStampファセット

すべての行に詳細インジケータが表示されるわけではない

注意:

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


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

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

始める前に:

属性が機能に与える影響に関する知識が役立つ場合があります。詳細は、12.4項「表への非表示機能の追加」を参照してください。

他のADF Faces機能を使用して追加できる機能について理解することが役立つ場合もあります。詳細は、12.1.2項「コレクションベース・コンポーネントの追加機能」を参照してください。

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

  1. ファセットに表示するコンポーネントを、「コンポーネント」ウィンドウから「構造」ウィンドウのdetailStampファセットにドラッグします(図12-26を参照)。

    図12-26 構造ウィンドウのdetailStampファセット

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

    注意:

    JSPまたはJSPX上のファセットに配置できる子コンポーネントは1つのみであるため、複数の子コンポーネントを追加する場合は、子コンポーネントをコンテナ(たとえばpanelGroupLayoutまたはgroupコンポーネント)の内側にラップする必要があります。Faceletページ上のファセットには、複数のコンポーネントを配置できます。



    ヒント:

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


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

    例12-9の省略形のコードは、図12-24に示したdetailStampファセットの表示に使用されているものです。この図では、選択された行の詳細が表示されています。

    例12-9 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>
    
  3. detailStampファセットにそのアイコンとコンポーネントを条件付きで表示する場合は、ファセットのrendered属性を、ファセットをレンダリングする必要があるかどうかを決定するマネージドBeanのメソッドに設定します。


注意:

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


12.4.2 実行時に行われる処理: rowDisclosureEvent

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

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

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

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

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

図12-27 フィルタ処理された表

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

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

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


注意:

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


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

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

<af:table value="#{myBean.products}" var="row"
          queryListener="#{tableFilter.processTableFilter}"
          filterModel="#{tableFilter.queryDescriptor}"
               ...
          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>

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

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

始める前に:

属性が機能に与える影響に関する知識が役立つ場合があります。詳細は、12.5項「表でのフィルタ処理の有効化」を参照してください。

他のADF Faces機能を使用して追加できる機能について理解することが役立つ場合もあります。詳細は、12.1.2項「コレクションベース・コンポーネントの追加機能」を参照してください。

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

  1. FilterableQueryDescriptorクラスのサブクラスであるJavaクラスを作成します。ConjunctionCriterionオブジェクトを返すように実装する必要があります。このクラスの詳細は、Oracle ADF Faces Java APIリファレンスを参照してください。

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

  3. 「構造」ウィンドウで表を選択し、次の属性を「プロパティ」ウィンドウで設定します。

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

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

    • QueryListener: 表フィルタを処理するリスナー・メソッドにバインドします。


    ヒント:

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

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

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

    3. コンポーネントの値を、手順1で作成したFilterableQueryDescriptorクラスのgetFilterConjunctionCriterionメソッドから返されたConjunctionCriterionオブジェクトとなるように設定します。値では、次の例のように、行に使用される変数を考慮する必要があります。

      #{af:inputDate label="Select Date" id="name"
                     value="row.queryDescriptor.
                            filterConjunctionCriterion.criterionMap.
      Hiredate.value"}

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

    • Filterable: trueに設定します。

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

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

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

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

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

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

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

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

例12-11に示すように、TreeModelクラスの作成時には、org.apache.myfaces.trinidad.model.ChildPropertyTreeModelクラスが便利です。

例12-11 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 ADF FacesによるWebユーザー・インタフェースの開発』の「マスター/ディテール・データの表示」の章を参照してください。


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


注意:

JavaScriptを使用して、ツリーを動的にサイズ変更することはできません。ツリーの高さは初めてレンダリングされるときに設定され、JavaScript APIを使用して変更することはできません。


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

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

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

例12-12 ツリーへのデータの表示

<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コンポーネントの使用方法の詳細は、12.9項「表メニュー、ツールバーおよびステータス・バーの表示」を参照してください。


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

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

始める前に:

属性が機能に与える影響に関する知識が役立つ場合があります。詳細は、12.6項「ツリーへのデータの表示」を参照してください。

他のADF Faces機能を使用して追加できる機能について理解することが役立つ場合もあります。詳細は、12.1.2項「コレクションベース・コンポーネントの追加機能」を参照してください。

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

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

  2. 「コンポーネント」ウィンドウの「データ・ビュー」パネルから、「ツリー」をドラッグ・アンド・ドロップして「ツリーの挿入」ダイアログを開きます。

  3. 必要に応じてツリーを構成します。ダイアログのヘルプを参照するには、「ヘルプ」をクリックするか、[F1]を押します。

  4. 「プロパティ」ウィンドウの「データ」セクションを開いて、次の属性を設定します。

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

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

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

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

      • index: 現在行の索引

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

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

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

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

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

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

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

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

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

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

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

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

    • AutoHeightRows: スクロール・バーを表示する前に表示するノードの最大数に設定します。デフォルト値は-1です(いくつであっても自動サイズ設定は行われません)。値を0に設定して、fetchSizeと同じ値にすることができます。


      注意:

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

      • inlineStyle属性に高さを指定しても効果はなく、AutoHeightRowsの値でオーバーライドされます。

      • inlineStyle属性にmin-heightまたはmax-heightを指定すると、autoHeightRows属性との間に矛盾が生じるため、このような指定はしないでください。

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


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

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

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

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

  8. データをツリーに表示するためのコンポーネントを追加するには、目的のコンポーネントを「コンポーネント」ウィンドウからnodeStampファセットにドラッグします。図12-29に、File Explorerアプリケーションのディレクトリの表示に使用されたツリーのnodeStampファセットを示します。

    図12-29 構造ウィンドウのnodeStampファセット

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

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


    ヒント:

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


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

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

例12-13 JSFページ内の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>

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

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

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

12.6.4 プログラムを使用したノードの開閉に関する必知事項

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

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

例12-14 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}">

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

例12-15 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属性として格納されます。例12-16に示すように、このインスタンスを使用して、階層内のノードの開いた状態または閉じた状態をプログラムで制御できます。RowKeySetインスタンスに含まれるノードは開かれ、その他すべてのノードは閉じられます。addAll()メソッドによりすべての要素がセットに追加され、removeAll()メソッドによりすべてのノードがセットから削除されます。

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

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

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

例12-17 行キーを処理するためのバッキング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;
}

12.6.5 プログラムを使用したノードの選択に関する必知事項

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

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

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

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

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

図12-30 File Explorerアプリケーションのツリー表

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

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


注意:

nodeStampファセットは、1列のみ含むことができます(これがツリーのノードになります)。


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

例12-18 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>

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

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

ツリー表を作成するには、「ツリー表の挿入」ウィザードを使用します。ウィザードが完了したら、「プロパティ」ウィンドウを使用してツリー表の追加プロパティを構成できます。

始める前に:

属性が機能に与える影響に関する知識が役立つ場合があります。詳細は、12.7項「ツリー表へのデータの表示」を参照してください。

他のADF Faces機能を使用して追加できる機能について理解することが役立つ場合もあります。詳細は、12.1.2項「コレクションベース・コンポーネントの追加機能」を参照してください。

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

  1. 「コンポーネント」ウィンドウの「データ・ビュー」パネルから、「ツリー表」をページにドラッグ・アンド・ドロップして、「ツリー表の挿入」ウィザードを開きます。

  2. ウィザードを完了することで表を構成します。ウィザードのヘルプを参照するには、「ヘルプ」をクリックするか[F1]を押します。

  3. 「プロパティ」ウィンドウを使用して、その他の属性を必要に応じて構成します。


    ヒント:

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


12.8 行を値として渡す

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

たとえば、マスター・ページにある単一選択の表に従業員を一覧表示し、ユーザーが行の1つを選択してボタンをクリックすると、その行のデータを編集するための新しいページに移動できるようにするとします(例12-19を参照)。EL変数名empは、表の1行(従業員)を表すために使用されます。buttonコンポーネントのaction属性値は、静的な文字列結果showEmpDetailです。これで、ユーザーが従業員詳細ページに移動できるようになります。setPropertyListenerタグにはfrom値(変数emp)が使用され、toの値に格納されます。

例12-19 setPropertyListenerおよび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:button text="Show more details" action="showEmpDetail">
      <af:setPropertyListener from="#{emp}" 
                              to="#{pageFlowScope.empDetail}" 
                              type="action"/>
    </af:button>
  </af:column>
</af:table> 

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

例12-20 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> 

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

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

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

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

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

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

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

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

例12-21 表、メニューおよびツールバーを含む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:button shortDesc="Create" icon="/new_ena.png">
      </af:button>
      <af:button shortDesc="Update" icon="/update_ena.png">
      </af:button>
      <af:button shortDesc="Delete" icon="/delete_ena.png">
      </af:button>
    </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コンポーネント内で、メニューを連結解除可能にできます。詳細は、16.2項「メニュー・バーでのメニューの使用方法」を参照してください。ユーザーに次のいずれかを期待する場合は、連結解除可能メニューの使用を検討してください。

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

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

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

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


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

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

始める前に:

属性が機能に与える影響に関する知識が役立つ場合があります。詳細は、12.9項「表メニュー、ツールバーおよびステータス・バーの表示」を参照してください。

他のADF Faces機能を使用して追加できる機能について理解することが役立つ場合もあります。詳細は、12.1.2項「コレクションベース・コンポーネントの追加機能」を参照してください。

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

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

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

  2. オプションで、特定のツールバーおよびメニュー項目をオフにして、panelCollectionツールバーをカスタマイズします。そのためには、「構造」ウィンドウでpanelCollectionコンポーネントを選択します。「プロパティ」ウィンドウで、featuresOff属性を設定します。表12-1に、有効な値とツールバーでのそれぞれの効果を示します。

    表12-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ファセットに「メニュー」をドロップし、同じファセットに「メニュー項目」をドロップしてメニュー・リストを作成します。メニューおよびツールバーの詳細は、第16章「メニュー、ツールバーおよびツールボックスの使用方法」を参照してください。

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

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

図12-32 1つのlistItemコンポーネントを持つlistViewコンポーネント

listViewコンポーネントとlistItem

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

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

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

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

例12-22 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:button id="cb1" text="Action"
                      shortDesc="Click To Invoke Action for Item #{vs.index + 1}">
          <af:showPopupBehavior popupId="::popupDialog"
                               alignId="cb1" align="afterStart"/>
        </af:button>
      </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クラスの詳細は、第12.6項「ツリーへのデータ表示」を参照)。

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

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

図12-34 listViewコンポーネントの単純な階層

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

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

例12-23 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コンポーネントに階層を表示する場合は、図12-35に示すように、ヘッダーで子コンポーネントを表示または非表示にできるように構成できます。

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

listViewコンポーネントの一部の子を表示し、一部を非表示にした状態

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

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

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

12.10.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. 「コンポーネント」ウィンドウの「データ・ビュー」パネルから、「リスト・ビュー」をページにドラッグ・アンド・ドロップします。

  3. 「プロパティ」ウィンドウの「その他」セクションを開いて、次のとおりに設定します。

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

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

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

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

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

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

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

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

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

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

    図12-36 構造ウィンドウのgroupHeaderStampファセット

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

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

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

図12-37 ADF Facesカルーセル

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

デフォルトでは、カルーセルは水平に表示されます。カルーセルの水平方向のオブジェクトは中央に垂直に整列され、カルーセル自体はそのコンテナの中央に水平に整列されます。

参照ローロデックス(回転式カード・ファイル)が必要な場合は、垂直に表示されるようにカルーセルを構成できます。デフォルトでは、垂直方向のカルーセルの中のオブジェクトは水平方向の中央がそろうように整列され、カルーセル自体は垂直方向の中央に整列されます(図12-38を参照)。カルーセルの位置合せ属性を使用して、位置合せを変更できます。

図12-38 垂直カルーセル・コンポーネント

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

ベスト・プラクティス:

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


前後のイメージを部分的に表示するかわりに、映写フィルム風デザインで(図12-39を参照)、またはルーミー・サーキュラー・デザインで(図12-40を参照)イメージを表示するようにカルーセルを構成することができます。

図12-39 カルーセルの映写フィルム風表示

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

図12-40 カルーセルのルーミー・サーキュラー表示

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

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

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

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

カルーセルに現在のイメージのみを表示するように構成することもできます(図12-42を参照)。

図12-42 カルーセルにイメージを1つだけ表示できる

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

イメージの一覧表示に使用されるコントロールを構成できます。前後への矢印付きの、複数のイメージにまたがるスライダを表示することも、前後へのボタンのみを表示することも(図12-42を参照)、前後へのボタンとスライド・カウンタを表示することもできます(図12-43を参照)。

図12-43 スライダのない次および前ボタン

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

carouselItemコンポーネントは、カルーセルにオブジェクトとそのオブジェクトのタイトルを表示します。表示するオブジェクトごとにcarouselItemコンポーネントを作成し、これらのコンポーネントを個々のオブジェクトにバインドするかわりに、carouselコンポーネントを完全なコレクションにバインドします。ツリーが各データ行をスタンプ・アウトするのと同様の方法で、コンポーネントは、各項目の値をスタンプ処理することで1つのcarouselItemコンポーネントを繰り返しレンダリングします。各項目にスタンプが設定されると、現在の項目のデータが、carouselコンポーネントvar属性を使用するEL式を使用して特定可能なプロパティにコピーされます。カルーセルのレンダリングが完了したら、このプロパティは削除されるか前の値に戻ります。カルーセルには、テキストの表示に使用されるcarouselItemコンポーネントのホルダーと各項目の短い説明の両方であり、各項目について表示されるイメージの親コンポーネントでもあるnodeStampファセットが含まれます。

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

例12-24 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 Application Development FrameworkによるFusion Webアプリケーションの開発』の「ADF Facesカルーセル・コンポーネントの使用」の章を参照してください。


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


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

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

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


スライダ・コントロールでは、ユーザーはコレクションをナビゲートできます。通常、スライダ上のサムにはオブジェクトの総数のうちの現在のオブジェクト番号(6/20など)が表示されます。オブジェクトの総数が大きすぎて計算できない場合、スライダ上のサムには現在のオブジェクト番号のみ表示されます。たとえば、会社の従業員電話帳にカルーセルが使用されているとします。デフォルトでは、電話帳には全従業員の顔写真が表示されますが、コストの高いデータベース・コールを行わないと、その日システムに厳密に94,409人の従業員がいることがわからない場合があります。

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

12.11.1 カルーセルの作成方法

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

始める前に:

属性が機能に与える影響に関する知識が役立つ場合があります。詳細は、12.11項「カルーセルでのイメージの表示」を参照してください。

他のADF Faces機能を使用して追加できる機能について理解することが役立つ場合もあります。詳細は、12.1.2項「コレクションベース・コンポーネントの追加機能」を参照してください。

表示するイメージのコレクションを提供するデータ・モデルを作成します。データ・モデルは、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クラスを参照してください。

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

  1. 「コンポーネント」ウィンドウの「データ・ビュー」パネルから、「カルーセル」をページにドラッグ・アンド・ドロップします。


    ベスト・プラクティス:

    子を拡大する親コンテナにカルーセルを配置します。


  2. 「プロパティ」ウィンドウで「共通」セクションを開き、次の設定を行います。

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

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

      • center: 中心点が同一になるように項目を位置合せします。これがデフォルトです。

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

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

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

      • middle: 中央点が同一になるように項目を位置合せします。これがデフォルトです。

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

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

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

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

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

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

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

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

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

    • EmptyText: 項目が返されない場合に表示するテキストを入力します。リソース・バンドルを使用している場合は、ドロップダウン・メニューを使用して「テキスト・リソースの選択」を選択します。

  5. 子を拡大する親コンポーネントにカルーセルを配置しない場合、カルーセルは幅500px、高さ300pxで表示されます。これらの設定は変更できます。そのためには、「スタイル」セクションを開き、「レイアウト」タブをクリックして高さと幅をピクセル単位で設定します。

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

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

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

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

      例12-25 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: オフセット・シフトをコントロールする値を入力します。カルーセルの項目は、現在のカルーセル項目の方向にある最も近い項目を基準として、この値に従ってシフトされます(DisplayItemsモードがcircularのとき)。

    • AuxiliaryPopOut: hoverを選択すると、補助アイテムにマウス・ポインタを置いたときにそのアイテムがフル・サイズでレンダリングされ、不透明のオーバーレイが除去されます。

    • AuxiliaryScale: サイズ・スケーリングをコントロールする値を入力します。カルーセルの項目は、現在のカルーセル項目の方向にある最も近い項目を基準として、この値に従って拡大されます(DisplayItemsモードがcircularのとき)。値が1の場合は、補助アイテムはすべて同じサイズになります。値が1より小さい場合は、補助アイテムは現在の項目から離れるに従って小さくなります。値が1より大きい場合は、補助アイテムは現在の項目から離れるに従って大きくなります。

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

      • full: スライダに、組込みの次および前ボタン、現在の項目テキストおよびイメージ番号が表示されます。これがデフォルトです。

      • compact: 次および前ボタンと項目テキストのみ表示されます。

      • small: 次および前ボタンが、現在の項目テキストおよびイメージ番号とともに表示されます。

      • none: スライダは表示されません。

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


      ヒント:

      DisplayItemsモードがcircularモードの場合にルーミー・サーキュラー・デザインを実現するには、AuxiliaryScaleを0.8、AuxiliaryOffsetを0.8に設定します。アイテムを循環モードの映写フィルム風デザインで表示するには、AuxiliaryScaleを1.0、AuxiliaryOffsetを1.1に設定します。


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

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

  10. 「コンポーネント」ウィンドウの「一般コントロール」パネルから、イメージをドラッグしてcarouselItemの子としてドロップします。

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

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

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

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

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

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

    <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:link . . .
                              />
          <af:outputText id="pageInfo" value="Page 1 of 1"/>
          <af:link . . .
                             />
          </af:panelGroupLayout>
        </af:panelGroupLayout>
      </af:panelGroupLayout>
    </af:carouselItem>
    

    例12-27に、対応するJavaScriptを示します。

    例12-27 マウス・オーバーとマウス・ダウンを処理するJavaScriptコード

    function handleItemOver(uiInputEvent)
    {
      var imageComponent = uiInputEvent.getCurrentTarget();
      var carousel = null;
      var componentParent = imageComponent.getParent();
      while (componentParent != null)
      {
        if (componentParent instanceof AdfRichCarousel)
        {
          carousel = componentParent;
        }
        componentParent = componentParent.getParent();
      }
      if (carousel == null)
      {
        AfLogger.LOGGER.severe("Unable to find the carousel component!");
        return;
      }
      var currentItemKeyPattern = ":"+ carousel.getCurrentItemKey() +":";
     
    var overlayHeaderComponent = imageComponent.findComponent("overHead");
    var overlayHeaderId = overlayHeaderComponent.getClientId();
    // In IE we get mouseover for other items as well. This is despite having an
    // overlay div on top
    if(overlayHeaderId.indexOf(currentItemKeyPattern) == -1)
    return;
    if (overlayHeaderId != window._myHeader)
    {
      // ensure only one set of overlays are visible
      hideExistingOverlays();
    }
    var overlayFooterComponent = imageComponent.findComponent("overFoot");
     
    window._myHeader = overlayHeaderComponent.getClientId();
    window._myFooter = overlayFooterComponent.getClientId();
     
    // do not propagate to the server otherwise all stamps will get this property on
    // next data fetch
    overlayHeaderComponent.setProperty("inlineStyle", "display:block", false, AdfUIComponent.PROPAGATE_LOCALLY);
              overlayFooterComponent.setProperty("inlineStyle", "display:block", false, AdfUIComponent.PROPAGATE_LOCALLY);
    }
     
    function handleItemDown(uiInputEvent)
      {
        if (uiInputEvent.isLeftButtonPressed())
        {
          // Only hide the overlays if the left button was pressed
          hideExistingOverlays();
        }
      }
     
    

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

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


12.11.2 カルーセル・コンポーネントと各種ブラウザに関する必知事項

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

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

Google Chromeでのカルーセル

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

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

Internet Explorerでのカルーセル

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

表、ツリーまたはツリー表から、あるいはデータ視覚化プロジェクトのガント・チャートの表領域から、データをMicrosoft Excelスプレッドシートまたはカンマ区切り形式(CSV)ファイルにエクスポートできます。ユーザーが表をエクスポートできるようにするには、エクスポートの起動に使用するアクション・ソース(ボタンやリンクなど)を作成し、exportCollectionActionListenerコンポーネントを追加して、エクスポートするデータに関連付けます。exportCollectionActionListenerを構成するときに、表またはツリーのすべての行をエクスポートするか、ユーザーが選択した行のみをエクスポートするかを指定します。


ヒント:

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


たとえば、図12-47に示すADF Facesデモ・アプリケーションの表には、ユーザーがデータをExcelのスプレッドシートに、またはCSVファイルとしてエクスポートするためのボタンがあります。

図12-47 データをエクスポートするためのボタンがある表

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

ユーザーがボタンの1つをクリックすると、すべての行をスプレッドシートまたはCSVにエクスポートする処理がリスナーによって実行されます。図12-47に示すように、ユーザーが選択する行のみがエクスポートされるように、exportCollectionActionListenerコンポーネントを構成することも可能です。

次の値のみエクスポートできます

imageコンポーネントおよびiconコンポーネントのshortDesc属性の値がエクスポートされないようにするには(たとえば、セル内にイメージがある場合)、事前定義済のskipObjectComponentフィルタ・メソッドを使用します。このメソッドはexportCollectionActionListenerの前に実行され、実行するとObjectコンポーネントはエクスポートされなくなります。独自のフィルタ・メソッドを作成して任意の必要なロジックをexportCollectionActionListenerの実行前に適用することもできます。

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

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

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

ユーザーがファイルの保存を選択した場合は、後でそのファイルをスプレッドシート・アプリケーションで開くことができます(図12-49を参照)。ユーザーがファイルを開くことを選択した場合、その後の動作はブラウザにより異なります。たとえば、ユーザーがページをMicrosoft Internet Explorerで見ているときにスプレッドシートをエクスポートした場合は、スプレッドシートはブラウザ・ウィンドウに表示されます。ユーザーがMozilla Firefoxでページを表示している場合は、スプレッドシートがExcelで開かれます。

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

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

注意:

スプレッドシートの場合は、ファイルのフォーマットがファイル拡張子で指定されたものとは異なるというExcelの警告が表示されることがあります。この警告は無視して問題ありません。


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

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

始める前に:

属性が機能に与える影響に関する知識が役立つ場合があります。詳細は、12.12項「表、ツリーまたはツリー表からのデータのエクスポート」を参照してください。

他のADF Faces機能を使用して追加できる機能について理解することが役立つ場合もあります。詳細は、12.1.2項「コレクションベース・コンポーネントの追加機能」を参照してください。

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


ヒント:

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


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

  1. 「コンポーネント」ウィンドウの「一般コントロール」パネルから、コマンド・コンポーネント(たとえばボタン)をページにドラッグ・アンド・ドロップします。


    ヒント:

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


    コマンド・コンポーネントのデフォルトのラベルを、意味のある名前(たとえば「スプレッドシートにエクスポート」)に変更することをお薦めします。

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

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

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

    • Type: excelHTMLに設定すると、Microsoft Excelスプレッドシートにエクスポートされます。CSVに設定すると、カンマ区切り値形式ファイルにエクスポートされます。

  4. exportCollectionActionListenerコンポーネントがまだ選択されている状態で、「プロパティ」ウィンドウで次のとおりに設定します。

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

    • Title: エクスポートするドキュメントのタイトルを指定します。タイトルを表示するかどうか、およびどれくらいの精度で表示するかは、スプレッドシート・アプリケーションに依存します。

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

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

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

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

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

    • RowLimit: エクスポートできる行の最大数を表す数値を入力します。制限なしの場合は、-1を入力します。

    • Charset: デフォルトではUTF-8が使用されます。必要であれば、別のキャラクタ・セットを指定できます。

    • FilterName: skipObjectComponentと入力すると、任意のObjectコンポーネントを処理対象から除外するための組込みメソッドが実行されるようになります。

    • FilterMethod: 評価結果がメソッドとなるようなEL式を入力します。このメソッドは、必要なオーバーライド・ロジックを処理するExportCollectionActionListenerの前に起動されます。

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

例12-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:button text="Export To Excel" immediate="true">
  <af:exportCollectionActionListener type="excelHTML" exportedId="table"
                               filename="export.xls" title="ADF Faces Export"/>

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

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

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

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

したがって、クライアント上で行固有のデータにアクセスするには、コレクションベース・コンポーネントそのものを使用して値にアクセスする必要があります。クライアント側のデータ・モデルを使用せずにこれを実現するには、クライアント側の選択変更リスナーを使用します。

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

コレクションベースのコンポーネントからクライアント上の値にアクセスするには、まずコンポーネントにクライアント表現があることを確認する必要があります。その後で、選択変更リスナーをクライアント上で登録する必要があります。そのリスナーは、選択された行を特定し、その行に対応するスタンプされたコンポーネントを見つけ、このコレクション・コンポーネントを使用して行固有の名前を特定し、選択されたデータに対して必要な操作を行うように設定する必要があります。

始める前に:

他のADF Faces機能を使用して追加できる機能について理解することが役立つ場合もあります。詳細は、12.1.2項「コレクションベース・コンポーネントの追加機能」を参照してください。

コレクションベース・コンポーネントから選択された値にアクセスする手順:

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

    例12-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属性を使用して設定します。

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

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

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

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

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

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

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

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

    • どの行が選択されているかを調べます。そのためには、リスナーに渡されるイベント・オブジェクトを使用します。選択イベントの場合、イベント・オブジェクトのタイプはAdfSelectionEventです。このタイプは、選択された各行キーのプロパティを含むPOJSO (plain old JavaScript object)を返すgetAddedSet()メソッドを介して、新規に選択された行キーへのアクセスを可能にします。このオブジェクトへのアクセスが可能になったら、"for in"ループを使用して行キーを反復できます。たとえば、例12-31のコードは最初の行キー(この場合は唯一の行キー)を抽出します。

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

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

      選択イベントの場合、コンポーネントはイベントのソースです。したがって、コレクション・コンポーネントをイベントのソースから取得し、このコレクション・コンポーネントを使用してそのIDと行キーを使用するインスタンスを見つけることができます。例12-32にこれを示します。nameStampは表のIDです。

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

      // The table needs to find the 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. コンポーネントを使用するために必要なその他のコードを追加します。スタンプ設定されたコンポーネントを検出したら、その他のコンポーネントの場合と同じように通信できます。たとえば、例12-33では、スタンプされたコンポーネントを使用してname属性の行固有の値(例12-29で示したスタンプされた値)を取得してから、この名前をアラートに表示する方法を示します。

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

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

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

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

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

  for (var rowKey in addedRowKeys)
  {
    firstRowKey = rowKey;
    break;
  }
  // The table needs to find the 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);
  }
}

12.13.2 選択された値へのアクセスに関する必知事項

行キーはサーバー上のtokenizedで、これはクライアント上の行キーとサーバー上の行キーに類似点がない可能性があることを意味します。そのため、クライアント側APIによって処理される行キー(AdfSelectionEvent.getAddedSet()など)のみ有効です。

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