ヘッダーをスキップ
Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド
11gリリース1(11.1.1)
B52029-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

10 表およびツリーの使用

この章では、ADF Facesのツリーおよびツリー表コンポーネントを使用して表およびツリーを表示する方法を説明します。

この章に含まれる項は次のとおりです。

10.1 表、ツリーおよびツリー表の概要

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

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

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

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

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

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

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

File Explorerの表コンポーネント

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

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

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

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

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

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

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

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

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

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

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

ツールバーを保持するpanelCollection

10.1.1 コンテンツの配信

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


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

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

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


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

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

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

10.1.2 行の選択

rowSelection属性を使用して、表、ツリーおよびツリー表の単一行または複数行のどちらかになるように選択を構成できます。これにより、選択された行で実行できる複数のアプリケーション・ロジックを提供できます。たとえば、ユーザーが表の行またはツリーのノードを選択して、選択された行のデータが表示される別のページにナビゲートするコマンド・ボタンをクリックし、その値を編集できるようにするとします。

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


注意:

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

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


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

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

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

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

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

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

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

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

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


注意:

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

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

  • SelectManyCheckbox

  • SelectManyListBox

  • SelectOneListBox

  • SelectOneRadio

  • SelectManyShuttle


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

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

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


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

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

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


ヒント:

選択された行に基づいて、ポップアップ・メニューにコンテンツが動的に表示されるようにするには、ポップアップ・コンテンツの配信をlazyUncachedに設定します。また、現在行を取得し、その現在行に基づいてデータを表示できるマネージドBeanのメソッドにsetPropertyListenerタグを追加します。
<af:tree value="#{fs.treeModel}"
         contextMenuSelect="false" var="node" ..>
  <f:facet name="contextMenu">
    <af:popup id="myPopup" contentDelivery="lazyUncached">
      <af:setPropertyListener from="#{fs.treeModel.rowData}"
               to="#{dynamicContextMenuTable.currentTreeRowData}"
               type="popupFetch" />
      <af:menu>
       <af:menu text="Node Info (Dynamic)">
         <af:commandMenuItem actionListener=
           "#{dynamicContextMenuTable.alertTreeRowData}"
           text=
     "Name - #{dynamicContextMenuTable.currentTreeRowData.name}" />
         <af:commandMenuItem actionListener=
           "#{dynamicContextMenuTable.alertTreeRowData}"
           text=
     "Path - #{dynamicContextMenuTable.currentTreeRowData.path}" />
         <af:commandMenuItem actionListener=
           "#{dynamicContextMenuTable.alertTreeRowData}"
           text="Date -
     #{dynamicContextMenuTable.currentTreeRowData.lastModified}" />
       </af:menu>
    </af:menu>
  </af:popup>
  </f:facet>
...
</af:tree>

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

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

  public Map getCurrentTreeRowData()
  {
    return _currentTreeRowData;
  }

  private Map _currentTreeRowData;
}

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

ポップアップ・メニュー作成の詳細は、13.2.6項「ポップアップ・メニューの作成方法」を参照してください。

10.1.5 クライアントの表、ツリーおよびツリー表コンポーネントへのアクセス

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

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

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

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

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

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

10.2 表へのデータの表示

表コンポーネントでは、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を参照してください。

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

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

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

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

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

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

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

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

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

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

10.2.1 列および列データ

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

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

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

10.2.2 表の書式設定

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

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

  • 表の高さ: 表の高さを絶対的(300ピクセルなど)に設定することも、autoHeightRows属性を使用して、一度に表示する行数に基づいて表の高さを決定することもできます。ただし、このオプションを使用できるのは、データ・フェッチをimmediateに設定した場合のみです。データのフェッチ方法の詳細は、10.1.1項「コンテンツの配信」を参照してください。

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

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

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

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


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

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

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


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

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

  • 列の選択: ユーザーにデータの列の選択を許可できます。行の選択同様、単一の列または複数の列を選択できるように構成できます。

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

