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

前
 
次
 

5 イベントの処理

この章では、サーバーおよびクライアントでのイベントの処理方法について説明します。

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

5.1 イベントおよびイベント処理の概要

従来のJSFアプリケーションでは、イベント処理は通常サーバーで行われます。JSFのイベント処理はJavaBeansイベント・モデルをベースにしており、JSFアプリケーションでイベント・クラスおよびイベント・リスナー・インタフェースを使用して、コンポーネントで生成されたイベントが処理されます。

アプリケーションでのユーザー・イベントの例には、ボタンまたはリンクのクリック、メニューまたはリストからの項目の選択、入力フィールドの値の変更などがあります。ボタンのクリックなどのユーザー・アクティビティが発生すると、イベントの情報を格納し、イベントを生成したコンポーネントを特定するイベント・オブジェクトがコンポーネントで作成されます。イベントはイベント・キューにも追加されます。JSFライフサイクルの適切なタイミングで、登録された適切なリスナーにイベントをブロードキャストするようにJSFからコンポーネントに指示し、リスナーでは、イベントを処理するリスナー・メソッドが起動されます。リスナー・メソッドでは、ユーザー・インタフェースでの変更のトリガーまたはバックエンド・アプリケーション・コードの起動、あるいはその両方が実行される場合があります。

標準JSFコンポーネントと同様に、コンポーネントがアクティブになると、ADF FacesコンポーネントでActionEventイベントが配信され、コンポーネントのローカル値が変更されると、ADF Facesの入力および選択コンポーネントでValueChangeEventイベントが配信されます。

たとえば、File Explorerアプリケーションでは、commandMenuItemコンポーネントを使用してユーザーがファイルまたはフォルダを新たに作成できるサブメニューが「ファイル」メニューに含まれます。ユーザーが「フォルダ」commandMenuItemをクリックすると、ActionEventイベントが起動されます。コンポーネントのactionListener属性の値として設定されているEL式がheaderManagerマネージドBeanのcreateNewDirectoryメソッドと解決されるため、このメソッドが起動されてディレクトリが新たに作成されます。


注意:

組込みイベント機能を持つADF Facesコンポーネントはformタグに含める必要があります。


ADF Facesは標準JSFイベント処理手法に準拠していますが、次の2つの主要な方法を提供することでイベント処理機能を向上させています。

5.1.1 イベントおよび部分ページ・レンダリング

標準JSFイベントとは異なり、ADF FacesイベントではAJAXスタイルの部分ポストバックがサポートされ、部分ページ・レンダリング(PPR)が行えます。フル・ページ・レンダリングのかわりに、ADF Facesのイベントおよびコンポーネントでは、リクエスト時にページの一部のみがリフレッシュされる部分ページ・レンダリングがトリガーされます。

特定のコンポーネントがイベント・ルート・コンポーネントとみなされます。イベント・ルート・コンポーネントによってページでの境界が決まり、その境界内のコンポーネントにのみライフサイクルが実行されます(ライフサイクルのこの機能の詳細は、4.3項「最適化されたライフサイクルの使用」を参照)。イベント・ルート内でイベントが発生すると、ルートの子であるこれらのコンポーネントのみがページでリフレッシュされます。イベント・ルート・コンポーネントの例はポップアップです。ポップアップ内でイベントが発生すると、ポップアップとその子のみが再レンダリングされ、ページ全体は再レンダリングされません。

イベント・ルート・コンポーネントとみなされるコンポーネントは、次のとおりです。

  • popup

  • region

  • panelCollection

  • calendar

  • editableValueHolderコンポーネント(inputTextなど)

また、特定のイベントは、特定のコンポーネントがイベント・ルート・コンポーネントであることを示します。たとえば、showDetailコンポーネントを展開または縮小する(8.9項「コンテンツの動的な表示および非表示」を参照)と送信される表示イベントは、showDetailコンポーネントがルートであることを示します。ライフサイクルはshowDetailコンポーネント(および子コンポーネントまたはこれをトリガーとするその他のコンポーネント)でのみ実行され、展開または縮小時にのみが再レンダリングされます。

表5-1に、ADF Facesでのイベント・タイプと、ソース・コンポーネントがイベント・ルートかどうかを示します。

表5-1 イベントとイベントのルート・コンポーネント

イベント・タイプ コンポーネントのトリガー先 イベント・ルートか

action

すべてのコマンド・コンポーネント

false

dialog

dialog

false

disclosure

showDetailshowDetailHeader

true

disclosure

showDetailItem

true

focus

treetreeTable

true

launch

すべてのコマンド・コンポーネント

NA

launchPopup

inputListOfValuesinputComboboxListOfValues

true

load

document

NA

poll

poll

true

popupOpened

popup

NA

popupOpening

popup

NA

popupClosed

popup

NA

propertyChange

すべてのコンポーネント

NA

queryEvent

queryquickQuery

true

queryOperation

queryquickQuery

true

rangeChange

table

NA

regionNavigation

region

NA

return

すべてのコマンド・コンポーネント

true

returnPopupData

inputListOfValuesinputComboboxListOfValues

true

returnPopup

inputListOfValuesinputComboboxListOfValues

true

rowDisclosure

treetreeTable

true

selection

treetreeTabletable

true

sort

treeTabletable

true

valueChange

すべての入力および選択コンポーネント(EditableValueHolderを実装するコンポーネント)

true



ヒント:

イベント・ルートを処理したときにイベント・ルートの外部にあるコンポーネントを処理する必要がある場合は、それらのコンポーネントのpartialTrigger属性をイベント・ルート・コンポーネントのIDに設定する必要があります。


5.1.2 クライアント側イベント・モデル

サーバー側のアクションおよび値変更イベントの他に、ADF Facesコンポーネントでは、クライアント側のアクションおよび値変更イベント、その他のサーバーおよびクライアント・イベントが起動されます。サーバー・コンポーネントとクライアント・コンポーネントの両方で生成されるイベント(選択イベントなど)も、サーバー・コンポーネントでのみ生成されるイベント(起動イベントなど)も、クライアント・コンポーネントでのみ生成されるイベント(ロード・イベントなど)もあります。

デフォルトでは、ほとんどのクライアント・イベントはサーバーに伝播されます。コンポーネントの状態の変更は、状態に矛盾がないよう自動的にサーバーと同期され、必要に応じてイベントがサーバーに送信され、追加処理が実行されます。ただし、イベントが伝播されないように構成できます。

また、サーバー側Javaコンポーネントにクライアント側イベント・リスナーを登録すると、RCFでJavaScriptコンポーネントが必要であるとみなされ、クライアント側コンポーネントが作成されます。

クライアント側JavaScriptイベントのソースはいくつかあります。DOMイベントやプロパティ変更イベントから自動的に導出されることもあれば、他のイベントの処理時に手動で作成することもできます。

5.2 ADF Facesサーバー・イベントの使用

ADF Facesには、多数のサーバー側イベントが用意されています。表5-2に、サーバーのADF Facesコンポーネントで生成されるイベントと、これをトリガーするコンポーネントを示します。

