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

前
 
次
 

5 ADFによるデータバインドされた表の作成

この章では、「データ・コントロール」パネルを使用して、編集可能な表や入力表など、ADF Facesコンポーネントに基づいてデータバインドされた基本的な表を作成する方法について説明します。

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

5.1 表の追加について

フォームと異なり、表を使用すると、アクセッサによって返されたコレクションのレコードを一度に複数表示できます。図5-1に、Summitデモ・アプリケーションのCustomerFindAllコレクションをドラッグし、表示用に4つの列を選択して作成された表を示します。

図5-1 検索基準に合う製品を表示する結果表

4つの列のある表

単にデータを表示する表を作成することも、データの編集または作成が可能な表を作成することもできます。アクセッサを表としてドロップすると、選択した行に対してなんらかのロジックを実行するアクションにバインドされたコマンド・ボタンを追加できます。また、必要に応じてデフォルトのコンポーネントを変更することもできます。

5.2 基本表の作成

フォームを構成する個々のUIコンポーネントをコレクション上の個々の属性にバインドするフォームとは異なり、表では、ADF Facesのtableコンポーネントをコレクション全体にバインドするか、コレクションから一度にnデータ・オブジェクトのレンジにバインドします。その結果、列にデータを表示するために使用される個々のコンポーネントが属性にバインドされます。イテレータ・バインディングによって各オブジェクトの適切なデータが表示され、tableコンポーネントによって各オブジェクトが1行で表示されます。JDeveloperを使用すると、宣言的にこの処理を行うことができるため、コードを記述する必要がありません。

5.2.1 基本表の作成方法

データ・コントロールを使用して表を作成するには、返されるコレクションにtableコンポーネントをバインドします。JDeveloperでは、「データ・コントロール」パネルからコレクションをドラッグ・アンド・ドロップして、宣言的にこの処理を実行できます。


ヒント:

コンポーネント・パレットから表コンポーネントをドラッグし、ADF Faces Tableの作成ウィザードを完了して表を作成することもできます。詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』のページでの表の表示方法に関する項を参照してください。


始める前に:

データ・コントロールを使用した表の作成に関する一般的な知識があると役立ちます。詳細は、5.2項「基本的な表の作成」を参照してください。

次のタスクを完了する必要があります。

2.2.1項「ADFデータ・コントロールの作成方法」の説明に従って、セッションBeanのデータ・コントロールを作成します。