10.2.3 列の書式設定

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

  • のソート: ユーザーが、指定された列を基準とし、sortable属性を使用して昇順または降順にコンテンツをソートできるよう列を構成できます。列ヘッダーの特別なインジケータにより、ユーザーは列がソート可能であることがわかります。ユーザーが列ヘッダーをクリックして、前にソートされていない列をソートすると、列のコンテンツは昇順でソートされます。次に同じヘッダーをクリックすると、コンテンツは降順でソートされます。表をソートできるようにするには、基礎となるデータ・モデルでもソートがサポートされている必要があります。詳細は、10.2.7項「プログラムを使用した表の列のソートの有効化について」を参照してください。

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


    ヒント:

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

  • 列の幅: width属性を使用して、列の幅をピクセル単位の絶対値として指定できます。

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

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

    図10-10 表の行ヘッダー

    表の行ヘッダー

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

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

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

ヒント:

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

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

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

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

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

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

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

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

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

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

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


    ヒント:

    リストされている以外のコンポーネントを使用する場合は、プロパティ・インスペクタで任意のコンポーネントを選択し、それを手動で必要なコンポーネントに変更します。これは次のように行います。
    1. 構造ウィンドウで、ダイアログにより作成されたコンポーネントを右クリックします。

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

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



    ヒント:

    列に複数のコンポーネントを表示する場合は、その他のコンポーネントを手動で追加し、それらをpanelGroupLayoutコンポーネントでラップします。これは次のように行います。
    1. 構造ウィンドウで、1つ目のコンポーネントを右クリックし、前に挿入または後に挿入を選択します。挿入するコンポーネントを選択します。

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

    3. panelGroupLayoutを選択します。


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

    • width: 表の幅を指定します。割合またはピクセル数で幅を指定できます。デフォルト設定は300ピクセルです。


      ヒント:

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

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


      注意:

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


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

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

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

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

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

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


      ヒント:

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

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

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

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

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

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

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

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

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


      注意:

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

    • first: ユーザーに最初に表示する行の索引を(ゼロベースの索引で)入力します。デフォルトでは、1行目が表示されるように設定されています。

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


      ヒント:

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

    • contentDelivery: データを送信するタイミングを指定します。contentDelivery属性がimmediateに設定されている場合、コンポーネントのレンダリングと同時にデータがフェッチされます。contentDelivery属性がlazyに設定されている場合は、後続のリクエスト中にデータがフェッチされてクライアントに送信されます。詳細は、10.1.1項「コンテンツの配信」を参照してください。

    • autoHeightRows: 使用可能な領域に合せて表で高さのサイズ設定が自動的に行われるようにする場合は、表に表示する最大の行数を指定します。これにより、行の高さは領域に合せて調整されます。デフォルト値は-1です(何行であっても自動サイズ設定は行われません)。


      注意:

      autoHeightRows属性の設定について、次の点に注意してください。
      • 高さの自動サイズ設定を使用するには、データのフェッチと同時に行の高さを判断する必要があるため、contentDelivery属性をimmediateに設定する必要があります。

      • inlineStyle属性に高さを指定すると、自動的にサイズ設定された高さがオーバーライドされますが、minimum-heightおよびmaximum-height値を設定すると、自動サイズ設定の結果に制限が設けられます。

      • 表がpanelSplitterなどのレイアウト管理コンテナに配置されている場合、表はコンテナ・コンポーネントによりサイズ設定され、表の自動サイズ設定は行われません。autoHeightRows設定が適用されるpanelCollectionには当てはまらないことに注意してください。詳細は、8.2.1項「ジオメトリ管理およびコンポーネントの拡大」を参照してください。


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


      注意:

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

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


      注意:

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

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

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

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

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

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

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

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

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

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


      注意:

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

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

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

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

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

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

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

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

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

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

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

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

  9. 既存の表に列を追加するには、構造ウィンドウで表を右クリックし、ポップアップ・メニューから「表の中に挿入」「列」を選択します。

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


    ヒント:

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

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


    ヒント:

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

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

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


    ヒント:

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

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


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

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

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

例10-2 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" 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"
             sortProperty="property.size">
    <f:facet name="header">
      <af:outputText value="#{explorerBundle['contents.size']}"/>
    </f:facet>
    <af:outputText value="#{file.property.size}" noWrap="true"/>
  </af:column>
...
  <af:column width="100">
    <f:facet name="header">
      <af:outputText value="#{explorerBundle['global.properties']}"/>
    </f:facet>
    <af:commandLink text="#{explorerBundle['global.properties']}"
                    partialSubmit="true"
                    action="#{explorer.launchProperties}"
                    returnListener="#{explorer.returnFromProperties}"
                    windowWidth="300" windowHeight="300"
                    useWindow="true"></af:commandLink>
  </af:column>