表5-2 ADF Facesサーバー・イベント

イベント トリガー元コンポーネント

ActionEvent

すべてのコマンド・コンポーネント

DialogEvent

dialog

DisclosureEvent

showDetailshowDetailHeadershowDetailItem

FocusEvent *

treetreeTable

LaunchEvent

すべてのコマンド・コンポーネント

LaunchPopupEvent

inputListOfValuesinputComboboxListOfValues

LoadEvent **

document

PollEvent

poll

QueryEvent

queryquickQuery

QueryOperationEvent

queryquickQuery

RangeChangeEvent

table

RegionNavigationEvent

region

ReturnEvent

すべてのコマンド・コンポーネント

ReturnPopupEvent

inputListOfValuesinputComboboxListOfValues

RowDisclosureEvent

treetreeTable

SelectionEvent

treetreeTabletable

SortEvent

treeTabletable

ValueChangeEvent

すべての入力および選択コンポーネント(EditableValueHolderを実装するコンポーネント)


*このフォーカスイベントは、特定のサブツリーがフォーカスされると生成され、クライアント側のキーボード・フォーカス・イベントとは異なります。

**LoadEventイベントは、初期ページの表示後に起動されます(データ・ストリーミング結果が遅れて到着する場合があります)。

すべてのサーバー・イベントには、関連付けられたコンポーネントに対するイベント・リスナーがあります。そのイベントを処理するハンドラを作成し、そのハンドラ・コードをコンポーネントのリスナーと関連付ける必要があります。

たとえば、File Explorerアプリケーションの場合、ユーザーが表の行を選択すると選択イベントが起動されます。表のselectionListener属性は、TableContentView.javaマネージドBeanのtableSelectFileItemハンドラ・メソッドにバインドされているため、このメソッドがイベントに対応して起動されます。

サーバー側イベントを処理する手順:

  1. マネージドBean(イベント・リスナーを使用するページの場合はバッキングBean)に、イベント(イベント・タイプ)を唯一のパラメータとし、voidを返すpublicメソッドを作成します。例5-1に、tableSelectFileItemハンドラのコードを示します。(マネージドBeanの作成と使用の詳細は、2.6項「マネージドBeanの作成と使用」を参照してください。)

    例5-1 イベント・リスナー・メソッド

      public void tableSelectFileItem(SelectionEvent selectionEvent)
      {
        FileItem data = (FileItem)this.getContentTable().getSelectedRowData();
        setSelectedFileItem(data);
      }
    

    ヒント:

    イベント・リスナー・コードがアプリケーションの複数ページで使用されることが多い場合、すべてのページでアクセスできるイベント・リスナー実装クラスの作成を検討します。すべてのサーバー・イベント・リスナー・クラスの実装では、processEvent()メソッド(Eventはイベント・タイプ)をオーバーライドする必要があります。

    たとえば、LaunchListenerイベント・リスナーは、LaunchEventのインスタンスを単一引数とします。実装では、次のメソッド・シグネチャに示すように、イベント処理メソッドをオーバーライドする必要があります。

    public void processLaunch (LaunchEvent evt) 
    {
      // your code here
    }
    

  2. イベント・リスナー・メソッドをコンポーネントに登録するには、構造ウィンドウでイベントを起動するコンポーネントを選択します。プロパティ・インスペクタでイベント・リスナー・プロパティの隣にあるドロップダウン・メニューを使用し、「編集」を選択します。

  3. 「属性の編集」ダイアログで、ステップ1で作成したマネージドBeanとメソッドを選択します。

    例5-2に、選択イベント・リスナー・メソッドをtableコンポーネントに登録するサンプル・コードを示します。

    例5-2 イベント・リスナー・メソッドの登録

    <af:table id="folderTable" var="file"
    . . . 
              rowSelection="single"
              selectionListener="#{explorer.tableContentView.tableSelectFileItem}"
    . . .
    </af:table>
    

5.3 ADF Facesクライアント・イベントに対するJavaScriptの使用

大部分のコンポーネントはクライアント側イベントでも使用できます。クライアントでイベントを処理すると、サーバーへのラウンドトリップが不要になります。クライアント側イベントを使用する場合、マネージドBeanにイベント・ハンドラ・コードを含めるかわりに、JavaScriptを使用し、コール元ページにもJavaScriptライブラリにも含めることができます。

デフォルトでは、クライアント・イベントはクライアントでのみ処理されます。ただし、ボタンがクリックされたことを示すAdfActionEventイベントのようにサーバーに配信されるイベント・タイプもあります。コンポーネントの状態に応じてサーバーに配信されるイベントもあります。たとえば、AdfValueChangeEventイベントは、autoSubmit属性がtrueに設定されている場合サーバーに配信されます。追加処理が不要な場合は、イベントのサーバーへの配信を取り消すことができます。ただし、取り消すことができないクライアント・イベントもあります。たとえば、popupOpenedイベント・タイプは、ポップアップ・ウィンドウが開くと配信されるため、このイベントのサーバーへの配信は取り消すことができません。


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

イベントのサーバーでの処理が不要な場合、イベントがサーバーに伝播されないよう、処理の最後にイベントを取り消すことを検討してください。詳細は、5.3.5項「イベントがサーバーに伝播されないようにする方法」を参照してください。


表5-3に、ADF Facesクライアント・コンポーネントで生成されるイベント、イベントがサーバーに送信されるかどうか、イベントが取消し可能かどうか、およびイベントをトリガーするコンポーネントをリストします。

表5-3ADF Facesクライアント・イベント

イベント・タイプ イベント・クラス サーバーへの伝播 取消し可能 トリガー元コンポーネント

action

AdfActionEvent

すべてのコマンド・コンポーネント

dialog

AdfDialogEvent

dialog

ユーザーがダイアログでOKボタンまたは取消しボタンを選択したとき

disclosure

AdfDisclosureEvent

showDetailshowDetailHeadershowDetailItem

公開状態がユーザーによって切り替えられたとき


AdfFocusEvent

treetreeTable


AdfLaunchPopupEvent

inputListOfValuesinputComboboxListOfValues

inlineFrameLoad

AdfDomComponentEvent

inlineFrame

内部のiframeloadイベントが起動されたとき。

load

AdfComponentEvent

document

ドキュメントのコンテンツがクライアントで表示された後(PPRナビゲーションが使用されている場合も含む)。onLoad DOMイベントには常に対応しません。


AdfPollEvent

poll

popupOpened

AdfPopupOpenedEvent

×

×

popup

ポップアップ・ウィンドウまたはダイアログが開いた後

popupOpening

AdfPopupOpeningEvent

×

popup

ポップアップ・ウィンドウまたはダイアログが開く前

popupClosed

AdfPopupClosedEvent

×

×

popup

ポップアップ・ウィンドウまたはダイアログが閉じた後

propertyChange

AdfPropertyChangeEvent

×

×

すべてのコンポーネント

query

AdfQueryEvent

queryquickQuery