データバインドされた表を作成する手順:

  1. 「データ・コントロール」パネルから、コレクションを選択します。

    たとえば、システム内の注文を表示する簡単な表をSummitデモ・アプリケーションで作成するには、ordFindAllアクセッサ・コレクションを選択します。

  2. コレクションをJSFページにドラッグし、ポップアップ・メニューから適切な表を選択します。

    コレクションをドラッグするときは、次のタイプの表から選択できます。

    • ADF表: 編集可能な表の列の表示に必要な特定の属性と、データの表示に使用するUIコンポーネントを選択できます。デフォルトでは、ADF inputTextコンポーネントはほとんどの属性で使用され、このコンポーネントにより、表は編集可能となります。日付である属性ではinputDateコンポーネントが使用されます。さらに、属性にUIヒントが作成されている場合、または属性がリストとして構成されている場合、ヒントにより設定されたコンポーネントが使用されます。UIヒントの設定の詳細は、3.3.5項「属性へのUIヒントの設定方法」を参照してください。

    • ADF読取り専用表: 「ADF表」と同じですが、各属性は、outputTextコンポーネントに表示されます。

    • ADF読取り専用動的表: 返されて表示される属性が実行時に動的に決定される表を作成できます。このコンポーネントは、対応するオブジェクトの属性が実行時まで不明な場合、あるいはJSFページに列名をハードコーディングしない場合に適しています。

  3. 次に表示される「表の列の編集」ダイアログには、コレクション内の各属性が表示されます。また、これらの属性がどのように動作し、表の列としてどのように表示されるかを定義できます。


    注意:

    コレクションに構造化属性(Javaのプリミティブ・タイプまたはコレクションのいずれでもない属性)が含まれる場合、その構造化属性の属性も同様にダイアログに表示されます。


    ダイアログを使用すると、次の操作ができます。

    • 「行選択」パネルで、ADFモデル・レイヤーによる選択の処理方法を指定します。「単一」ラジオ・ボタンを選択すると、ユーザーは1つの行を選択し、イテレータ・バインディングがイテレータにアクセスして選択した行を決定します。「複数」ラジオ・ボタンを選択すると、ユーザーは複数の行を選択でき、イテレータ・バインディングがイテレータにアクセスして選択した行を決定します。表での選択を実行しない場合は、「なし」を選択します。

    • 「ソート」チェック・ボックスの選択による、ADFモデル・レイヤーでの列のソート処理。このオプションを選択すると、イテレータ・バインディングがイテレータにアクセスし、order-by問合せを実行して順序を決定します。列のソートを実行しない場合以外は、このオプションを選択してください。

    • 「フィルタリング」チェック・ボックスの選択による、入力した基準を使用した、表の列のフィルタリングの実行。このオプションを選択すると、各列の上にあるテキスト・フィールドに基準を入力できます。その後で、この基準を使用してコレクションへのQuery-by-Example(QBE)検索を作成すると、問合せによって戻された結果のみが表に表示されます。詳細は、8.5項「スタンドアロンのフィルタ処理された検索表の作成」を参照してください。

    • 目的の属性(ダイアログでは行として表示)の選択および「グループ化」ボタンのクリックによる、親列下での選択した属性の列のグループ化。図5-2に、表の作成後、グループ化された2つの列がビジュアル・エディタでどのように表示されるかを示します。

      図5-2 ADF Faces表のグループ化された列

      列をグループ化できます
    • テキストまたはEL式を入力して、ラベルの値を他のもの(リソース・ファイルのキーなど)にバインドすることによる、列の表示ラベルの変更。デフォルトでは、ラベルは表バインディング上の属性に定義されたすべてのUIヒントのlabelプロパティにバインドされます。このバインディングにより、データ・コントロール構造ファイルのラベル・テキストの値を1回のみ変更でき、また、その変更はラベルを表示するすべてのページに反映されます。

    • バインド対象に別の属性を選択することによる、列の値バインディングの変更。単に列を並べ替える場合は、順序ボタンを使用してください。列の属性バインディングを変更すると、列のラベルも変更されます。

    • ドロップダウン・メニューを使用した、属性の表示に使用されるUIコンポーネントの変更。UIコンポーネントは、コレクションをページにドロップしたときに選択した表と、対応する属性のタイプ(たとえば、日付である属性にはinputDateコンポーネントを使用)、およびBeanのデータ・コントロール構造ファイルでデフォルト・コンポーネントがUIヒントとして設定されているかどうかに基づいて設定されます。


      ヒント:

      表の属性の1つが主キーでもある場合、ユーザーが値を変更できないUIコンポーネントを選択します。



      ヒント:

      ドロップダウン・メニューに表示されないコンポーネントを使用する場合は、このダイアログを使用してoutputTextコンポーネントを選択した後、手動で他のタグをページに追加します。


    • 順序ボタンを使用した列の順序の変更。

    • 追加」アイコンを使用した列の追加。追加できる列の数に制限はありません。最初にアイコンをクリックすると、JDeveloperではダイアログの下部に新規列の行が追加され、そこにバインドされたコレクションの最初の属性の値が移入されます。後続の新規列には順序内の次の属性の値が移入され、その後も同様に続きます。

    • 「削除」アイコンを使用した列の削除。

  4. 表をページにドロップした後は、プロパティ・インスペクタを使用して表に他の表示プロパティを設定できます。たとえば、表の幅を特定のパーセンテージまたはサイズに設定します。表示プロパティの詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』の「表とツリーの使用」を参照してください。


    ヒント:

    表の幅を100%に設定すると、表には境界が含まれないため、表の実際の幅はさらに大きくなります。コンテナの幅の100%に表を設定するには、プロパティ・インスペクタの「スタイル」セクションを展開し、「ボックス」タブを選択してBorder Width属性を0ピクセルに設定します。


  5. ユーザーが表の情報を編集し、変更を保存できるようにするには、変更を発行して保存する方法を指定する必要があります。詳細は、5.3項「編集可能な表の作成」を参照してください。ユーザーによるデータ入力が可能な表の作成手順は、5.4項「入力表の作成」を参照してください。

5.2.2 表の作成時の処理

「データ・コントロール」パネルから表をドロップすると、テキスト・フィールドまたはフォームをドロップするのと同じ効果があります。要約すると、JDeveloperによって行われる処理は次のとおりです。

  • 表のバインディングを作成し、ページ定義ファイルにそのバインディングを追加します。

  • UIコンポーネントに必要なコードをJSFページに追加します。

詳細は、4.2.2項「テキスト・フィールドの作成時の処理」を参照してください。

5.2.2.1 表のイテレータと値バインディング

「データ・コントロール」パネルから表をドロップすると、ツリーの値バインディングが作成されます。ツリーはノードの階層で構成され、各サブノードは上位レベルのノードから分岐します。表の場合、フラット化された階層であり、各属性(列)は表のサブノードになります。フォームで使用される属性バインディングと同様に、ツリーの値バインディングによってアクセッサ・イテレータ・バインディングが参照される一方、アクセッサ・イテレータ・バインディングによってデータ・コントロールのイテレータが参照されます。これにより、コレクションのデータ・オブジェクト全体の反復が円滑に行われます。属性ごとに異なるバインディングが作成されるのではなく、表ノードへのツリー・バインディングのみが作成されます。ツリー・バインディングでは、表の各行で表示または参照に使用する各属性の子要素が、nodeDefinition要素のAttrNames要素に含まれています。

ツリーの値バインディングは、FacesCtrlHierBindingクラスのインスタンスです。このクラスは、コアのJUCtrlHierBindingクラスを拡張して、次の2つのJSF固有のプロパティを追加します。

  • collectionModel: JSFおよびADF Facesで表などのコレクション値コンポーネントに使用するjavax.faces.model.DataModelオブジェクトを拡張するオブジェクトによってラップされたデータを戻します。

  • treeModel: collectionModelを拡張し、実質的に階層構造であるデータを戻します。詳細は、第6章「マスター/ディテール・データの表示」を参照してください。