</af:table>

10.2.6 実行時の処理

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

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

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

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

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

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


public boolean isSortable(String propertyName)
public List getSortCriteria()
public void setSortCriteria(List criteria)

詳細は、http://myfaces.apache.org/trinidad/trinidad-1_2/trinidad-api/apidocs/index.htmlにあるMyFaces TrinidadのJavadocを参照してください。

基礎となるモデルがCollectionModelインスタンスではない場合、tableコンポーネントにより、どのプロパティがソート可能かを判断するために実際のデータが自動的に調査されます。java.lang.Comparableクラスを実装するデータがある列はソート可能です。この自動サポートは、CollectionModelに直接ソートをコーディングする(ソートをSQLのORDER BY句に変換するなど)ほど効率はよくありませんが、小規模なデータ・セットには十分です。

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

ユーザーは表の1行以上を選択し、それらの行に対してアクションを実行できます。

表の選択状態が変更されると、表により選択イベントが起動されます。selectionEventイベントにより、選択解除された行や選択された行が報告されます。

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

現在の選択内容(選択された1行または複数の行)はRowKeySetオブジェクトで、表に対してgetSelectedRowKeys()メソッドをコールして取得できます。プログラムを使用して選択内容を変更するには、次のいずれかを実行します。

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

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

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

例10-3 行の選択

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

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

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

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

// Binding methods for access to the table.
public void setTable(UIXTable table) { _table = table; }
public UIXTable getTable() { return _table; }
private UIXTable _table;

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

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

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

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

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

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

public List<Item> 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<Item> items = new ArrayList<Item>(list.size());
   for (SomeModelObject entry : list)
   {
     items.add(new Item(entry.getValue(), entry.getLabel());
    }
    // Return the items
    return items;
}

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

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

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

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

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

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

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

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

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

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


注意:

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

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

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

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

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

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

注意:

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

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

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

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

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

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

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

    ヒント:

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

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

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

    例10-8 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>
    

10.3.2 実行時の処理

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

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

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

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

たとえば、図10-16の表は、ProductIdが100より大きい行のみを表示するようにフィルタ処理されています。

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

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

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

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


注意:

ADFモデルを使用する場合は、フィルタ・モデルが作成されます。

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

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

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

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

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

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

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

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

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

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

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


    ヒント:

    フィルタにinputTextコンポーネント以外のコンポーネント(inputDateコンポーネントなど)を使用する場合は、filterVisibletrueに設定するかわりに、filterファセットに必要なコンポーネントを追加できます。これは次のように行います。
    1. 構造ウィンドウでフィルタ処理する列を右クリックし、「af:columnの中に挿入」「JSF Core」フィルタ・ファセットを選択します。

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

    3. 手順1で作成したFilterableQueryDescriptorクラス内の対応する属性にコンポーネントの値を設定します。この値は、行に使用される変数を考慮して設定する必要があります。次を参照してください。

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

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

    • filterable: trueに設定します。

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

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

ADF Facesのツリー・コンポーネントは、組織図や階層ディレクトリ構造などの階層データを表示します。これらのタイプのデータには、一連のトップレベル・ノードがあり、構造の各要素は展開してその他の要素を格納できます。たとえば、組織図で、階層の各要素であるそれぞれの従業員には、任意の数の子要素(直下のレポート)を含むことができます。ツリー・コンポーネントでは、複数のルート要素がサポートされています。このコンポーネントでは、構造を表す形式でデータが表示されます。各要素は階層内のレベルを表すために適切なレベルにインデントされ、親に接続されています。ユーザーは階層の一部を展開および縮小できます。

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

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

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

例10-10 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();
}

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

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

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

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

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

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

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


ヒント:

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

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

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

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

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

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

  3. プロパティ・インスペクタで、「共通」セクションを開き、id属性に値を入力します。

  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)を指定します。詳細は、10.1.3項「表、ツリーおよびツリー表のデータの編集」を参照してください。

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

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

    • contentDelivery: コンポーネントが最初にレンダリングされる際に、データをフェッチするかどうかを指定します。contentDelivery属性がimmediateの場合、コンポーネントのレンダリング時にデータがフェッチされます。contentDelivery属性がlazyの場合は、データがフェッチされて後続のリクエスト中にクライアントに送信されます。詳細は、10.1.1項「コンテンツの配信」を参照してください。

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

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

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

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

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

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

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

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

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


    ヒント:

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

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

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

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

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