問合せアクション時(ユーザーが検索アイコンまたは検索ボタンをクリックしたとき)

queryOperation

AdfQueryOperationEvent

queryquickQuery


AdfReturnEvent

すべてのコマンド・コンポーネント


AdfReturnPopupDataEvent

inputListOfValuesinputComboboxListOfValues


AdfReturnPopupEvent

inputListOfValuesinputComboboxListOfValues

rowDisclosure

AdfRowDisclosureEvent

treetreeTable

行の公開状態が切り替えられたとき

selection

AdfSelectionEvent

treetreeTabletable

選択状態が変わったとき

sort

AdfSortEvent

treeTabletable

ユーザーが表のデータをソートしたとき

touchStart
touchMove
touchEnd
touchCancel

AdfComponentTouchEvent

×

すべて

valueChange

AdfValueChangeEvent

すべての入力および選択コンポーネント(EditableValueHolderを実装するコンポーネント)

入力または選択コンポーネントの値が変更されたとき


ADF Facesでは、表5-4に示すように、クライアント・キーボードおよびマウス・イベントもサポートします。

表5-4 サポートされるキーボードとマウスのイベント・タイプ

イベント・タイプ イベントが発生するタイミング

click

ユーザーがコンポーネントをクリックしたとき

dblclick

ユーザーがコンポーネントをダブルクリックしたとき

mousedown

ユーザーがコンポーネント上でマウス・ボタンを押したとき

mouseup

ユーザーがコンポーネント上でマウス・ボタンを離したとき

mousemove

ユーザーがコンポーネント上でマウスを移動したとき

mouseover

コンポーネント内にマウスが移動したとき

mouseout

コンポーネントからマウスが移動したとき

keydown

コンポーネントのフォーカス中にユーザーがキーを押したとき

keyup

コンポーネントのフォーカス中にユーザーがキーを離したとき

keypress

コンポーネントのフォーカス中にキーを押す動作が正常に完了したとき

focus

コンポーネントがキーボード・フォーカスを得たとき

blur

コンポーネントがキーボード・フォーカスを失ったとき



ベスト・プラクティス:

キーボードとマウスのイベントは、AdfBaseEventクラスのAdfUIInputEventサブクラスを使用してネイティブDOMイベントをラップし、DOM本来のイベントへのアクセスだけでなく、キー・コード、マウス座標などを取得するための簡易関数も幅広く提供されます。AdfBaseEventクラスでは、これらのイベントの実装方法のブラウザ間の違いも考慮します。このため、getNativeEvent()メソッドを直接起動するのではなく、AdfUIInputEvent APIを使用する必要があります。


clientListenerタグによって、クライアント側イベント・ハンドラ・スクリプトをコンポーネントに登録する宣言的方法が提供されます。サポートされているクライアント・イベント・タイプが発生すると、スクリプトが起動されます。例5-3に、アクション・イベントに関連付けられているJavaScript関数の例を示します。

例5-3 clientListenerタグ

<af:commandButton id="button0"
                  text="Do something in response to an action">
  <af:clientListener method="someJSMethod" type="action"/>
</af:commandButton>

ヒント:

コンポーネントのJavaScriptプロパティのかわりにclientListenerタグを使用します。


5.3.1 クライアント側イベントの使用方法

クライアント側イベントを使用するには、まず、イベントを処理するJavaScriptを作成する必要があります。次に、clientListenerタグを使用します。