例5-1に、SOrdListアクセッサ・コレクションをドロップすると作成される表の値バインディングを示します。

例5-1 ページ定義ファイルにおける表の値バインディング・エントリ

<bindings>
  <tree IterBinding="SOrdListIterator" id="SOrdList">
    <nodeDefinition DefName="model.Ord" Name="SOrdList0">
      <AttrNames>
        <Item Value="id"/>
        <Item Value="dateOrdered"/>
        <Item Value="paymentTypeId"/>
        <Item Value="salesRepId"/>
        <Item Value="total"/>
        <Item Value="orderFilled"/>
        <Item Value="dateShipped"/>
      </AttrNames>
    </nodeDefinition>
  </tree>
...
</bindings>

データにアクセスする必要があるのは表のみであるため、(列または個々のセル内のテキスト・コンポーネントではなく)モデルにバインドする必要があるのは表コンポーネントのみです。表のツリー・バインディングは表の個々の構造化属性にドリルダウンするので、表の列は表コンポーネントからその情報を導出できます。

5.2.2.2 ADF Faces表のJSFページのコード

「データ・コントロール」パネルを使用してJSFページに表をドロップすると、表バインディングで指定された各属性に対するADF Facesのcolumnコンポーネントが含まれたADF FacesのtableコンポーネントがJDeveloperによって挿入されます。各列には、属性の値にバインドされた別のコンポーネント(inputTextコンポーネントやoutputTextコンポーネントなど)が含まれます。各列のヘッダーは、属性のコントロール・ヒントのlabelsプロパティにバインドされます。


ヒント:

関連付けられている構造ファイルで属性が非表示としてマークされている場合、対応するUIは作成されません。


例5-2に、ordFindAllアクセッサ・コレクションを読取り専用表としてドロップして作成した表から抜粋したコードを示します。

例5-2 ADF Faces読取り専用表のJSFコード

<af:table value="#{bindings.ordFindAll.collectionModel}" var="row"
          rows="#{bindings.ordFindAll.rangeSize}"
          emptyText="#{bindings.ordFindAll.viewable ? 'No data to display.' : 
                      'Access Denied.'}"
          fetchSize="#{bindings.ordFindAll.rangeSize}" rowBandingInterval="0"
          id="t1">
    <af:column sortProperty="#{bindings.ordFindAll.hints.dateOrdered.name}" 
               sortable="false"
               headerText="#{bindings.ordFindAll.hints.dateOrdered.label}" 
               id="c1">
        <af:outputText value="#{row.dateOrdered}" id="ot1">
            <af:convertDateTime
                 pattern="#{bindings.ordFindAll.hints.dateOrdered.format}"/>
        </af:outputText>
    </af:column>
    <af:column sortProperty="#{bindings.ordFindAll.hints.dateShipped.name}" 
               sortable="false"
               headerText="#{bindings.ordFindAll.hints.dateShipped.label}"
               id="c2">
        <af:outputText value="#{row.dateShipped}" id="ot2">
            <af:convertDateTime
                  pattern="#{bindings.ordFindAll.hints.dateShipped.format}"/>
            </af:outputText>
     </af:column>
. . .
</af:table>

ツリー・バインディングは、イテレータ・バインディングによって公開されたデータ全体を反復します。表の値は、collectionModelオブジェクトにアクセスするcollectionModelプロパティにバインドされています。表は、イテレータ・バインディングからの結果セットをcollectionModelオブジェクト内にラップします。collectionModelにより、コレクションの各アイテムは、var属性を使用して表コンポーネント内で使用できるようになります。

例では、表は、ordFindAllアクセッサ・バインディングの現在レンジの行全体を反復します。バインディングは、現在の行を追跡する行セット・イテレータにバインドします。表のvar属性をrowに設定すると、次のaf:outputTextタグの値に示すように、各列はrow変数を使用して、表タグに示される現在行の現在データ・オブジェクトにアクセスします。

<af:outputText value="#{row.dateOrdered}"/>

行変数にバインドするかわりに、ADF表(ADF読取り専用表ではなく)をドロップすると、入力コンポーネントの値は、bindingsプロパティによってバインディング・コンテナ内の特定の行に暗黙的にバインドされます(例5-3を参照)。さらに、入力コンポーネントごとにバリデータ・コンポーネントとコンバータ・コンポーネントが追加されます。bindingsプロパティを使用すると、発生した例外を該当するバインド・オブジェクトにリンクできます。コントローラは、バインディング・コンテナ内のすべての例外を反復処理し、FacesMessageオブジェクトの作成時にクライアントIDを取得するためのバインディング・オブジェクトを取得します。この取得により、特定のセルのエラーを表に表示できるようになります。この方法は、リストなどの選択コンポーネントを含め、すべての入力コンポーネントに使用されます。

例5-3 入力コンポーネントを使用したバリデータとコンバータの追加