10.5.3 実行時の処理

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

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

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

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

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

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

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

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

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

public void handleRowDisclosure(RowDisclosureEvent rowDisclosureEvent)
  throws Exception {
    Object rowKey = null;
    Object rowData = null;
    RichTree tree = (RichTree) rowDisclosureEvent.getSource();
    RowKeySet rks = rowDisclosureEvent.getAddedSet();

    if (rks != null) {
        int setSize = rks.size();
        if (setSize > 1) {
            throw new Exception("Unexpected multiple row disclosure
                                 added row sets found.");
        }

        if (setSize == 0) {
           // nothing in getAddedSet indicates this is a node
           // contraction, not expansion. If interested only in handling
           // node expansion at this point, return.
           return;
        }

        rowKey = rks.iterator().next();
        tree.setRowKey(rowKey);
        rowData = tree.getRowData();

        // Do whatever is necessary for accessing tree node from
        // rowData, by casting it to an appropriate data structure
        // for example, a Java map or Java bean, and so forth.
   }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


    ヒント:

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

10.7 行を値として渡す

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

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

例10-18 setPropertyListener and pageFlowScopeの使用

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

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

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

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

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

panelCollectionコンポーネントを使用して、表、ツリーおよびツリー表にメニュー、ツールバーおよびステータス・バーを追加できます。panelCollectionコンポーネントを使用するには、表、ツリーまたはツリー表コンポーネントをpanelCollectionコンポーネントの直接の子として追加します。panelCollectionコンポーネントには、デフォルトのメニューとツールバー・ボタンが用意されています。図10-19に、ツリー表コンポーネントを含む、File ExplorerアプリケーションのpanelCollectionコンポーネントを示します。このコンポーネントには、ツリー表で実行可能なアクション(ノードの開閉など)を提供するメニュー、ユーザーがツリー表を連結解除できるボタン、およびユーザーがツリー表に表示された行を変更できるボタンが含まれます。メニュー、ツールバー、ツールバー・ボタンの詳細は、第14章「メニュー、ツールバーおよびツールボックスの使用方法」を参照してください。

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

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

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

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

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

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

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

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

ヒント:

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

表、ツリーまたはツリー表のデータをMicrosoft Excelのスプレッドシートにエクスポートできます。コマンド・ボタンやコマンド・リンクなどのアクション・ソースを作成し、exportCollectionActionListenerコンポーネントを追加して、エクスポートするデータを関連付けます。すべての行がエクスポートされるように、またはユーザーが選択した行のみがエクスポートされるように表を構成できます。たとえば、図10-20に、ユーザーがExcelのスプレッドシートにデータをエクスポートできるコマンド・ボタン・コンポーネントが含まれるADF Facesアプリケーションの表を示します。

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

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

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

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

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

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

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

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

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

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

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

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


    ヒント:

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

  2. 存在しない場合は、表、ツリーまたはツリー表コンポーネントのid属性に値を追加します。

  3. ページにボタンなどのコマンド・コンポーネントを追加します。


    ヒント:

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

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

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

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

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

    • type: excelHTMLに設定します。

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

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

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

    • exportedRows「その他」セクション): すべての行が自動的に選択されてエクスポートされるようにするには、allに設定します。ユーザーが選択した行のみがエクスポートされるようにする場合は、selectedに設定します。

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

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

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

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

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

10.10 スタンプ設定を使用するコンポーネントからクライアント上の選択された値へのアクセス

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  for (var rowKey in addedRowKeys)
  {
    firstRowKey = rowKey;
    break;
  }
  // We need the table to find our stamped component.
  // Fortunately, in the case of selection events, the
  // table is the event source.
  var table = event.getSource();

  // We use the table to find the name stamp component by id/row key:
  var nameStamp = table.findComponent("nameStamp", firstRowKey);

  if (nameStamp)
  {
    // This is the row-specific name
    var name = nameStamp.getValue();

     alert("The selected name is: " + name);
  }
}

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

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

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