クライアント側イベントを使用する手順:

  1. JavaScriptイベント・ハンドラ関数を作成します。JavaScriptの作成の詳細は、3.3項「JavaScriptのページへの追加」を参照してください。この機能内で追加できるのは、次のとおりです。

    • ページでのクライアント・コンポーネントの検索

      イベント・ハンドラを別のコンポーネントで処理する場合、そのコンポーネントをページで検索する必要があります。たとえば、File Explorerアプリケーションでユーザーが「ヘルプ」メニューのフィードバック・メニュー項目を選択した場合、関連付けられているJavaScript関数でヘルプ・ポップアップ・ダイアログを開くには、このダイアログを検索する必要があります。クライアント・コンポーネントの検索の詳細は、3.5項「ページでのクライアント・コンポーネントの検索」を参照してください。

    • イベントの発生元の戻し

      ページに複数の同じコンポーネントがある場合、JavaScript関数でイベントを発行したコンポーネントを判断する必要があります。たとえば、同じポップアップ・ダイアログを開くことができる複数のコンポーネントがあり、コール元のコンポーネントと並べてそのダイアログを表示するとします。ポップアップ・ダイアログを並べる場所を決めるには、AdfLaunchPopupEventのソースが認識できる必要があります。詳細は、5.3.2項「イベントの発生元を返す方法」を参照してください。

    • クライアント属性の追加

      クライアント・イベント・ハンドラでコンポーネントの特定の属性を使用する必要が生じる場合があります。たとえば、File Explorerアプリケーションでユーザーが「ヘルプ」メニューの「バージョン情報」メニュー項目を選択すると、ユーザーがフィードバックを提供できるダイアログが起動します。このダイアログを開いて表示する関数は他のダイアログでも使用され、別個に表示する必要があります。このため、表示するダイアログとダイアログの配置情報を関数で認識できる必要があります。この情報はクライアント属性に保持されます。クライアント属性は、カスタムのサーバー側属性のクライアントへのマーシャリングにも使用できます。詳細は、5.3.3項「イベントのクライアント側属性の使用方法」を参照してください。

    • サーバーへの伝播の取消し

      表5-3に示すように、一部のコンポーネントではクライアント側イベントがサーバーへ伝播されます。この追加処理が不要な場合、伝播を取り消すことができます。詳細は、5.3.5項「イベントがサーバーに伝播されないようにする方法」を参照してください。

  2. JavaScript関数の作成後、イベント・メソッドをコールするイベント・リスナーを追加する必要があります。


    注意:

    また、ADF Facesコンポーネントのすべてのクライアント・イベントもクライアント動作として公開されるため、JSF 2.0クライアント動作タグ(f:ajaxなど)を使用して、クライアント・イベントに応答できます。詳細は、Java EE 6チュートリアル(http://download.oracle.com/javaee/index.html)を参照してください。


    1. JavaScriptを起動するコンポーネントを選択し、プロパティ・インスペクタでClientComponenttrueに設定します。

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

    3. 「クライアント・リスナーの挿入」ダイアログでメソッドを入力し、JavaScript関数のタイプを選択します。

      clientListenerタグのmethod属性で、対応するイベントが発生したときにコールするJavaScript関数を指定します。JavaScript関数は1つのパラメータ(イベント・オブジェクト)をとる必要があります。

      clientListenerタグのtype属性で、actionvalueChangeなどのタグでリスニングするクライアント・イベント・タイプを指定します。表5-3に、ADF Facesクライアント・イベントを示します。

      clientListenerタグのtype属性では、キーボードおよびマウスのイベントに関連するクライアント・イベント・タイプもサポートされます。表5-4に、キーボードとマウスのイベント・タイプを示します。

      例5-4に、Explorer.js JavaScriptファイルのshowHelpFileExplorerPopup関数の起動に使用されるコードを示します。

      例5-4 JSFページのclientListenerタグ

      <af:commandMenuItem id="feedbackMenuItem"
                          text="#{explorerBundle['menuitem.feedback']}"
                          clientComponent="true">
        <af:clientListener method="Explorer.showHelpFileExplorerPopup"
                           type="action"/>
      </af:commandMenuItem>
      
    4. コンポーネント・パレットの「操作」パネルからクライアント属性をドラッグして選択したコンポーネントの子としてドロップし、必要な属性を追加します。プロパティ・インスペクタで属性の名前と値を入力します。例5-5に、showAboutFileExplorerPopup関数の属性値の設定に使用されるコードを示します。

      例5-5 属性の追加

       <af:commandMenuItem id="aboutMenuItem"
                           text="#{explorerBundle['menuitem.about']}"
                           clientComponent="true">
          <af:clientListener method="Explorer.showAboutFileExplorerPopup"
                              type="action"/>
          <af:clientAttribute name="popupCompId" value=":fe:aboutPopup"/>
          <af:clientAttribute name="align" value="end_after"/>
          <af:clientAttribute name="alignId" value="aboutMenuItem"/>
        </af:commandMenuItem>
      

      注意:

      attributeタグ(clientAttributeタグではなく)を使用して、アプリケーション固有の属性やボーナス属性をサーバー・コンポーネントに追加した場合、これらの属性は、対応するクライアント・コンポーネントに含まれません。JSFページでclientAttributeタグを使用すると、サーバーとクライアントの両方で値が使用可能になります。クライアント値のサーバーへのポストバックの詳細は、5.4項「クライアントからサーバーへのカスタム・イベントの送信」を参照してください。ボーナス属性の詳細は、3.8項「クライアント側コンポーネントに対するボーナス属性の使用」を参照してください。


5.3.2 イベントの発生元を返す方法

JavaScriptメソッドgetSource()は、クライアント・イベントの発生元を返します。たとえば、File Explorerアプリケーションには、例5-6に示すshowAboutFileExplorerPopup関数が含まれており、クライアント属性を使用して値が受け渡され、特定のポップアップ・ダイアログまたはウィンドウの位置合せの設定に複数のイベントで使用できます。関数を使用する各イベントで属性の値が異なる場合があるため、対応する属性値にアクセスできるようイベントの発生元を関数で認識する必要があります(クライアント属性の使用の詳細は、5.3.3項「イベントのクライアント側属性の使用方法」を参照してください)。

例5-6 クライアント・イベントのソース・コンポーネントの検出

Explorer.showAboutFileExplorerPopup = function(event)
{
  var source = event.getSource();
  var alignType = source.getProperty("align");
  var alignCompId = source.getProperty("alignId"); 
  var popupCompId = source.getProperty("popupCompId");
  
  source.show({align:alignType, alignId:alignCompId});
  
  event.cancel();
}

getSource()メソッドがコールされ、現在のフォーカス・イベントを発生したクライアント・コンポーネント(このケースではポップアップ・コンポーネント)が決まります。

5.3.3 イベントのクライアント側属性の使用方法

スクリプトのロジックでコンポーネントになんらかの変更を加える場合があります。これを行うには、イベントによって受け渡される属性値が必要な場合があります。たとえば、File Explorerアプリケーションには、例5-7に示すshowAboutFileExplorerPopup関数が含まれており、クライアント属性を使用して値が受け渡され、特定のポップアップ・コンポーネントの位置合せの設定に使用できます。属性値には、ソース・コンポーネントでgetPropertyメソッドをコールしてアクセスします。

例5-7 JavaScriptからアクセスされる属性値

Explorer.showAboutFileExplorerPopup = function(event)
{
  var source = event.getSource();
  var alignType = source.getProperty("align");
  var alignCompId = source.getProperty("alignId"); 
  var popupCompId = source.getProperty("popupCompId");
  
  var aboutPopup = event.getSource().findComponent(popupCompId);  
  aboutPopup.show({align:alignType, alignId:alignCompId});
  
  event.cancel();
}

例5-8に示すように、値はソース・コンポーネントで設定されます。

例5-8 コンポーネントでの属性の設定

<af:commandMenuItem id="aboutMenuItem"
                    text="#{explorerBundle['menuitem.about']}"
                    clientComponent="true">
  <af:clientListener method="Explorer.showAboutFileExplorerPopup"
                     type="action"/>
  <af:clientAttribute name="popupCompId" value=":aboutPopup"/>
  <af:clientAttribute name="align" value="end_after"/>
  <af:clientAttribute name="alignId" value="aboutMenuItem"/>
</af:commandMenuItem>

このように属性を使用すると、同じイベントをトリガーする異なるコンポーネントでスクリプトを再利用できます。

5.3.4 イベント実行時のUI入力のブロック方法

実行時間が長いイベントの処理中に、ユーザーがUIを操作できないようにする場合があります。たとえば、アプリケーションがボタンを使用して命令を送信し、処理の一部にユーザーのアカウントに対する請求を作成する処理が含まれているとします。ユーザーが不注意でボタンを2回押した場合、そのアカウントは2回請求されることになります。サーバーの処理が完了するまでユーザーの操作をブロックすることで、誤ったクライアント・アクティビティが発生しないようにできます。

ADF Faces JavaScript APIには、AdfBaseEvent.preventUserInput関数が含まれています。preventUserInput関数をコールすると、ブラウザ・ウィンドウ全体がガラス・ペインで覆われ、イベントがサーバーへのラウンドトリップを完了するまで入力できなくなり、イベントの処理中にすべてのユーザー入力を阻止できます。

preventUserInput関数は、カスタム・イベント、カスタム・クライアント・スクリプトで発生したイベント、またはカスタム・クライアント・コンポーネントのピアで発生したイベントでのみ使用できます。また、イベントをサーバーに伝播する必要があります。例5-9に、JavaScriptでpreventUserInputを使用する方法を示します。

例5-9 UI入力のブロック

function queueEvent(event)
{
   event.cancel(); // cancel action event
   var source = event.getSource();
         
   var params = {};
   var type = "customListener";
   var immediate = true;
   var isPartial = true;
   var customEvent =  new AdfCustomEvent(source, type, params, immediate);
   customEvent.preventUserInput();
   customEvent.queue(isPartial);
}   

5.3.5 イベントがサーバーに伝播されないようにする方法

一部のクライアント・イベントは、クライアントでの処理が完了すると、デフォルトでサーバーに伝播されます。この伝播が行われないようにすることが必要な状況もあります。たとえば、ボタンがクリックされるとJavaScriptコードを実行するcommandButtonコンポーネントを使用している場合、サーバーにactionListenerイベント・リスナーがなければ、イベントを伝播することはリソースを無駄に消費することになります。サーバーへ伝播されないようにするには、リスナーでイベントのcancel()関数をコールします。cancel()関数がコールされると、isCanceled()関数でtrueが返されます。

例5-10に、伝播を取り消すshowAboutFileExplorerPopup関数を示します。

例5-10 クライアント・イベントのサーバーへの伝播の取消し

Explorer.showAboutFileExplorerPopup = function(event)
{
  var source = event.getSource();
  var alignType = source.getProperty("align");
  var alignCompId = source.getProperty("alignId"); 
  var popupCompId = source.getProperty("popupCompId");
  
  var aboutPopup = event.getSource().findComponent(popupCompId);  
  aboutPopup.show({align:alignType, alignId:alignCompId});
  
  event.cancel();
}

イベントを取り消すことで、行われないデフォルト処理もあります。たとえば、ポップアップ・メニューのAdfUIInputEventイベントを取り消すと、このイベントを受けて表示されるポップアップ・メニューがブラウザで表示されません。

イベントが取り消せない場合、cancel()関数コールは無視され、そのイベントはisCancelable()関数でfalseが返されることで示されます(取り消せないイベントは、表5-3で「取消し可能」列に「×」と表示されています)。これは、イベントが完了済の通知で、ブロックできないということを通常意味します。一度取り消したイベントの取消しを無効にすることもできません。

5.3.6 実行時の処理: クライアント側イベントの機能の仕方

イベント処理は、一般にブラウザのネイティブ・イベント・ループから捕捉されます。ページでは、ドキュメントにバブル・アップされるすべてのDOMイベントを受け取り、そのDOMに関連付けられているピアに渡します。ピアでは、DOMイベントをラップするリッチ・クライアントJavaScriptイベント・オブジェクトが作成され、ページに返され、イベントがキューイングされます(ピアとADF Facesアーキテクチャの詳細は、第3章「ADF Facesアーキテクチャの使用」を参照してください)。

各DOMイベントのページでの処理(この結果、通常コンポーネント・イベントがキューイングされる)後、ページのイベント・キューは、通常ブラウザのイベント・ループの最後で空になります。ただし、タイマー起動時にポーリング・イベントを発生するポーリング・コンポーネントなど、ユーザー入力とは無関係にイベントがキューイングされることがあるため、イベントをキューイングすると、ユーザー入力がなくても、イベント・キューを空にするタイマーも起動されます。

イベント・キューは先入れ先出しキューです。イベント・キューを空にするには、ページで各イベント・オブジェクトを捕捉し、イベント・ソースのbroadcast()関数に配信します。このループは、キューが空になるまで続きます。イベントのブロードキャストによって、導出された新規イベントのキューイングが間接的に引き起こされることは非常に理にかなっています(一般的です)。導出されたイベントは、同じループでブロードキャストされます。

イベントがコンポーネントにブロードキャストされると、コンポーネントで次の処理が行われます。

  1. イベントをピアのDispatchComponentEventメソッドに配信します。

  2. そのイベント・タイプ用に登録されているリスナーにイベントを配信します。

  3. イベントをバブルする必要があるかどうかを確認し、必要な場合はバブルを開始します。ほとんどのイベントがバブルされます。例外には、プロパティ変更イベント(キューイングされず、このプロセスにまったく関与しない)やマウスの移動イベント(効率を高めるため)があります。

    イベントがバブルされる時、イベントはAdfUIComponentHandleBubbledEvent関数に配信され、ここからピアのDispatchComponentEvent関数に渡されます。クライアント・イベント・リスナーではなく、ピアがイベントを受け取ることに注意してください。

    イベントのバブルは、イベントのstopBubbling()関数をコールしてブロックでき、その後、isBubblingStopped()関数でtrueが返され、バブルが止まります。取消し同様、このコールは元に戻すことはできません。


    注意:

    イベントを取り消してもバブルは止まりません。イベントの取消しとバブルの停止の両方を行う場合は、両方の関数をコールする必要があります。


  4. 前述の処理でイベントが取り消されない場合は、AdfUIComponent.HandleEventメソッドをコールします。このメソッドでは、イベントでのリクエストに応じてイベントがサーバー・イベント・キューに追加されます。

5.3.7 ネーミング・コンテナの使用について

ADF Facesのいくつかのコンポーネントは、pageTemplatesubformtableおよびtreeなどのNamingContainerコンポーネントです。NamingContainerコンポーネントを含むページでクライアント側APIとイベントを使用する場合、ソース・コンポーネントでfindComponent()メソッドを使用する必要があります。

たとえば、File Explorerアプリケーション内のページのコンポーネントはすべて最終的にはpageTemplateコンポーネント内にあるため、例5-11に示すように、JavaScript関数でgetSource()findComponent()メソッドを使用する必要があります。getSource()メソッドはAdfUIComponentクラスにアクセスし、コンポーネントの検出に使用できます。

例5-11 findComponent()メソッドを使用するJavaScript

function showPopup(event)
{
  event.cancel();
  var source = event.getSource();
  var popup = source.findComponent("popup");
  popup.show({align:"after_end", alignId:"button"});
}

findComponent()メソッドを使用すると、メソッドを起動したコンポーネントでローカルに検索が開始します。ネーミング・コンテナの使用の詳細は、3.5項「ページでのクライアント・コンポーネントの検索」を参照してください。

5.4 クライアントからサーバーへのカスタム・イベントの送信

clientAttributeタグでは、サーバーからクライアントへのボーナス属性の送信はサポートされますが、これらの属性のサーバーへの同期化は行われません。カスタム・データをサーバーに戻すには、AdfCustomEventクラスとserverListenerタグを使用して送信されるカスタム・イベントを使用します。

AdfCustomEvent.queue() JavaScriptメソッドによって、clientComponent属性がtrueに設定されているコンポーネントからカスタム・イベントを起動できます。カスタム・イベント・オブジェクトには、クライアント・イベント・ソースと、イベントに含まれるパラメータのマップに関する情報が含まれます。カスタム・イベントは即時配信(リクエスト値の適用フェーズ中)にも非即時配信(アプリケーションの起動フェーズ中)にも設定できます。

たとえば、File Explorerアプリケーションでは、ユーザーは左側の検索フィールドにファイル名を入力した後、[Enter]キーを押して検索を起動します。例5-12 に示すように、これは、inputTextフィールドに、[Enter]キーが押されると、JavaScript関数を起動するclientListenerが含まれているためです。

例5-12 clientListenerによってJavaScript関数が起動され、ServerLIstenerが起動される

//Code on the JSF page...
<af:inputText id="searchCriteriaName"
              value="#{explorer.navigatorManager.searchNavigator.
                                               searchCriteriaName}"
              shortDesc="#{explorerBundle['navigator.filenamesearch']}">
  <af:serverListener type="enterPressedOnSearch"
                     method="#{explorer.navigatorManager.
                                        searchNavigator.searchOnEnter}"/>
  <af:clientListener type="keyPress"
                     method="Explorer.searchNameHandleKeyPress"/>