<af:table value="#{bindings.ordFindAll.collectionModel}" var="row"
          rows="#{bindings.ordFindAll.rangeSize}"
          emptyText="#{bindings.ordFindAll.viewable ? 'No data to display.' :
                      'Access Denied.'}"
          fetchSize="#{bindings.ordFindAll.rangeSize}" rowBandingInterval="0"
          id="t1">
    <af:column sortProperty="#{bindings.ordFindAll.hints.dateOrdered.name}"
               sortable="false"
               headerText="#{bindings.ordFindAll.hints.dateOrdered.label}"
               id="c1">
        <af:inputDate value="#{row.bindings.dateOrdered.inputValue}"
               label="#{bindings.ordFindAll.hints.dateOrdered.label}"
               required="#{bindings.ordFindAll.hints.dateOrdered.mandatory}"
               columns="#{bindings.ordFindAll.hints.dateOrdered.displayWidth}"
               shortDesc="#{bindings.ordFindAll.hints.dateOrdered.tooltip}"
               id="id1">
            <f:validator binding="#{row.bindings.dateOrdered.validator}"/>
            <af:convertDateTime
                pattern="#{bindings.ordFindAll.hints.dateOrdered.format}"/>
        </af:inputDate>
    </af:column>
    <af:column sortProperty="#{bindings.ordFindAll.hints.dateShipped.name}"
               sortable="false"
               headerText="#{bindings.ordFindAll.hints.dateShipped.label}"
               id="c2">
        <af:inputDate value="#{row.bindings.dateShipped.inputValue}"
                      label="#{bindings.ordFindAll.hints.dateShipped.label}"
                     required="#{bindings.ordFindAll.hints.dateShipped.mandatory}"
                   columns="#{bindings.ordFindAll.hints.dateShipped.displayWidth}"
                      shortDesc="#{bindings.ordFindAll.hints.dateShipped.tooltip}"
                      id="id2">
            <f:validator binding="#{row.bindings.dateShipped.validator}"/>
            <af:convertDateTime
                 pattern="#{bindings.ordFindAll.hints.dateShipped.format}"/>
        </af:inputDate>
    </af:column>
    <af:column sortProperty="#{bindings.ordFindAll.hints.id.name}"
               sortable="false"
               headerText="#{bindings.ordFindAll.hints.id.label}" id="c3">
        <af:inputText value="#{row.bindings.id.inputValue}"
                      label="#{bindings.ordFindAll.hints.id.label}"
                      required="#{bindings.ordFindAll.hints.id.mandatory}"
                      columns="#{bindings.ordFindAll.hints.id.displayWidth}"
                      maximumLength="#{bindings.ordFindAll.hints.id.precision}"
                      shortDesc="#{bindings.ordFindAll.hints.id.tooltip}"
                      id="it1">
            <f:validator binding="#{row.bindings.id.validator}"/>
        </af:inputText>
    </af:column>
. . .
</af:table>

ADF Facesのバリデータとコンバータの使用方法の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』の「入力の検証および変換」を参照してください。

表5-1に、「データ・コントロール」パネルを使用して作成されたADF Faces表に対して、デフォルトで定義された他の属性を示します。

表5-1 ADF Faces表の属性と移入される値

属性 説明 デフォルト値

rows

一度に表示する行数を決定します。

デフォルトで、関連付けられたイテレータ・バインディングのrangeSizeプロパティに評価されるEL式。これにより、データ・コントロールから一度にフェッチされるデータの行数が決定されます。表は戻される行数以上を表示できないため、rows属性の値は、対応するイテレータのrangeSize値以下にする必要があります。rangeSizeプロパティの詳細は、4.4.2.2項「イテレータのRangeSize属性」を参照してください。

emptyText

戻す行がない場合に表示するテキスト。

イテレータの表示可能なプロパティに評価されるEL式。表が表示可能で、戻すオブジェクトがない場合、「表示するデータがありません」と表示されます。表が表示できない場合(表に対して認可の制限が設定されている場合など)は、「アクセスが拒否されました」と表示されます。

fetchSize

データソースからフェッチされるデータの行数。

デフォルトで、関連付けられたイテレータ・バインディングのrangeSizeプロパティに評価されるEL式。rangeSizeプロパティの詳細は、4.4.2.2項「イテレータのRangeSize属性」を参照してください。この属性は、rows属性より大きい数値に設定することができます。

selectedRowKeys

表の選択の状態。

デフォルトでコレクション・モデルの選択された行に評価されるEL式。

selectionListener

選択イベントをリスニングするメソッドへの参照。

デフォルトでコレクション・モデルのmakeCurrentメソッドに評価されるEL式。

rowSelection

行が選択可能かどうかを決定します。

一度に1行のみ選択するにはsingleに設定します。

列の属性



sortProperty

列のソート基準のプロパティを決定します。

列の対応する属性バインディング値に設定します。

sortable

ソートできる列かどうかを決定します。

falseに設定します。trueに設定すると、イテレータ・バインディングがイテレータにアクセスし、順序を決定します。

headerText

列の上部に表示されるテキストを決定します。

デフォルトで、対応する属性に設定されたラベルのlabel UIヒントに評価されるEL式。


5.2.3 表での現在行の設定について

アプリケーションで表を使用し、ADF Modelレイヤーで行選択を管理できるようにする場合、現在行はイテレータによって決定されます。ユーザーがADF Faces表で行を選択すると、表の行が影付きになり、選択された行がコンポーネントによりイテレータに通知されます。そのためには、例5-4に示すように、表のselectedRowKeys属性をコレクション・モデルの選択した行にバインドします。

例5-4 表のselection属性