</af:inputText>

//Code in JavaScript file...
Explorer.searchNameHandleKeyPress = function (event)
{
  if (event.getKeyCode()==AdfKeyStroke.ENTER_KEY)
  {
    var source = event.getSource();
    AdfCustomEvent.queue(source,
                         "enterPressedOnSearch", 
                         {}, 
                         false);
  } 
}

JavaScriptには、イベント・ソース、カスタム・イベント・タイプとして文字列enterPressedOnSearch、nullパラメータ・マップ、即時パラメータにFalseをとるAdfCustomEvent.queueメソッドが含まれています。

ページのinputTextにも、次のserverListenerタグが含まれています。

<af:serverListener type="enterPressedOnSearch"
                   method="#{explorer.navigatorManager.
                                      searchNavigator.searchOnEnter}"/>

タイプ値enterPressedOnSearchがJavaScriptのAdfCustomEvent.queueメソッドのパラメータの値と同じであるため、メソッド式#{explorer.navigatorManager.searchNavigator.searchOnEnter}に解決されるメソッドが起動されます。

5.4.1 クライアントからサーバーへのカスタム・イベントの送信方法

クライアントからサーバーへカスタム・イベントを送信するには、カスタム・イベント・タイプを使用してクライアント・イベントを起動し、バッキングBeanにサーバー・リスナー・メソッドを記述し、このメソッドでカスタム・イベントを処理する必要があります。次に、サーバー・リスナーをコンポーネントに登録します。

カスタム・イベントを送信する手順:

  1. イベント・ソース、カスタム・イベント・タイプおよびサーバーに送信するパラメータを指定してAdfCustomEvent.queue()メソッドを使用し、カスタム・イベントを処理するJavaScriptを作成します。

    たとえば、[Enter]キーが押されると検索機能を起動するJavaScriptでは、例5-13に示すようなイベント・ソース、カスタム・イベント・タイプとして文字列enterPressedOnSearch、nullパラメータ・マップ、即時パラメータとしてFalseをとるAdfCustomEvent.queueメソッドを使用します。

    例5-13 カスタム・イベント用のサンプルJavaScript

    Explorer.searchNameHandleKeyPress = function (event)
    {
      if (event.getKeyCode()==AdfKeyStroke.ENTER_KEY)
      {
        var source = event.getSource();
        AdfCustomEvent.queue(source,
                             "enterPressedOnSearch", 
                             {}, 
                             false);
      } 
    }
    
  2. マネージドBeanにサーバー・リスナー・メソッドを作成します。このメソッドはpublicで、oracle.adf.view.rich.render.ClientEventオブジェクトを引数とし、void型を返します。例5-14に、別のメソッドをコールして検索を実行し、ナビゲータをリフレッシュするだけのSearchNavigatorViewマネージドBeanに使用されるコードを示します。

    例5-14 カスタム・クライアント・イベント用サーバー・リスナー・メソッド

      public void searchOnEnter(ClientEvent clientEvent)
      {
        doRealSearchForFileItem();
        
        // refresh search navigator
        this.refresh();
      }
    

    注意:

    JavaからJavaScriptへの変換では、Numberschars、Java Objectsarraysおよび文字列でないCharSequencesの型情報が失われます。このため、サーバーに送信されるオブジェクトが初めはサーバーにある場合、変換が正しく行われるようにするロジックを追加します。5.4.3項「データのマーシャリングとアンマーシャリングについて」を参照してください。


  3. コンポーネント・パレットの「操作」パネルからクライアント・リスナーをドラッグしてイベントが発生するコンポーネントの子としてドロップし、clientListenerを登録します。


    注意:

    カスタム・クライアント・イベントを発生させるコンポーネントでは、クライアント側で生成されたコンポーネントが使用可能になるよう、clientComponent属性をtrueに設定します。


  4. 「クライアント・リスナーの挿入」ダイアログでメソッドを入力し、JavaScript関数のタイプを入力します。スクリプトがページに含まれていない場合はライブラリ名を必ず含めます。タイプはカスタム・イベントの識別に使用される任意の文字列が可能で、たとえば、File ExplorerではenterPressedOnSearchが使用されています。

  5. コンポーネント・パレットの「操作」パネルからサーバー・リスナーをドラッグしてclientListenerタグの兄弟としてドロップし、サーバー・リスナーを登録します。

  6. 「サーバー・リスナーの挿入」ダイアログで、enterPressedOnSearchなどのこのサーバー・リスナーに対する値としてクライアント・リスナーのタイプ値に使用される文字列を入力します。

    プロパティ・インスペクタで、2で作成したメソッドに解決される式をmethod属性に入力します。

5.4.2 実行時の処理: クライアント・リスナーとサーバー・リスナーの協働の仕方

実行時、[Enter]キーを押すなど、ユーザーによってイベントが発生すると、クライアント・リスナー・スクリプトが実行されます。このスクリプトでAdfCustomEvent.queue()メソッドをコールし、指定したイベント・タイプのカスタム・イベントが入力コンポーネントのキューに置かれます。入力コンポーネントに登録されているサーバー・リスナーがカスタム・イベントを受け取り、関連付けられているBeanメソッドが実行されます。

5.4.3 データのマーシャリングとアンマーシャリングについて