<af:table value="#{bindings.ordFindAll.collectionModel}" var="row"
.
.
.
          selectedRowKeys="#{bindings.ordFindAll.collectionModel.selectedRow}"
          selectionListener="#{bindings.ordFindAll.collectionModel.makeCurrent}"
          rowSelection="single" id="t1">

このバインディングは、表の選択したキーをコレクション・モデルの選択した行にバインドします。selectionListener属性は、コレクション・モデルのmakeCurrentプロパティにバインドされます。このバインディングは、コレクションの選択した行をイテレータの現在行に設定します。


注意:

カスタム選択リスナーを作成した場合、コレクション・モデルのmakeCurrentプロパティへのメソッド・バインディング(#{binding.Ord.collectionModel.makeCurrent}など)を作成し、任意のカスタム・ロジックの前にこのメソッド・バインディングをカスタム選択リスナーで起動する必要があります。


表は選択を自動的に処理できますが、オブジェクトの現在行をイテレータにプログラムで設定する必要がある場合があります。

getKey()メソッドをどのビュー行でコールしても、行を識別する1つ以上のキー属性をカプセル化するKeyオブジェクトを取得できます。Keyオブジェクトは、findByKey()による行セット内のビュー行の検索にも使用できます。実行時に、setCurrentRowWithKeyまたはsetCurrentRowWithKeyValueのいずれかの組込み操作がデータ・バインディング・レイヤーによって名前で起動されると、findByKey()メソッドを使用して、パラメータとして渡された値に基づいて行が検索された後、検索された行が現在の行として設定されます。

setCurrentRowWithKey操作およびsetCurrentRowWithKeyValue操作ではいずれもrowKeyという名前のパラメータをとりますが、実行時にそのrowKeyパラメータに想定される値はそれぞれで異なります。

setCurrentRowWithKey操作

setCurrentRowWithKeyでは、rowKeyパラメータ値に、ビュー行キーのシリアライズされた文字列表現が想定されています。これは、次の文字列のような16進の暗号化された文字列です。

000200000002C20200000002C102000000010000010A5AB7DAD9

キーのシリアライズされた文字列表現により、ブラウザのURL文字列またはフォーム・パラメータで単一値として渡すことができる方法で、ビュー行のキーを構成する可能性のあるすべてのキー属性がエンコードされます。実行時に、有効なシリアライズされた文字列キーではないパラメータ値を間違って渡すと、oracle.jbo.InvalidParamExceptionまたはjava.io.EOFExceptionなどの例外を結果として受け取る場合があります。Webページでは、ADFコントロール・バインディングのrowKeyStrプロパティ(#{bindings.SomeAttrName.rowKeyStr}など)またはADF Faces表の行変数(#{row.rowKeyStr}など)を参照すると、行のシリアライズされた文字列キーの値にアクセスできます。

setCurrentRowWithKeyValue

setCurrentRowWithKeyValue操作では、rowKeyパラメータ値がビュー行のキーを表すリテラル値であると想定しています。たとえば、注文番号201を検索する場合、この値は単に201になります。

5.3 編集可能な表の作成

ユーザーが表内の情報を編集し、その変更をデータソースにコミットできるようにする表を作成できます。そのためには、返されるコレクション(またはデータ・コントロール自体)に関連付けられたデータ・レコードを変更できる操作を使用して、コマンド・ボタンを作成し、このボタンを表のツールバーに配置します。たとえば、browse.jspxページの表には、ユーザーが製品を削除できるボタンがあります。このボタンによって、現在は、ユーザーが削除を確定できるダイアログが表示されますが、製品を直接削除するメソッドにボタンをバインドすることもできます。


ヒント:

データ・ストアに新規レコードを挿入できる表を作成するには、5.4項「入力表の作成」を参照してください。


編集可能なフォーム同様、ADFモデル・レイヤーでは、コレクションの新規インスタンスが生成されるまで、行の変更が認識されないことに注意してください。したがって、変更をコミットするには、アクセッサ・イテレータで実行操作を起動する必要があります。詳細は、2.3.4項「イテレータの結果のキャッシュについて」を参照してください。

編集可能なコンポーネントを使用してデータを表示することにした場合、表に一度にすべての行を変更可能として表示するか、ユーザーが行内をダブルクリックするまですべての行を読取り専用として表示するかを選択できます。図5-3は、すべての行に編集可能フィールドがある表を示しています。ページは、ページに追加されたコンポーネント(inputTextinputDateinputNumberSpinboxコンポーネントなど)を使用してレンダリングされます。

図5-3 編集可能フィールドがある表

編集可能フィールドがある表

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

図5-4 クリック可能な行が選択された表

クリック可能な行が選択された表

ADF Facesの表コンポーネントによる編集の処理方法の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』の表、ツリーおよびツリー表のデータの編集に関する項を参照してください。

5.3.1 編集可能な表の作成方法

編集可能な表を作成するには、基本表の作成に類似した手順に従い、続いて操作にバインドされたコマンド・ボタンを追加します。ただし、表にツールバーを含めるには、表の作成に使用されたコレクションのアイテムとツールバーを関連付けるADF Facesコンポーネントを追加する必要があります。

始める前に:

編集可能な表の一般的な知識があると役立ちます。詳細は、5.3項「編集可能な表の作成」を参照してください。

次のタスクを完了する必要があります。

2.2.1項「ADFデータ・コントロールの作成方法」の説明に従って、セッションBeanのデータ・コントロールを作成します。

編集可能な表を作成する手順:

  1. 「データ・コントロール」パネルから、表に表示するコレクションを選択します。

    たとえば、システム内の顧客を編集可能な簡単な表をSummitデモ・アプリケーションで作成するには、customerFindAllアクセッサ・コレクションを選択します。

  2. アクセッサをJSFページにドラッグし、ポップアップ・メニューから「ADF表」を選択します。

  3. 次に表示される「表の列の編集」ダイアログを使用して、属性がどのように動作し、表の列としてどのように表示されるかを決定します。「行選択」チェック・ボックスを必ず選択することにより、ユーザーは編集する行を選択できます。

    このダイアログを使用して表を構成する方法の詳細は、5.2項「基本表の作成」を参照してください。

  4. 構造ウィンドウで表を選択し、プロパティ・インスペクタの「動作」セクションを展開してEditingMode属性を設定します。全行を編集可能にする場合は、editAllを選択します。ユーザーに1行をクリックさせてその行を編集可能にする場合は、clickToEditを選択します。

  5. 構造ウィンドウで、表コンポーネントを右クリックし、ポップアップ・メニューから「囲む」を選択します。

  6. 「囲む」ダイアログでは、ドロップダウン・リストで「ADF Faces」が選択されていることを確認し、「パネル・コレクション」コンポーネントを選択して「OK」をクリックします。

    panelCollectionコンポーネントのツールバー・ファセットによりツールバーが保持され、そのツールバーによりデータの更新に使用されるコマンド・コンポーネントが保持されます。

  7. 構造ウィンドウで、panelCollectiontoolbarファセット・フォルダを右クリックし、ポップアップ・メニューから「ツールバーの中に挿入」「ツールバー」の順に選択します。

    これにより、ユーザーが表の表示方法を変更できるデフォルトのメニューと、表全体の連結を解除する「連結解除」リンクをすでに含むツールバーが作成され、ブラウザ・ウィンドウの大部分を占めるように表示されます。panelCollectionコンポーネントの詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』の表メニュー、ツールバーおよびステータス・バーの表示に関する項を参照してください。

  8. 「データ・コントロール」パネルから、ロジックの実行対象となるオブジェクトのコレクションに関連付けられているメソッドまたは操作を選択し、構造ウィンドウのtoolbarコンポーネントにドラッグします。これにより、データバインドされたコマンド・コンポーネントがツールバー内に配置されます。

    たとえば、顧客レコードを削除できるようにする場合は、removeCustomer(Customer)メソッドをドラッグします。図5-5に、Summitデモ・アプリケーションの削除メソッドを示します。

    図5-5 データ・コントロールの削除メソッド

    「データ・コントロール」パネルに表示された削除メソッド
  9. ポップアップ・メニューから「操作」→「ADFツールバー・ボタン」を選択します。

    メソッドがパラメータをとるため、 アクション・バインディング・エディタが開き、パラメータの値を設定するよう求められます。

  10. 「アクション・バインディングの編集」ダイアログで、メソッドのパラメータに値を移入する必要があります。削除メソッド(およびその他のデフォルト・メソッド)の場合、これが選択されるオブジェクトです。

    1. 「パラメータ」セクションで、「値」ドロップダウン・リストを使用して「EL式ビルダーの表示」を選択します。

    2. 式ビルダーで、アクセッサのイテレータのノードを展開して「currentRow」ノードを展開し、「dataProvider」を選択します。

      これによって、アクセッサのイテレータで現在の行の値と評価されるEL式が作成されます。

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

    たとえば、ordFindAllアクセッサを使用して表を作成した場合、JDeveloperによってordFindAllIteratorという名前のaccessorIteratorバインディングが作成されます。図5-6に示すように、そのイテレータの下の現在の行のdataProviderオブジェクトを選択する必要があります。この参照は、パラメータ値が、現在選択されている行の値に解決されることを表します。

    図5-6 ordFindAllIteratorバインディングの現在の行のdataProvider

    ordFindAllIteratorの現在の行のdataProvider
  11. コレクションが変更されていることをADFモデル・レイヤーに通知するには、イテレータをリフレッシュするメソッドにツールバー・ボタンをバインドする必要もあります。

    1. ファイルを右クリックして「ページ定義に移動」を選択し、JSPXファイルのページ定義を開きます。

    2. ページ定義の構造ウィンドウで、「バインディング」を右クリックし、「バインディングの中に挿入」「一般バインディング」「アクション」を選択します。

    3. 「アクション・バインディングの作成」ダイアログで、「イテレータの選択」ドロップダウン・リストを使用してコレクションに関連付けるイテレータを選択し、「操作」「実行」を選択します。

      JDeveloperによって、イテレータのexecute操作に対するアクション・バインディングが作成されます。次に、コマンド・ボタンでこの操作をコールする必要があります。

  12. JSFページで、手順8でメソッドをドロップして作成したコマンド・コンポーネントを選択します。プロパティ・インスペクタで、「アクション」を次のように設定します。

    #{bindings.Execute.execute}
    

    コマンド・コンポーネントがクリックされると、actionListener属性のバインディングの後でaction属性へのバインディングが評価されます。この順序によって、エンティティの削除後にイテレータでリフレッシュや実行が行われることが保障されます。

5.3.2 編集可能な表の作成時の処理

編集可能な表の作成は、レコードの編集に使用するフォームの作成と類似しています。「データ・コントロール」パネルからドロップした操作に対してアクション・バインディングが作成されます。詳細は、4.6.2項「値を変更するメソッドの使用時の処理」を参照してください。

5.4 入力表の作成

ユーザーが表に新しく空白行を挿入し、各列に値を追加することのできる表を作成できます(対応するデータ・コントロール構造ファイルに設定されたデフォルト値は自動的に移入されます)。

5.4.1 入力表の作成方法

入力表を作成する際に、現在の行セット内の他の行のコンテキストにある新しい空白行をユーザーに表示する必要があります。この挿入をできるようにするには、表の作成に使用したコレクションのアクセッサに関連付けられているcreate操作を使用する必要があります。

create操作はキャッシュに行を作成するだけであるため、新たに作成された行をコレクションに実際にマージするボタンを追加する必要もあります。図5-7は、この表に行が作成された場合を示しています。

図5-7 行の作成およびデータの保存のボタンがある入力表

表は仕入先の行を示しています

ページ全体をリフレッシュするのではなく、他のコンポーネントとの対話に基づいて1つのコンポーネントをリフレッシュするようにADF Facesコンポーネントを設定できます。これは、部分ページ・レンダリングと呼ばれます。ユーザーが新規行を作成するボタンをクリックすると、その新規行が表示されるよう、表をリフレッシュする必要があります。これを行うには、ユーザー・アクションに対応するよう表を構成する必要があります。

始める前に:

入力表の一般的な知識があると役立ちます。詳細は、5.4項「入力表の作成」を参照してください。

次のタスクを完了する必要があります。

入力表を作成する手順:

  1. 「データ・コントロール」パネルから、ドロップされたコレクションに関連付けられた「作成」操作をドラッグし、ツールバー・ボタンとしてツールバーにドロップします。


    ヒント:

    CreateなどのわかりやすいものにIDを変更できます。これによって、部分トリガーとして選択する際に識別しやすくなります。


  2. 構造ウィンドウで、表コンポーネントを選択します。

  3. プロパティ・インスペクタで「動作」セクションを展開し、PartialTriggers属性のドロップダウン・メニューをクリックして「編集」を選択します。

  4. 「プロパティの編集」ダイアログで、panelCollectionコンポーネントのツールバー・ファセットを展開し、「作成」コマンド・コンポーネントを含むツールバーを展開します。そのコンポーネントを選択し、「選択済」パネルに移動します。「OK」をクリックします。これにより、そのコンポーネントが、表をリフレッシュするトリガーとして設定されます。

  5. ユーザーが新規オブジェクトをコレクションにマージできるボタンを作成します。「データ・コントロール」パネルから、表の作成に使用されたコレクションに関連付けるマージ・メソッドをドラッグし、ツールバー・ボタンまたはリンクとしてツールバーにドロップします。


    ヒント:

    永続化後もユーザーが行を更新できるようにする場合、かわりに永続化メソッドを使用してボタンを作成します。詳細は、4.6.3項「マージ・メソッドと永続化メソッドとの違いについて」を参照してください。


    図5-8は、Ordコレクションのマージ・メソッドを示しています。

    図5-8 「データ・コントロール」パネルでのマージ・メソッド

    mergeOrdメソッドが選択され展開された状態

5.4.2 入力表の作成時の処理

create操作を使用して入力表を作成すると、JDeveloperによって次の処理が行われます。

  • コレクションのイテレータ・バインディング、create操作のアクション・バインディング、および表の属性バインディングが作成されます。create操作は、行セットに新しい行を作成します。マージ・メソッドを使用してコマンド・ボタンまたはリンクを作成した場合、JDeveloperによって、そのメソッドに対するアクション・バインディングも作成されます。

  • ADF Facesコンポーネントの表のコードがJSFページに挿入されます。

例5-5に、入力表のページ定義ファイルを示します。

例5-5 入力表のページ定義コード

<executables>
  <variableIterator id="variables"/>
  <iterator Binds="root" RangeSize="25" DataControl="SessionEJBLocal"
            id="SessionEJBLocalIterator"/>
  <accessorIterator MasterBinding="SessionEJBLocalIterator"
                    Binds="suppliersFindAll" RangeSize="25"
                    DataControl="SessionEJBLocal" BeanClass="model.Suppliers"
                    id="suppliersFindAllIterator"/>
</executables>
<bindings>
  <action IterBinding="suppliersFindAllIterator" id="Create"
          RequiresUpdateModel="true" Action="createRow"/>
  <methodAction id="mergeSuppliers" RequiresUpdateModel="true"
                Action="invokeMethod" MethodName="mergeSuppliers"
                IsViewObjectMethod="false" DataControl="SessionEJBLocal"
                InstanceName="SessionEJBLocal.dataProvider"
                ReturnName="SessionEJBLocal.methodResults.mergeSuppliers_
                            SessionEJBLocal_dataProvider_mergeSuppliers_result">
    <NamedData NDName="suppliers"
               NDValue="#{bindings.Create.currentRow.dataProvider}"
               NDType="model.Suppliers"/>
  </methodAction>
  <tree IterBinding="suppliersFindAllIterator" id="suppliersFindAll">
    <nodeDefinition DefName="model.Suppliers">
      <AttrNames>
        <Item Value="email"/>
        <Item Value="phoneNumber"/>
        <Item Value="supplierId"/>
        <Item Value="supplierName"/>
        <Item Value="supplierStatus"/>
      </AttrNames>
    </nodeDefinition>
  </tree>
</bindings>

例5-6に、コマンド・ツールバー・ボタンを、表をリフレッシュするためのトリガーとして使用し、部分ページ・レンダリングを提供するJSFページに追加されたコードを示します。

例5-6 表のコマンド・ボタンに設定された部分ページ・トリガー

<af:form id="f1">
  <af:panelCollection id="pc1">
    <f:facet name="menus"/>
    <f:facet name="toolbar">
      <af:toolbar id="t2">
        <af:commandToolbarButton actionListener="#{bindings.Create.execute}"
                                 text="Create New Supplier"
                                 disabled="#{!bindings.Create.enabled}"
                                 id="ctb1"/>
        <af:commandToolbarButton
                               actionListener="#{bindings.mergeSuppliers.execute}"
                               text="Commit New Suppliers"
                               disabled="#{!bindings.mergeSuppliers.enabled}"
                               id="ctb2"/>
      </af:toolbar>
    </f:facet>
    <f:facet name="statusbar"/>
    <af:table value="#{bindings.suppliersFindAll.collectionModel}"
              var="row" rows="#{bindings.suppliersFindAll.rangeSize}"
              emptyText="#{bindings.suppliersFindAll.viewable ? 'No data to
                                                  display.' : 'Access Denied.'}"
              fetchSize="#{bindings.suppliersFindAll.rangeSize}"
              rowBandingInterval="0"
              selectedRowKeys=
                        "#{bindings.suppliersFindAll.collectionModel.selectedRow}"
              selectionListener=
                  "#{bindings.suppliersFindAll.collectionModel.makeCurrent}"
              rowSelection="single" id="t1"
              partialTriggers="::ctb1 ::ctb2">
      <af:column sortProperty="supplierId" sortable="false"
                 headerText=
                    "#{bindings.suppliersFindAll.hints.supplierId.label}"
                 id="c6">
        <af:inputText value="#{row.bindings.supplierId.inputValue}"
                      label="#{bindings.suppliersFindAll.hints.supplierId.label}"
                required="#{bindings.suppliersFindAll.hints.supplierId.mandatory}"
              columns="#{bindings.suppliersFindAll.hints.supplierId.displayWidth}"
           maximumLength="#{bindings.suppliersFindAll.hints.supplierId.precision}"
                 shortDesc="#{bindings.suppliersFindAll.hints.supplierId.tooltip}"
                 id="it4">
          <f:validator binding="#{row.bindings.supplierId.validator}"/>
          <af:convertNumber groupingUsed="false"
                  pattern="#{bindings.suppliersFindAll.hints.supplierId.format}"/>
        </af:inputText>
      </af:column>
.
.
.
    </af:table>
  </af:panelCollection>
</af:form>

5.4.3 実行時に行われる処理: 作成および部分ページ・リフレッシュの動作方法

create操作にバインドされたボタンを起動すると、アクションが実行され、ページがレンダリングされることによりコレクションの新しいインスタンスが作成されます。ボタンは、表をリフレッシュするトリガーとして構成されているため、表の最上部に新しい空白行を表示して再描画されます。ユーザーが、マージ・メソッドにバインドされたボタンをクリックすると、行セットに新規作成された行がデータベースに挿入されます。部分ページ・リフレッシュの詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド』の「部分ページ・コンテンツのレンダリング」を参照してください。

5.4.4 行の作成および列のソートについて

表の列のソートが可能で、新規行を挿入する前にユーザーが列をソートした場合、新規行はソートされません。新規行もソートされるようにするには、ユーザーは、希望するソートとは反対のソートを行った後、再度ソートする必要があります。これは、表で列がすでにソートされていると見なされるためで、最初から希望のソート順をクリックしても列には何の効果もあらわれません。

たとえば、ユーザーが列を昇順でソートし、その後行を新たに追加するとします。最初、その行は最上部に表示されます。ユーザーが列を再度昇順でソートするようクリックすると、表は再ソートされません。これは、列がすでに昇順であると見なされるためです。ユーザーは、降順でソートした後に昇順でソートする必要があります。

行を挿入すると、データが特定の列で特定の順に自動的にソートされるようにする場合、プログラムでコミット後にSortEventをキューに入れ、ソートを実行するハンドラを実装します。

5.5 表に表示される属性の変更

「データ・コントロール」パネルを使用して表を作成したら、属性の削除、表示順序の変更、表示に使用されるコンポーネントの変更、コンポーネントの属性バインディングの変更ができます。新しい属性を追加したり、表を新規のデータ・コントロールに再バインドすることもできます。

既存のUIコンポーネントとバインディングの変更の詳細は、『Oracle Fusion Middleware Oracle Application Development Framework Fusion開発者ガイド』の表に表示される属性の変更に関する項を参照してください。