マーシャリングアンマーシャリングとは、プログラミング言語のデータ・オブジェクトをバイト・ストリームに変換し、同じプログラミング言語または別のプログラミング言語にネイティブのデータ・オブジェクトに戻すプロセスです。ADF Facesでは、マーシャリングとアンマーシャリングは、クライアント・エンドのJavaScriptとサーバー・エンドのJavaとの間で適切にやりとりできるようデータを適切な形式に変換することです。クライアントがブラウザベースの場合、JavaScript Object Notation(JSON)およびXMLの2つが一般的なマーシャリング方法です。ADF Facesでは両方の方法を組み合せて使用し、情報は、サーバーからクライアントには主にJSONで、クライアントからサーバーにはXMLで送信されます(JSONの詳細は、http://www.json.orgを参照してください)。

JavaScriptからJavaへ情報を送信する場合、JavaScriptデータ・オブジェクトはXMLに変換され(マーシャリング)、サーバー側で解析してJavaオブジェクトに戻されます(アンマーシャリング)。たとえば、cmdというIDのcommandButtonコンポーネントを含むJSFページを考えてみます。ユーザーがcommandButtonコンポーネントをクリックしたとき、このcommandButtonによってactionEventが発生したことをクライアントからサーバーに通信する必要があります。requestParameterマップで、情報がevent + . + id(idはコンポーネントのID)という形式を使用したキーにマップされます。つまり、commandComponentrequestParameterマップ・キーは、キーevent.cmdの値として格納されているXML文字列です。

この例でマーシャリング後のXMLフラグメントは次のようになります。

<m xmlns="http:/oracle.com/richClient/comm"><k v="type"><s>action</s></k></m>

例のmは、これがマップにアンマーシャルされることを表します。kはキーであることと、値がString型であることを表します。サーバー側でXMLフラグメントが、type(java.lang.String)をキーとし、action(java.lang.String)を値とする1つのエントリのjava.util.Mapに解析されます。

アンマーシャリングされた情報は、クライアントIDごとにまとめられ、リクエスト・マップに格納されてコンポーネントのデコード時に使用されます。この例では、commandButtonがデコードされるとき、クライアントID(event.cmd)を使用してクライアント・イベントがあるかどうかが確認され、検出された場合はアクションがキューイングされます(デコード動作は、commandButtonコンポーネントのレンダラ階層で実装されます)。

表5-5に、JavaScript型と対応するJava型のマッピングを示します。

表5-5 JavaScriptとJavaの型マップ

JavaScript型 Java型

Boolean

java.lang.Boolean

Number

java.lang.Double

String

java.lang.String

Date

java.util.Date

Array

java.util.ArrayList

Object

java.util.Map


JavaからJavaScriptへのマーシャリングは、ほとんどの場合JSONを使用して行われます。JSONがJavaScriptでのオブジェクト・リテラル表記法であるため、この種のマーシャリングは明らかです。クライアント・コンポーネントのプロパティは通常JSONでエンコードされます。次の例を考えてみます。

new AdfRichCommandButton('demoTemplate:richComand'
    {'partialSubmit':true,'useWindow':false})

2番目の引数({'partialSubmit':true,'useWindow':false})はJSONオブジェクトです。JSONがオブジェクトとして直接JavaScript環境に解析されるため、ブラウザ・エンドでの追加のアンマーシャリング処理が不要です。

表のエンコードでも、JSONを使用してプッシュ・メッセージをクライアントに渡します。エンコードされた1つのプッシュ・メッセージを含むエンベロープの例を次にしまします。

[{'rKey':'0','type':'update','data':[{'val':'Active Data Every Second: on row 0:78','prop':'value','cInd':0},{'val':'Active Data Every Second: on row 0:78','prop':'value','cInd':1}]}]

エンベロープは、1つのオブジェクトのみを含むJavaScript Arrayで、メッセージを表します。このメッセージには、変更のタイプ、データの実際の値などの情報が含まれ、クライアント側の表ピアで使用され、表自体が更新されます。

表5-6に、Java型と対応するJavaScript型のマッピングを示します。

表5-6JavaとJavaScriptの型マップ

Java型 JavaScript型

java.lang.Boolean

Boolean

java.lang.Double

Number

java.lang.Integer

Number

java.lang.Float

Number

java.lang.Long

Number

java.lang.Short

Number

java.lang.Character

String

java.lang.CharSequence

String

java.util.Collection

Array

java.util.Date

Date

java.util.Map

Object

Array

Array

java.awt.Color

TrColor


変換処理中に情報が失われる可能性あることに注意してください。たとえば、次の例に示すように、カスタム・イベントを使用して数値1と文字列testを送信するとします。

AdfCustomEvent.queue(event.getSource(), "something", {first:1, second:"test"});

JavaScriptからJavaへの変換では数値はDoublesに変換されるため、サーバー側リスナーでfirstパラメータの型がjava.lang.Doubleになります。ただし、初めはサーバー側でintだったパラメータが、JavaからJavaScriptへの変換で数値になった可能性もあります。サーバーへ戻る際にDoubleに変換されます。

5.5 イベント・レスポンス内でのスクリプトの実行

ExtendedRenderKitServiceクラスを使用すると、アクション・メソッド・バインディングの起動後などのイベント・レスポンスにJavaScriptを追加できます。これは、ユーザーにデータベース接続が確立できないことを通知するアラートの送信などの簡単なメッセージの場合もあれば、プログラムからポップアップ・ダイアログを終了させるためのポップアップ・ウィンドウでのhide()などの関数のコールの場合もあります。

たとえば、File ExplorerアプリケーションでユーザーがUpOneFolderナビゲーション・ボタンをクリックしてフォルダ構造を上に移動すると、フォルダ・ペインが再描画されて、選択した親フォルダが表示されます。UpOneFolderボタン・イベントのクリックを受けてHandleUpOneFolder()メソッドがコールされます。ExtendedRenderKitServiceクラスを使用してJavaScriptがレスポンスに追加されます。

例5-15に、actionListener属性が、ボタンがクリックされたときにアクション・イベントを処理するHandleUpOneFolder()ハンドラ・メソッドにバインドされているページのUpOneFolderコードを示します。

例5-15 JavaScriptをレスポンスに追加するメソッドの起動

<af:commandToolbarButton id="upOneFolder"
. . .
        actionListener="#{explorer.headerManager.handleUpOneFolder}"/>

例5-16に、ExtendedRenderKitServiceクラスを使用するhandleUpOneFolderメソッドを示します。

例5-16 JavaScriptのレスポンスへの追加

public void handleUpOneFolder(ActionEvent actionEvent)
 {
   UIXTree folderTree = 
     feBean.getNavigatorManager().getFoldersNavigator().getFoldersTreeComponent();
   Object selectedPath = 
    feBean.getNavigatorManager().getFoldersNavigator().getFirstSelectedTreePath();
    
   if (selectedPath != null)
    {
      TreeModel model = 
        _feBean.getNavigatorManager().getFoldersNavigator().getFoldersTreeModel();
      Object oldRowKey = model.getRowKey();
      try
      {
        model.setRowKey(selectedPath);
        Object parentRowKey = model.getContainerRowKey();
        if (parentRowKey != null)
        {
          folderTree.getSelectedRowKeys().clear();
          folderTree.getSelectedRowKeys().add(parentRowKey);
          // This is an example of how to force a single attribute
          // to rerender. The method assumes that the client has an optimized
          // setter for "selectedRowKeys" of tree.
          FacesContext context =  FacesContext.getCurrentInstance();
          ExtendedRenderKitService erks =
            Service.getRenderKitService(context,
                    ExtendedRenderKitService.class);
          String clientRowKey = folderTree.getClientRowKeyManager().
            getClientRowKey(context, folderTree, parentRowKey);
          String clientId = folderTree.getClientId(context);
          StringBuilder builder = new StringBuilder();
          builder.append("AdfPage.PAGE.findComponent('");
          builder.append(clientId);
          builder.append("').setSelectedRowKeys({'");
          builder.append(clientRowKey);
          builder.append("':true});");
          erks.addScript(context, builder.toString());
        }
      }
      finally
      {
        model.setRowKey(oldRowKey);
      }
      // Only really needed if using server-side rerendering
      // of the tree selection, but performing it here saves
      // a roundtrip (just one, to fetch the table data, instead
      // of one to process the selection event only after which
      // the table data gets fetched!)
      _feBean.getNavigatorManager().getFoldersNavigator().openSelectedFolder();
    } 
    
  }

5.6 クライアントの動作タグの使用

クライアント側での動作を実装する場合、通常はJavaScriptを記述し、それをクライアント・リスナーとしてコンポーネントに登録する必要がありますが、ADF Facesのクライアント動作タグを使用すると、一般的なクライアント操作を宣言的に実行できます。JavaScriptコードを記述するかわりにこれらのタグを使用して同じ処理を実装すると、ブラウザにダウンロードする必要のあるJavaScriptコードの量が少なくなります。

ADF Facesでは、クライアント・リスナーのかわりに使用できるクライアント動作タグが用意されています。

クライアント動作タグで、サーバー側イベント配信が自動的に取り消されます。したがって、親コンポーネントのactionListenerまたはaction 属性が無視されます。これは無効にすることができません。サーバー側の機能もトリガーする場合は、クライアント側イベントを使用する(5.3項「ADF Facesクライアント・イベントに対するJavaScriptの使用」を参照)か、AdfCustomEventおよびaf:serverListenerを使用してサーバー側イベントを配信するクライアント・リスナーを追加します(5.4項「「クライアントからサーバーへのカスタム・イベントの送信」を参照)。

5.6.1 scrollComponentIntoViewBehaviorタグの使用方法

ユーザーがページの特定のコンポーネントに移動できるようにする場合は、scrollComponentIntoViewBehaviorタグを使用します。このアクションは、HTMLのアンカーと似ています。たとえば、commandLinkコンポーネントを使用して、ユーザーがページの特定の部分に移動できるようにできます。richTextEditorおよびinlineFrameコンポーネントの場合は、サブコンポーネントに移動できます。たとえば、図5-1は、そのテキストに多数のセクションがあるrichTextEditorコンポーネントを示しています。エディタの下にあるコマンド・リンクを使用すると、テキストの特定部分に移動できます。

図5-1 エディタのscrollComponentIntoViewBehaviorタグ

エディタのscrollComponentIntoViewBehaviorタグ

ユーザーがスクロールしたコンポーネントにフォーカスを切り替えるためのタグを構成することもできます。

scrollComponentIntoViewBehaviorタグを使用する手順:

  1. ユーザーがクリックして、指定されたコンポーネントに移動するコマンド・コンポーネントを作成します。手順は、18.2.1項「コマンド・ボタンおよびコマンド・リンクの使用方法」を参照してください。

  2. コンポーネント・パレットの「操作」セクションから、「コンポーネントのビュー内へのスクロール動作」をコマンド・コンポーネントの子としてドラッグ・アンド・ドロップします。

  3. 「コンポーネントのスクロール表示動作の挿入」ダイアログで、ドロップダウン矢印を使用して「編集」を選択し、移動してユーザーの移動先であるコンポーネントを選択します。

  4. 移動後にコンポーネントにフォーカスを設定する場合は、プロパティ・インスペクタで、focus属性をtrueに設定します。

  5. richTextEditorまたはinlineFrameコンポーネントの場合は、オプションで、subTargetId属性の値を入力します。このIDは、richTextEditorまたはinlineFrameコンポーネントの値で定義されています。

    たとえば、図5-1に示されているscrollComponentIntoViewBehaviorタグのsubTargetId属性の値は、Introductionです。richTextEditorの値は、例5-17に示されているプロパティにバインドされています。Introductionは最初のヘッダーのIDです。

    例5-17 プロパティに定義されているsubTargetId値

    private static final String _RICH_SECTIONED_VALUE = 
      "<div>\n" + 
      "    <h2>\n" + 
      "      <a id=\"Introduction\"></a>Introduction</h2>\n" + 
      "    <p>\n" + 
      "      The ADF Table component is used to display a list of structured data. For example,\n" + 
      "      if we have a data structure called Person that has two properties - firstname and\n" + 
      "      lastname, we could use a Table with two columns - one for firstname, and the other\n" + 
      "      for lastname - to display a list of Person objects.\n" + 
      "    </p>\n" + 
      "  </div>\n" + 
      "  <div>\n" + 
      "    <h2>\n" + 
      "      <a id=\"The_Table_Model\"></a>The Table Model</h2>\n" + 
      "    <p>\n" + 
      . . .
       </div>";
    

5.7 ポーリング・イベントを使用したページの更新

ADF Facesでは、pollEventを使用して、指定した間隔でサーバーと通信できるポーリング・コンポーネントが提供されます。たとえば、ポーリング・コンポーネントを使用して、outputTextコンポーネントを更新したり、サーバーにハートビートを配信して、それらのセッションがタイムアウトするのを防ぐことができます。

ポーリング時に必要な処理を実行するのに使用されるpollEventに、リスナーを作成する必要があります。たとえば、ポーリング・コンポーネントを使用してoutputTextコンポーネントの値を更新する場合は、データ・ソースの値をチェックしてからコンポーネントを更新するpollEventListenerメソッドを実装します。

間隔時間を設定し、ポーリング・コンポーネントがそのポーリング・イベントを配信する頻度を決定できます。ページがタイムアウトするまでの時間を設定することもできます。これは、ページでのポーリングによりセッションがタイムアウトしないようにする場合に便利です。リクエストがサーバーに送信されるたびに、セッションのタイムアウト値がページに書き込まれ、セッションをいつタイムアウトするかが決定されます。ポーリング・コンポーネントは(間隔時間に基づいて)サーバーにリクエストを送信し続けるため、セッションがタイムアウトすることはありません。これは、ネットワークの使用とメモリーの両方で非効率になります。

この問題を回避するには、web.xml構成ファイルにoracle.adf.view.rich.poll.TIMEOUTコンテキスト・パラメータを含めます(タイムアウトするまでのページの実行時間を指定します)。キーボードまたはマウスのアクティビティがない場合、ページはタイムアウトできるとみなされます。デフォルトのタイムアウト時間は10分です。このため、ユーザーのアクティビティが10分間ない場合(キーボードやマウスを使用しない時間)は、フレームワークによりポーリングが停止され、その時点から、ページは標準のサーバ側セッション・タイムアウトに入ります(詳細は、A.2.3.22項「セッション・タイムアウトの警告」を参照)。

アプリケーションがタイムアウトした場合、ユーザーがマウスを移動したり、キーボードを再度使用すると、新しいセッション・タイムアウト値がページに書き込まれ、ポーリングが再開します。

ポーリング・コンポーネントのtimeout属性を使用して、特定のページでこのタイムアウトをオーバーライドできます。

5.7.1 ポーリング・コンポーネントの使用方法

ポーリング・コンポーネントを使用する場合、ポーリング・イベントの機能を処理するには、通常ハンドラ・メソッドも作成します。

開始前

属性が機能に与える影響について理解しておくと役立ちます。詳細は、5.7項「ポーリング・イベントを使用したページの更新」を参照してください。

ポーリング・コンポーネントを使用する手順:

  1. マネージドBeanで、ポーリング・コンポーネントのハンドラを作成します。マネージドBeanの詳細は、2.6項「マネージドBeanの作成と使用」を参照してください。

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

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

    • Interval: ポーリング・イベント間の時間を入力します(ミリ秒)。ポーリングを無効にするには0に設定します。

    • PollListener: 手順1のメソッドに評価されるEL式を入力します。

  4. web.xmlファイルのグローバル・タイムアウト値をオーバーライドする場合は、「その他」セクションを開き、「タイムアウト」に、ページがポーリングを停止してセッションがタイムアウトするまでの時間(ミリ秒)を設定します。