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

前
 
次
 

4 ADF Facesクライアント側アーキテクチャの使用方法

この章では、ADF Facesクライアント側アーキテクチャの概要を説明します。

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

4.1 ADF Facesアーキテクチャの使用について

ADF Facesは、JavaServer Facesアーキテクチャを拡張し、標準のサーバー中心モデルの上にクライアント側フレームワークを追加しています。ADF Facesコンポーネントの大部分は、リクエストのためにサーバー側で生成されるHTMLにレンダリングされます。また、ADF Facesでは、クライアント側コンポーネントとイベント・モデルを使用してクライアントに到達できるようにコンポーネントを実装できます。

ADF Facesフレームワークには、JavaScriptを使用するために通常必要な機能の多くがすでに含まれています。多くの場合、JavaScriptを使用しなくても、リッチなコンポーネント機能を宣言的に実現できます。ただし、クライアント側イベントに対するカスタム処理など、独自のJavaScriptを追加する必要がある場合があります。このような場合は、クライアント側フレームワークを使用できます。

最も多く対話対象となるJavaScriptクラスはAdfUIComponentとそのサブクラスです。このクラスのインスタンスは、サーバー側コンポーネントのクライアント側表現です。クライアント側コンポーネントは、イベント処理がサポートされる簡単なプロパティ・コンテナとみなすことができます。クライアント側コンポーネントは、主に、アプリケーション開発者とフレームワーク自体の両方に対するAPI規定を公開することでページに動作を追加するためにあります。特に、クライアントでのボタンの状態の切替えを可能にするのは、この規定です。

各クライアント・コンポーネントには、プロパティ(キーと値のペア)のセットと、サポートされている各イベント・タイプ用のリスナーのリストがあります。すべてのADF Faces JavaScriptクラスは、他のJavaScriptライブラリと名前が競合しないようAdfで始まります。たとえば、RichCommandButtonAdfRichCommandButtonを持ち、RichDocumentAdfRichDocumentを持つなどです。

クライアント側JavaScriptレイヤーでは、クライアント・コンポーネントは主にフレームワークおよび開発者にAPI規定を提供するために存在します。クライアント・コンポーネントは、状態を格納し、APIを提供するためにのみ存在するため、DOM(Document Object Model)と直接対話しません。DOMとのすべての対話は、ピアと呼ばれる媒介を使用して行われます。ピアは、Javaレンダラによって生成されたDOMと対話し、その状態の更新およびユーザー操作への応答を処理します。

ピアでは、この他に次のような多くの処理が行われます。

この分離により、コンポーネントおよびアプリケーション開発者がコンポーネントのDOM実装の変更から隔離され、コンポーネント(たとえば、Flashコンポーネント)がHTML DOMで実装されているかどうかをアプリケーションが知る必要もまったくなくなります。

大部分のコンポーネントベースのフレームワーク同様、JSFのコンポーネント・モデルに固有の特性は、コンポーネントはネストして階層(通常コンポーネント・ツリーと呼ばれる)を形成できるということです。これは、親コンポーネントで子が追跡され、コンポーネント・ツリーをたどって特定のコンポーネントの子孫をすべて見つけることができるということです。コンポーネント・ツリー全体はサーバーにあり、ADF Facesクライアント側コンポーネント・ツリーにはあまり移入されません。

パフォーマンスを最適化するために、クライアント・コンポーネントは、clientListenerハンドラが登録されているため、またはページ開発者がクライアント側のコンポーネントと対話する必要があり、クライアント・コンポーネントを使用可能として構成したため必要になった場合にのみ存在します。例外的なケースを除き、クライアント・フレームワークを理解する必要はありません。アーキテクチャ機能の大部分は、コードを作成せずに宣言的に使用できます。

たとえば、フレームワークでは、各サーバー側コンポーネントに対応するクライアント・コンポーネントをすべて作成するわけではないため、クライアント版のコンポーネント・インスタンスが必要な場合もあります。4.4項「クライアント側コンポーネントのインスタンス化」に、これを宣言的に行う方法が説明されています。JDeveloperのプロパティ・インスペクタを使用して、4.8項「レンダリングおよび可視性の理解」で説明されている、コンポーネントをレンダリングするかどうか、あるいは非表示にするかどうかを決めるプロパティを設定します。


注意:

既存のサーバー側コンポーネントに対応しないJavaScriptコンポーネントが存在することも可能です。たとえば、一部のADF Facesコンポーネントでは、ポップアップ・コンテンツが必要なクライアント側動作を持ちます。これらのコンポーネントでは、サーバー側Java RichPopupコンポーネントが存在しなくても、AdfRichPopup JavaScriptコンポーネントを作成できます。


その他の機能では、ADF Faces JavaScript APIの使用が必要な場合があります。たとえば、4.5項「ページでのクライアント・コンポーネントの検索」では、APIを使用して特定のクライアント側コンポーネントを探す方法を説明し、4.6項「クライアントでのコンポーネント・プロパティへのアクセス」では、特定のプロパティにアクセスする方法を説明しています。

JavaScriptを多用したフレームワークに共通する問題は、大規模なJavaScriptコード・ベースをクライアントに送信する最良の方法を決定することです。すべてのコードが単一のJavaScriptライブラリにある場合はダウンロード時間が長くなりますが、JavaScriptを多くのライブラリに分割しすぎると、ラウンドトリップが大量になります。この問題を軽減するために、ADF FacesではJavaScriptコードがパーティションに集約されます。JavaScriptライブラリ・パーティションには、コンポーネントのコードまたは通常一緒に使用される機能、あるいはその両方が含まれています。詳細は、4.9項「JavaScriptライブラリのパーティション化」を参照してください。

4.2 クライアント・イベントのリスニング

従来のJSFアプリケーションでは、クライアントでイベントを処理する場合、DOMレベルのイベントをリスニングする必要があります。ただし、これらの実装は移植可能な形式で配信されません。ADF Facesのクライアント側イベント・モデルはJSFイベント・モデルと似ていますが、クライアントで実装されます。クライアント側イベント・モデルはDOMの要約で、コンポーネントレベルのイベント・モデルとライフサイクルが提供され、サーバーから独立して実行されます。このため、ボタンのclickイベントをリスニングする必要がありません。かわりに、キーまたはマウスのイベントで発生するAdfActionEventイベントをリスニングできます。

クライアントによって送信されるイベントはすべてAdfBaseEventクラスのサブクラスです。各クライアント・イベントには、イベントをトリガーしたコンポーネントであるソースがあります。イベントには、イベントをリスニングするリスナーを判断するタイプ(actionまたはdialogなど)もあります。クライアント・リスナーは、af:clientListenerタグを使用してコンポーネントに宣言的に登録します。

4.2.1 クライアント・イベントをリスニングする方法

af:clientListenerタグを使用して、クライアント・イベントに対して対応するJavascriptをコールします。たとえば、クリックされたら"Hello World"アラートを表示する必要のあるボタンがあるとします。最初に、アラートを表示することでイベントに応答するJavaScript関数を作成する必要があります。次に、その関数を呼び出すクライアント・リスナーをコンポーネントに追加します。

始める前に

クライアント・イベント処理に関する知識が役立つ場合があります。詳細は、4.2項「クライアント・イベントのリスニング」を参照してください。

クライアント・イベントをリスニングする手順:

  1. JavaScript関数を実装します。たとえば、アラートを表示するには、例4-1に示すJavaScript関数を作成できます。

    例4-1 JavaScriptイベント・ハンドラ

    function sayHello(event)
      {
        alert("Hello, world!")
      }
    
  2. コンポーネント・パレットの「操作」パネルから、「クライアント・リスナー」を、イベントを起動するコンポーネントに子としてドラッグ・アンド・ドロップします。

    手順1で作成した関数と、リスナーが応答する必要のあるアクションのタイプを入力します。例4-2に、sayHello関数のリスナーに対して作成するコードを示します。

    例4-2 クライアント・リスナーの登録

    <af:commandButton text="Say Hello">
      <af:clientListener method="sayHello" type="action"/>
    </af:commandButton>
    

ヒント:

ボタンにクライアント・リスナーが登録されているため、フレームワークで、クライアント版のコンポーネントが自動的に作成されます。


クライアント版のコンポーネントがあるため、ボタンがクリックされると、AdfActionクライアント・イベントが起動されます。AdfActionイベントをリスニングするようclientListenerタグが構成されているため、sayHello関数が実行されます。クライアント側イベントの詳細は、6.3項「ADF Facesクライアント・イベントに対するJavaScriptの使用」を参照してください。

4.3 JavaScriptのページへの追加

インラインJavaScriptをページに直接追加するか、JavaScriptライブラリをページにインポートできます。ライブラリをインポートする場合は、ページ・コンテンツ・サイズが削減され、ライブラリをページ間で共有でき、ブラウザによってキャッシュできます。可能な場合には必ずJavaScriptライブラリをインポートする必要があります。インラインJavaScriptは、ページ固有の小さなスクリプトが必要な場合にのみ使用します。


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

JavaScriptを必要とするページにのみJavaScriptを含めると、JavaScriptがテンプレートに含まれている場合とは異なり、それを必要としないページではロードする必要がないため、パフォーマンスが向上します。ただし、ほとんどのページで同じJavaScriptコードを使用する場合は、ライブラリをインポートするためのスクリプトまたはタグをテンプレートに含めることを検討してください。

ただし、JavaScriptコード・ライブラリが非常に大きくなった場合、ライブラリを内容に応じて分割し、(テンプレートではなく)ページで必要な部分のみを含めることに注意してください。この方法で、ブラウザ・キャッシュが使用され、ページのHTMLコンテンツが小さくなるため、パフォーマンスが向上します。


4.3.1 インラインのJavaScriptの使用方法

JavaScriptをページに作成し、clientListenerタグを使用して呼び出します。

始める前に

ページへのJavaScriptの追加に関する知識が役立つ場合があります。詳細は、4.3項「JavaScriptのページへの追加」を参照してください。

インラインのJavaScriptを使用する手順:

  1. 例4-3に太字で示すコードを追加して、MyFaces Trinidadタグ・ライブラリをページのルート要素に追加します。

    例4-3 ページでのMyFaces Trinidadタグ・ライブラリ

    <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
              xmlns:f="http://java.sun.com/jsf/core"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
              xmlns:trh="http://myfaces.apache.org/trinidad/html">
    
  2. コンポーネント・パレットで、「レイアウト」パネルの「コア構造」グループから、「リソース」をページにドラッグ・アンド・ドロップします。


    注意:

    ページまたはテンプレートにf:verbatimタグを使用してJavaScriptを指定しないでください。


  3. リソースの挿入ダイアログで、ドロップダウン・メニューから「JavaScript」を選択し、「OK」をクリックします。

  4. ページの<af:resource>タグ内にJavaScriptを作成します。

    たとえば、例4-1に示すsayHello関数は、例4-4のようにJSFページに含めることができます。

    例4-4 インラインのJavaScript

    <af:resource>
      function sayHello()
      {
        alert("Hello, world!")
      }
    </af:resource>
    
  5. 構造ウィンドウで、JavaScriptを呼び出すコンポーネントを右クリックし、componentの中に挿入」「ADF Faces」「クライアント・リスナー」の順に選択します。

  6. クライアント・リスナーの挿入ダイアログで「メソッド」フィールドにJavaScript関数の名前を入力します。タイプ・フィールドで、関数を起動するイベント・タイプを選択します。

4.3.2 JavaScriptライブラリのインポート方法

af:resourceタグを使用して、ページからJavaScriptライブラリにアクセスします。このタグは、documentタグのmetaContainerファセットの内部に含める必要があります。

始める前に

ページへのJavaScriptの追加に関する知識が役立つ場合があります。詳細は、4.3項「JavaScriptのページへの追加」を参照してください。

ページからJavaScriptライブラリにアクセスする手順:

  1. documentタグの下に、例4-5に太字で示すコードを追加し、JavaScriptライブラリが含まれるディレクトリへの相対パスに/mySourceDirectoryを置き換えます。

    例4-5 JavaScriptライブラリへのアクセス

    <af:document>
      <f:facet name="metaContainer">
        <af:resource source="/mySourceDirectory"/>
      </facet>
      <af:form></af:form>
    </af:document>
    
  2. 構造ウィンドウで、JavaScriptを呼び出すコンポーネントを右クリックし、componentの中に挿入」「ADF Faces」「クライアント・リスナー」の順に選択します。

  3. クライアント・リスナーの挿入ダイアログで「メソッド」フィールドに関数の完全修飾名を入力します。たとえば、sayHello関数がMyScriptsライブラリにある場合、MyScripts.sayHelloと入力します。タイプ・フィールドで、関数を起動するイベント・タイプを選択します。

4.3.3 クライアント・イベント・ソースへのアクセスについて

JavaScriptでクライアント・コンポーネントにアクセスする必要がある場合、リスナーのコンテキストで行われ、イベントのソース・コンポーネントにアクセスする必要がある場合がしばしばあります。getSource()メソッドを使用してクライアント・コンポーネントを取得します。例4-6に、名前を表示するためにソース・クライアント・コンポーネントにアクセスするsayHello関数を示します。

例4-6 クライアント・イベント・ソースへのアクセス

function sayHello(actionEvent)
{
  var component=actionEvent.getSource();
  
  //Get the ID for the component
  var id=component.getId();

  alert("Hello from "+id);
}

クライアント・イベント・ソースへのアクセスの詳細は、6.3項「ADF Facesクライアント・イベントに対するJavaScriptの使用」を参照してください。クライアント側プロパティへのアクセスの詳細は、4.6項「クライアントでのコンポーネント・プロパティへのアクセス」を参照してください。実行時にクライアント・イベントを処理する方法の詳細は、6.3.7項「実行時の処理: クライアント側イベントの機能の仕方」を参照してください。

4.4 クライアント側コンポーネントのインスタンス化

デフォルトでは、フレームワークでは、どのコンポーネントが、対応するクライアント側コンポーネント・インスタンスを持つかについて保証されません。クライアント上のコンポーネントと対話するには、通常はclientListenerハンドラを登録します。登録されているclientListenerハンドラがコンポーネントにある場合、コンポーネントはクライアント側表現を自動的に持ちます。clientComponent属性をtrueに設定して、コンポーネントがクライアントで使用できるよう明示的に構成することもできます。

4.4.1 クライアント側インスタンス用にコンポーネントを構成する方法

clientComponent属性を使用してクライアント側インスタンスを持つようにコンポーネントを手動で構成できます。


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

クライアントのコンポーネントとプログラムで対話する場合にのみclientComponenttrueに設定します。



注意:

フレームワークが独自に使用するためにクライアント・コンポーネントを作成する場合、そのクライアント・コンポーネントにはその時点でフレームワークが必要とする情報のみ含まれます。たとえば、一部の属性は使用可能でない場合があります。


始める前に

クライアント側インスタンスに関する知識が役立つ場合があります。詳細は、4.4項「クライアント側コンポーネントのインスタンス化」を参照してください。

クライアント側インスタンスのコンポーネントを構成する手順:

  1. 構造ウィンドウで、クライアント側インスタンスを必要とするコンポーネントを選択します。

  2. プロパティ・インスペクタで、ClientSidetrueに設定します。

4.4.2 clientComponentをtrueに設定した場合の処理

clientComponent属性をtrueに設定すると、コンポーネントのAdfUIComponentクラスのインスタンスがフレームワークで作成されます。このクラスでは、クライアント側で操作できるAPIが提供され、基本的なプロパティ・アクセッサ・メソッド(getProperty()setProperty()など)、イベント・リスナーの登録およびイベント配信関連のAPIも提供されます。フレームワークには、プロパティ固有のアクセッサ・メソッド(getText()setText()など)を公開するレンダラ固有のサブクラス(AdfRichOutputTextなど)も用意されています。これらのアクセッサ・メソッドは、AdfUIComponentクラスのgetProperty()およびsetProperty()メソッドをラップするのみのラッパーで、コーディングが簡便になるよう用意されています。

たとえば、sayHello関数から値(表示するテキスト)を取得するoutputTextコンポーネントがページにあるとします。この関数は、値を設定するためにoutputTextコンポーネントにアクセスできる必要があります。これが機能するには、クライアント側バージョンのoutputTextコンポーネントがある必要があります。例4-7に、JSFページ・コードを示します。outputTextコンポーネントにid値があり、clientComponent属性がtrueに設定されていることに注意してください。また、値はJavaScriptで設定されるため、例には値がないことにも注意してください。

例4-7 コンポーネントの追加

<af:commandButton text="Say Hello">
  <af:clientListener method="sayHello" type="action"/>
</af:commandButton>

<af:outputText id="greeting" value="" clientComponent="true">

outputTextにクライアント側表現があるため、JavaScriptでこれを見つけて使用できます。

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

イベントのソースではないクライアント・コンポーネントを検索する必要がある場合、AdfUIComponent.findComponent(expr)メソッドを使用できます。このメソッドはJSFのUIComponent.findComponent()メソッドと似ており、指定した検索式に合致するIDを使用してUIComponentオブジェクトを検索して返します。AdfUIComponent.findComponent(expr)メソッドは、サーバーではなくクライアントでのみ機能します。

例4-8に、コンポーネントのIDを使用してoutputTextコンポーネントを検索するsayHello関数を示します。

例4-8 findComponent()を使用したクライアント・コンポーネントの検索

function sayHello(actionEvent)
{
  var buttonComponent=actionEvent.getSource();
  
  //Find the client component for the "greeting" af:outputText
  var greetingComponent=buttonComponent.findComponent("greeting");

  //Set the value for the outputText component
  greetingComponent.setValue("Hello World")
}

ADF Facesには、AdfPage.PAGE.findComponentByAbsoluteId(absolute expr)メソッドもあります。このメソッドは、IDの文字列をハードコーディングする場合に使用します。クライアントIDがコンポーネントから取得される場合は、AdfUIComponent.findComponent(expr)を使用します。


注意:

似たような名前のAdfPage.PAGE.findComponent(clientId)というメソッドもありますが、この関数は、リリース間で変わる可能性のある実装固有の識別子を使用し、ページ作成者は使用しません。


4.5.1 ネーミング・コンテナ内のコンポーネントの検索について

見つける必要があるコンポーネントがネーミング・コンテナ(pageTemplatesubformtableおよびtreeなど)であるコンポーネントにある場合は、AdfPage.PAGE.findComponentByAbsoluteId(absolute expr)メソッドを使用するかわりに、AdfUIComponent.findComponent(expr)メソッドを使用します。絶対式も相対式も使用できます。


ヒント:

コンポーネントがネーミング・コンテナかどうかは、コンポーネント・タグのドキュメントを確認して判断できます。タグのドキュメントには、コンポーネントがネーミング・コンテナかどうかが示されています。


絶対式では、NamingContainer.SEPARATOR_CHAR文字を先頭とし、完全修飾されたJSFクライアントID(コンポーネントを含むNamingContainerコンポーネントのすべてのIDが先頭に付けられる)を使用します。次に例を示します。

":" + (namingContainersToJumpUp * ":") + some ending portion of the clientIdOfComponentToFind

たとえば、myTemplateテンプレートを使用するページのID r1のリージョンに含まれるID pc1のパネル・コレクション・コンポーネント内にあるID t1の表を検索するには、次の文字列を使用できます。

:myTemplate:r1:pc1:t1

または、両方のコンポーネント(検索を実行するコンポーネントと検索されるコンポーネント)が同じNamingContainerコンポーネントを階層のどこかで共有する場合は、相対パスを使用して、検索を実行するコンポーネントとの相対で検索を実行できます。相対パスには、たとえば次のように、先頭に複数のNamingContainer.SEPARATOR_CHAR文字があります。

":" + clientIdOfComponentToFind

前述の例で、検索元のコンポーネントが表と同じリージョンにある場合、次を使用できます。

::somePanelCollection:someTable

ヒント:

ネーミング・コンテナをフォルダと考え、clientIdをファイル・パスと考えます。フォルダとファイルに関して、2つの連続ピリオドとスラッシュ(../)を使用して、階層内の上にホルダに移動します。これは、複数のコロン(:)文字がfindComponent()式で果たす役割と同じです。先頭の単一のコロン(:)は、ファイル・パスが、ファイル構造のルートからの絶対パスであることを意味します。式の先頭に複数のコロン(:)文字がある場合、最初のコロンは無視され、他のコロンは考慮されます。コロン(:)文字当たり1セットのピリオドとスラッシュ(../)が考慮されます。

AdfPage.findComponentByAbsoluteId()メソッドを使用する場合、パスは常に絶対パスであるため、先頭のコロンは不要です。


絶対パスを使用するか相対パスを使用するかを決める際、次の点に注意します。

  • 検索対象のコンポーネントが常に同じネーミング・コンテナ内あることがわかっている場合は、絶対パスを使用します。

  • 検索元のコンポーネントと検索対象のコンポーネントの相対的位置が常に同じであることがわかっている場合は、相対パスを使用します。

クライアントにはgetChildren()関数もgetFacet()関数もありません。かわりに、すべての子コンポーネントとファセット(つまり、すべての子孫)にアクセスするAdfUIComponent.visitChildren()関数が用意されています。ADF Facesはスパース・コンポーネント・ツリー(クライアント・コンポーネントが必要に応じて作成されるツリー)であるため、getParent()メソッドがクライアントで返すコンポーネントは、サーバー上の実際の親ではない場合があります(先祖である可能性はあります)。同様に、クライアント上に直接の子として出現するコンポーネントは、任意の子孫である可能性があります。詳細は、ADF Faces JavaScriptのドキュメントを参照してください。

4.6 クライアントでのコンポーネント・プロパティへのアクセス

コンポーネントの各組込みプロパティには、簡易アクセッサ・メソッドがコンポーネント・クラスに用意されています。たとえば、クライアント・コンポーネントでgetValue()メソッドをコールし、サーバーで使用されたのと同じ値を受け取ることができます。


注意:

ADF Faces内のブール・プロパティを含むすべてのクライアント・プロパティでgetXyz関数ネーミング規則を使用します。ブール・プロパティのisXyzネーミング規則は使用されません。


定数もクラス・オブジェクトのプロパティ名に使用できます。たとえば、styleClassを使用するかわりにAdfRichDialog.STYLE_CLASS定数を使用できます。


注意:

一部のJavaScript実行環境では、文字列をコーディングすると呼出しのたびにオブジェクトを割り当てる必要があるため、JavaScriptでは、文字列をコーディングするよりも定数を参照する方が効率的です。


コンポーネントのプロパティが変更されると、最終的な結果として、コンポーネントのDOMが新しい状態を反映するように更新されます。場合によっては、サーバーへのラウンドトリップは発生しません。このプロセスにおけるコンポーネントのロールはかなり限られています。新しいプロパティ値を格納してから、変更をピアに通知するだけです。ピアには、新しいコンポーネント状態を反映するようにDOMを更新するロジックが含まれます。


注意:

すべてのプロパティの変更が、クライアント側のピアを使用して処理されるわけではありません。一部のプロパティ変更はサーバーに伝播され、PPRを使用してコンポーネントがレンダリングされます。


クライアントに設定されるほとんどのプロパティ値は、サーバーとの自動同期が行われる原因になります(ただし、一部の複合Javaオブジェクトはクライアントにまったく送信されません)。ただし、これとは異なる動作をするセキュア・プロパティと分離プロパティの2種類のプロパティがあります。

セキュア・プロパティは、クライアントにまったく設定できないプロパティです。たとえば、悪意のあるクライアントでJavaScriptを使用してcommandLinkコンポーネントのimmediateフラグがtrueに設定されるとします。この変更がサーバーに伝播された結果、サーバー側の検証が省略され、セキュリティ・ホールとなる可能性があります(immediateプロパティの使用の詳細は、5.2項「immediate属性の使用」を参照してください)。つまり、immediateプロパティはセキュア・プロパティです。

JavaScriptからセキュア・プロパティの設定を試みると失敗します。詳細は、4.6.3項「無効化されたプロパティを非保護にする方法」を参照してください。表4-1に、クライアント・コンポーネントのセキュア・プロパティを示します。

表4-1 セキュア・クライアント・プロパティ

コンポーネント セキュア・プロパティ

AdfRichChooseColor

colorData

AdfRichComboboxListOfValue

disabled

readOnly

AdfRichCommandButton

disabled

readOnly

blocking

AdfRichCommandImageLink

blocking

disabled

partialSubmit

AdfRichCommandLink

readOnly

AdfRichDialog

dialogListener

AdfRichDocument

failedConnectionText

AdfRichInputColor

disabled

readOnly

colorData

AdfRichInputDate

disabled

readOnly

valuePassThru

AdfRichInputFile

disabled

readOnly

AdfRichInputListOfValues

disabled

readOnly

AdfRichInputNumberSlider

disabled

readOnly

AdfRichInputNumberSplinBox

disabled

readOnly

maximum

minimum

stepSize

AdfRichInputRangeSlider

disabled

readOnly

AdfRichInputText

disabled

readOnly

secret

AdfRichPopUp

launchPopupListener

model

returnPopupListener

returnPopupDataListener

createPopupId

AdfRichUIQuery

conjunctionReadOnly

model

queryListener

queryOperationListener

AdfRichSelectBooleanCheckbox

disabled

readOnly

AdfRichSelectBooleanRadio

disabled

readOnly

AdfRichSelectManyCheckbox

disabled

readOnly

valuePassThru

AdfRichSelectManyChoice

disabled

readOnly

valuePassThru

AdfRichSelectManyListBox

disabled

readOnly

valuePassThru

AdfRichSelectManyShuttle

disabled

readOnly

valuePassThru

AdfRichSelectOneChoice

disabled

readOnly

valuePassThru

AdfRichSelectOneListBox

disabled

readOnly

valuePassThru

AdfRichSelectOneRadio

disabled

readOnly

valuePassThru

AdfRichSelectOrderShuttle

disabled

readOnly

valuePassThru

AdfRichUITable

filterModel

AdfRichTextEditor

disabled

readOnly

AdfUIChart

chartDrillDownListener

AdfUIColumn

sortProperty

AdfUICommand

actionExpression

returnListener

launchListener

immediate

AdfUIComponentRef

componentType

AdfUIEditableValueBase

immediate

valid

required

localValueSet

submittedValue

requiredMessageDetail

AdfUIMessage.js

for

AdfUINavigationLevel

level

AdfUINavigationTree

rowDisclosureListener

startLevel

immediate

AdfUIPage

rowDisclosureListener

immediate

AdfUIPoll

immediate

pollListener

AdfUIProgress

immediate

AdfUISelectBoolean

selected

AdfUISelectInput

actionExpression

returnListener

AdfUISelectRange

immediate

rangeChangeListener

AdfUIShowDetailBase

immediate

disclosureListener

AdfUISingleStep

selectedStep

maxStep

AdfUISubform

default

AdfUITableBase

rowDisclosureListener

selectionListener

immediate

sortListener

rangeChangeListener

showAll

AdfUITreeBase

immediate

rowDisclosureListener

selectionListener

focusRowKey

focusListener

AdfUITreeTable

rowsByDepth

rangeChangeListener

AdfUIValueBase

converter


ADF Facesでは、disabledプロパティを非保護にできるように構成できます。この機能は、JavaScriptを使用してボタンを有効および無効にする必要がある場合に役立ちます。

分離プロパティは、クライアントで設定できるがサーバーに伝播することはできないプロパティです。これらのプロパティには、サーバーのライフサイクルに依存しないクライアント上のライフサイクルがあります。たとえば、クライアント・フォーム入力コンポーネント(AdfRichInputTextなど)には、JavaのEditableValueHolderコンポーネントのようにsubmittedValueプロパティがあります。ただし、このプロパティの設定はサーバーに直接影響しません。この場合、標準のフォーム送信手法によって、送信された値のサーバーでの更新を処理します。

プロパティは、分離とセキュアの両方にすることができます。実際には、このようなプロパティはクライアント上で分離プロパティのように動作します。これらはクライアントで設定できますが、サーバーには送信されません。ただし、サーバーではセキュア・プロパティとして動作するため、クライアントがこれらを設定しようとすると拒否されます。

4.6.1 クライアントでのプロパティ値の設定方法

ADF Facesフレームワークには、基礎となるADFUIComponent.setProperty関数をコールして適切なプロパティ名を渡す便利なsetXYZ関数が用意されています(詳細は、ADF Faces JavaScript JavaDocを参照してください)。例4-9に、setProperty関数を使用して、値が変更されたときにinputTextコンポーネントのbackgroundcolorプロパティを赤に設定する方法を示します。

例4-9

<af:form>
  <af:resource type="javascript">
    function color(event) {
        var inputComponent = event.getSource();
        inputComponent.setproperty("inlineStyle", "background-color:Red");
    }
  </af:resource>
  <af:outputText id="it" label="label">
    <af:clientListener method="color" type="valueChange"/>
  </af:inputText>
</af:form>

これらの関数を使用してプロパティの値を変更できます。分離プロパティまたはセキュア・プロパティでないかぎり、値はサーバー上でも変更されます。

4.6.2 クライアント上のプロパティの設定について

プロパティの値をサーバーに常に配信して同期することは望ましくない場合があります。たとえば、フォームにinputTextコンポーネントがあり、ユーザーがコンポーネントの1つで値を変更したらすぐに、変更済インジケータを表示するとします。この操作を行うには、JavaScriptを使用して、valueChangeEventイベントが配信されたらクライアント・コンポーネントのchanged属性をtrueに設定します。また、ユーザーがページを送信した場合は、その時点で値が保存されるため、変更済インジケータを表示しません。

次の例に示すように、JavaScriptを使用して、valueChangeEventが配信されたらchanged属性をtrueに設定します。

例4-10 JavaScriptを使用したchangedプロパティの設定

<af:form>
  <af:resource type="javascript">
    function changed(event) {
        var inputComponent = event.getSource();
        inputComponent.setChanged(true);
    }
  </af:resource>
  <af:inputText id="it" label="label">
    <af:clientListener method="changed" type="valueChange"/>
  </af:inputText>
  <af:commandButton text="Submit"/>
</af:form>

コンポーネントのすべてのプロパティは一般にサーバーと同期されるため、この例を使用すると、changed属性の値(true)はサーバーにも送信されます。このため、変更済インジケータは引き続き表示されます。

値がサーバーに保存されたときにインジケータを表示しないようにするには、次のいずれかの代替方法を使用できます。

  • イベント・リスナーを使用して、ロジックをクライアントからサーバーに移動します。この代替方法は、valueChangeEventイベントなど、サーバーに配信されるイベントがある場合に使用します。例4-11に、JSPコード例を示します。

    例4-11 サーバー上のプロパティ値を設定するJSPコード

    <af:form>
      <af:inputText label="label"
                    autoSubmit="true"
                    changed="#{test.changed}"
                    valueChangeListener="#{test.valueChange}"/>
      <af:commandButton text="Submit" />
    </af:form>
    

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

    例4-12 マネージドBeanを使用したプロパティ値の設定

    import javax.faces.event.ValueChangeEvent;
    import oracle.adf.view.rich.context.AdfFacesContext;
     
    public class TestBean {
        public TestBean() {}
        
        public void valueChange(ValueChangeEvent valueChangeEvent) 
        {
          setChanged(true);
          AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
          adfFacesContext.addPartialTarget(valueChangeEvent.getComponent());   
          FacesContext.getCurrentInstance().renderResponse();
        }
        
        public void setChanged(boolean changed) 
        {
            _changed = changed;
        }
     
        public boolean isChanged() 
        {
            return _changed;
        }    
        private boolean _changed;
    }
    
  • カスタム・サーバー・イベントとserverListenerタグを呼び出すJavaScriptを使用して、ロジックをサーバーに移動します。この方法は、配信されるイベントがない場合に使用します。例4-13に、JSPコードを示します。

    例4-13 JavaScriptとサーバー・リスナーを使用してプロパティ値を設定するJSPコード

    <af:form>
      <af:resource type="javascript">
        function changed(event) 
        {
          var inputComponent = event.getSource();
          AdfCustomEvent.queue(inputComponent, "myCustomEvent", null, true);
        }
      </af:resource>
      <af:inputText label="label" changed="#{test2.changed}">
        <af:serverListener type="myCustomEvent"
                           method="#{test2.doCustomEvent}"/>
        <af:clientListener method="changed" type="valueChange"/>
      </af:inputText>
      <af:commandButton text="Submit"/>
    </af:form>
    

    例4-14に、マネージドBeanコードを示します。

    例4-14 カスタム・イベントを使用したプロパティ値の設定

    package test;
     
    import javax.faces.context.FacesContext;
     
    import oracle.adf.view.rich.context.AdfFacesContext;
    import oracle.adf.view.rich.render.ClientEvent;
     
    public class Test2Bean
    {
      public Test2Bean()
      {
      }
     
      public void doCustomEvent(ClientEvent event)
      {
        setChanged(true);
        AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
        adfFacesContext.addPartialTarget(event.getComponent()); 
        FacesContext.getCurrentInstance().renderResponse();
      }
     
      public void setChanged(boolean changed)
      {
        _changed = changed;
      }
     
      public boolean isChanged()
      {
        return _changed;
      }
      private boolean _changed;
     
    }
    
  • クライアント・コンポーネントでchanged属性をtrueに設定し、これがサーバーに伝播されますが、その後コマンド・コンポーネントでactionListenerを使用して、changed属性をfalseに戻します。例4-15に、JSPコードを示します。

    例4-15 コマンド・コンポーネント上のリスナーを使用してプロパティ値を設定するJSPコード

    <af:form>
      <af:resource type="javascript">
        function changed(event) {
          var inputComponent = event.getSource();
          inputComponent.setChanged(true);
        }
      </af:resource>
      <af:inputText binding="#{test3.input}" label="label">
        <af:clientListener method="changed" type="valueChange"/>
      </af:inputText>
      <af:commandButton text="Submit" actionListener="#{test3.clear}"/>
    </af:form>
    

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

    例4-16 ActionLIstenerを使用したプロパティ値の設定

    package test;
     
    import javax.faces.event.ActionEvent;
     
    import oracle.adf.view.rich.component.rich.input.RichInputText;
     
    public class Test3Bean
    {
      public Test3Bean()
      {
      }
      
      public void clear(ActionEvent actionEvent)
      {
        _input.setChanged(false);
      }
     
      public void setInput(RichInputText input)
      {
        _input = input;
      }
     
      public RichInputText getInput()
      {
        return _input;
      }  
      
      private RichInputText _input;
    }
    

4.6.3 無効化されたプロパティを非保護にする方法

unsecuredプロパティを使用して、disabledプロパティを非保護に設定します。disabledプロパティを非保護にする必要のあるコンポーネントのコードに、このプロパティとdisabledの値を手動で追加する必要があります。たとえば、disabledプロパティを非保護にする必要のあるボタンのコードは次のようになります。

<af:commandButton text="commandButton 1" id="cb1" unsecure="disabled"/>

unsecure属性をdisabledに設定すると、悪意のあるJavaScriptがdisabled属性を不注意で変更する可能性があります。たとえば、支出承認ページがあり、そのページで特定のマネージャが$200未満の請求書のみ承認できるようにするとします。そのため、現在のユーザーが請求書の承認を許可されていないかぎり、承認ボタンを無効にする必要があります。

unsecured属性disabledに設定していない場合、承認ボタンは、現在のユーザーが支出を承認できるかどうかを判断するロジックがあるサーバーとのラウンドトリップが発生するまで無効なままになります。ただし、ページに支出がロードされたときにはボタンを正しく表示する必要があるため、unsecure属性をdisabledに設定します。これで、クライアントでJavaScriptを使用して、ボタンを無効にするかどうかを判断できます。ただし、この場合は、任意のJavaScript(制御できない悪意のあるJavaScriptを含む)が同じことを行う可能性があります。

悪意のあるJavaScriptを回避するには、ボタンが悪意のあるクライアント側Javascriptによって有効にされた可能性があるため、現在のマネージャが承認を実行する前に適切な支出管理権限を持っていることを必ず再チェックする必要があることを、アプリケーションで常に想定する必要があります。支出レポート承認画面で、金額が$200未満であることをチェックするJavaScriptがあっても、承認ボタンのアクションではサーバー上のロジックを実行する必要があります。サーバーにロジックを追加すると、無効な属性を変更してはならない場合に、それが変更されません。

同様に、アプリケーションを実行時に変更できるようにし、ユーザーがunsecureまたはdisabled属性、あるいはその両方を編集できるようにする場合は、サーバーとのラウンドトリップが発生した場合と同じロジックがアプリケーションによって実行されるようにする必要があります。

4.6.4 実行時の処理: クライアント・プロパティのクライアントでの設定方法

クライアントでsetProperty()関数をコールすると、プロパティが新しい値に設定され、同時にPropertyChangeEventイベントが古い値と新しい値を使用して起動されます(値が異なる場合)。また、プロパティを設定すると、コンポーネントが自身を再レンダリングする場合があります。

4.7 クライアント側コンポーネントに対するボーナス属性の使用

組込みプロパティ以外の情報をクライアントに送信する必要がある場合もあります。これは、ボーナス属性を使用して行えます。ボーナス属性は、clientAttributeタグを使用してコンポーネントに追加できる追加属性です。パフォーマンス上の理由から、クライアントに送信されるボーナス属性は、clientAttributeで指定されたもののみです。

clientAttributeタグでは、サーバー側コンポーネントの属性マップに追加される名前と値のペアを指定します。サーバー側属性マップの移入に加えて、clientAttributeタグを使用すると、ボーナス属性がクライアントに送信され、AdfUIComponent.getProperty("bonusAttributeName")メソッドを使用してアクセスできます。

フレームワークで、属性値のクライアントへのマーシャリングが行われます。マーシャリング・レイヤーで、文字列、ブール、数値、日付、配列、マップなど、各オブジェクト型のマーシャリングがサポートされます。マーシャリングの詳細は、6.4.3項「データのマーシャリングとアンマーシャリングについて」を参照してください。


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

マーシャリングによる過度のオーバーヘッドを防ぐため、クライアント側ボーナス属性を多用しないでください。



注意:

clientAttributeタグは、(アプリケーションで定義される)ボーナス属性にのみ使用します。クライアントで標準のコンポーネント属性にアクセスする必要がある場合、clientAttributeタグを使用するのではなく、clientComponent属性をtrueに設定します。詳細は、4.4項「クライアント側コンポーネントのインスタンス化」を参照してください。


4.7.1 ボーナス属性の作成方法

コンポーネント・パレットを使用して、ボーナス属性をコンポーネントに追加できます。

始める前に

ボーナス属性に関する知識が役立つ場合があります。詳細は、4.7項「クライアント側コンポーネントに対するボーナス属性の使用」を参照してください。

ボーナス属性を作成する手順:

  1. 構造ウィンドウで、ボーナス属性を追加するコンポーネントを選択します。

  2. コンポーネント・パレットで、「操作」パネルから「クライアント属性」をコンポーネントに子としてドラッグ・アンド・ドロップします。

  3. プロパティ・インスペクタで「名前」「値」属性を設定します。

4.7.2 ボーナス属性のマーシャリングについて

クライアント側ボーナス属性は、サーバーからクライアントへ自動的に配信されますが、その逆は行われません。つまり、クライアントでのボーナス属性の変更または設定は、サーバーに反映されません。既知(ボーナス以外)の属性のみ、クライアントからサーバーへ同期がとられます。アプリケーションで定義されたデータをサーバーに送り返す必要がある場合、カスタム・イベントを作成します。詳細は、6.4項「クライアントからサーバーへのカスタム・イベントの送信」を参照してください。

4.8 レンダリングおよび可視性の理解

すべてのADF Faces表示コンポーネントには、コンポーネントをページに表示してユーザーに見えるようにするかどうかに関係するrenderedvisibleの2つの属性があります。

rendered属性のセマンティクは非常に厳密です。renderedfalseに設定されている場合、サーバーへのラウンドトリップなしにコンポーネントをクライアントで表示することはできません。ページのコンテンツの動的な表示/非表示をサポートするために、フレームワークにはvisible属性が追加されています。falseに設定されている場合、コンポーネントのマークアップはクライアントで使用可能ですが、コンポーネントは表示されません。したがって、setVisible(true)またはsetVisible(false)メソッドをコールすると、JavaからのコールであろうとJavaScriptからのコールであろうと、コンポーネントがブラウザ内で表示または非表示になります(renderedtrueに設定されている場合)。ただし、visibleは単純にDOMのコンテンツを表示および非表示にするため、renderedを使用した場合と常に同じ視覚的変化を提供するとはかぎりません。


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

JavaScriptなど、サーバーへのラウンドトリップなしに可視性を切り替える必要がある場合にのみvisible属性をfalseに設定します。非表示のコンポーネントも、検証を含むコンポーネント・ライフサイクルを経過します。

クライアントでのみ可視性を切り替える必要がない場合は、かわりにrendered属性をfalseに設定します。コンポーネントをレンダリングしない(表示しないのではなく)場合、コンポーネントはクライアント側表現を持たず、コンポーネント・ライフサイクルを経過しないため、サーバーのパフォーマンスとクライアントのレスポンス時間が向上します。


例4-17に、2つのoutputTextコンポーネントを示します。一度にその一方のみがレンダリングされます。最初のoutputTextコンポーネントは、値がinputTextコンポーネントに入力されなかった場合にレンダリングされます。2番目のoutputTextコンポーネントは、値が入力されたときにレンダリングされます。

例4-17 レンダリングされる/レンダリングされないコンポーネント

<af:panelGroupLayout layout="horizontal">
  <af:inputText label="Input some text" id="input"
                value="#{myBean.inputValue}"/>
  <af:commandButton text="Enter"/>
</af:panelGroupLayout>
<af:panelGroupLayout layout="horizontal">
  <af:outputLabel value="You entered:"/>
  <af:outputText value="No text entered" id="output1"
                 rendered="#{myBean.inputValue==null}"/>
  <af:outputText value="#{myBean.inputValue}"
                 rendered="#{myBean.inputValue !=null}"/>
</af:panelGroupLayout>

コンポーネントがクライアントでレンダリングされる場合、visibleプロパティを使用してコンポーネントをページに表示したり、非表示にできます。

例4-18例4-17と同じ機能を示しますが、この例ではvisible属性を使用して、表示されるコンポーネントを判断します(rendered属性はデフォルトでtrueに設定されるため、明示的に設定する必要はありません)。

例4-18 表示可能/表示不可能なコンポーネント

<af:panelGroupLayout layout="horizontal">
  <af:inputText label="Input some text" id="input"
                value="#{myBean.inputValue}"/>
  <af:commandButton text="Enter"/>
</af:panelGroupLayout>
<af:panelGroupLayout layout="horizontal">
  <af:outputLabel value="You entered:"/>
  <af:outputText value="No text entered" id="output1"
                 visible="#{myBean.inputValue==null}"/>
  <af:outputText value="#{myBean.inputValue}"
                 visible="#{myBean.inputValue !=null}"/>
</af:panelGroupLayout>

ただし、visible属性のかわりにrendered属性を使用することは、サーバー側でのパフォーマンスを向上させるため、JavaScriptで可視性を処理することもできます。

例4-19に、コンポーネントの可視性を処理するJavaScriptのページ・コードを示します。

例4-19 JavaScriptを使用した可視性の切替え

function showText() 
{
    var output1 = AdfUIComponent.findComponent("output1")
    var output2 = AdfUIComponent.findComponent("output2")
    var input = AdfUIComponent.findComponent("input")
    
    if (input.getValue() == "")
    {
      output1.setVisible(true);
    }
    else 
    {
      output2.setVisible(true)
    }
    
 }
   

4.8.1 Javascriptを使用した可視性の設定方法

コンポーネントのvisible属性を切り替えられる条件付きJavaScript関数を作成できます。

始める前に

コンポーネントの表示方法に関する知識が役立つ場合があります。詳細は、4.8項「レンダリングおよび可視性の理解」を参照してください。

可視性を設定する手順:

  1. 可視性を切り替えるJavaScriptを作成します。例4-19に、値がない場合にoutputTextコンポーネントの可視性を有効にし、そうでない場合は別のoutputTextコンポーネントの可視性を有効にするスクリプトを示します。

  2. JavaScript関数に必要なコンポーネントごとに、プロパティ・インスペクタで拡張セクションを開き、ClientComponent属性をtrueに設定します。これによって、JavaScriptで使用されるクライアント・コンポーネントが作成されます。

  3. 可視性を切り替えるコンポーネントのvisible属性をfalseに設定します。

例4-20に、JavaScriptを使用した可視性の切替えに使用されるページ・コード全体を示します。

例4-20 JavaScriptでの可視性の切替え

<f:view>
<af:resource>
  function showText() 
  {
      var output1 = AdfUIComponent.findComponent("output1")
      var output2 = AdfUIComponent.findComponent("output2")
      var input = AdfUIComponent.findComponent("input")
      
      if (input.value == "")
      {
      output1.setVisible(true);
      }
      else 
      {
      output2.setVisible(true)
      }
      
  }
</af:resource>
<af:document>
  <af:form>
    <af:panelGroupLayout layout="horizontal"> 
      <af:inputText label="Input some text" id="input"
                    value="#{myBean.inputValue}" clientComponent="true"
                    immediate="true"/>
      <af:commandButton text="Enter" clientComponent="true">
        <af:clientListener method="showText" type="action"/>
      </af:commandButton>
    </af:panelGroupLayout>
    <af:panelGroupLayout layout="horizontal">
       <af:outputLabel value="You entered:" clientComponent="false"/>
       <af:outputText value="No text entered" id="output1"
                      visible="false" clientComponent="true"/>
       <af:outputText value="#{myBean.inputValue}" id="output2"
                      visible="false" clientComponent="true"/>
    </af:panelGroupLayout>
  </af:form>
 </af:document>
</f:view>

4.8.2 VisibleとisShowing関数について

コンポーネントの親のvisible属性がfalseに設定されている場合、visible属性がtrueに設定されている子コンポーネントにisVisible関数が実行されると、子が表示されていなくてもtrueが返されます。たとえば、outputTextコンポーネントを子として含むpanelGroupLayoutコンポーネントがあり、panelGroupLayoutコンポーネントのvisible属性はfalseに設定され、outputTextコンポーネントのvisible属性はデフォルトのまま(true)とします。クライアントでは、panelGroupLayoutコンポーネントもoutputTextコンポーネントも表示されませんが、isVisible関数がoutputTextコンポーネントに実行されると、trueが返されます。

このため、フレームワークにはisShowing()関数が用意されています。この関数は、コンポーネントのvisible属性がfalseに設定されている場合、またはコンポーネントの親のvisiblefalseに設定されている場合、falseを返します。

4.9 JavaScriptライブラリのパーティション化

JavaScriptを多用したフレームワークに共通する問題は、大規模なJavaScriptコード・ベースをクライアントに送信する最良の方法を決定することです。極端な方法は、すべてのコードを1つのJavaScriptライブラリにバンドリングすることで、この方法ではダウンロード時間が長くなります。逆の極端な方法はJavaScriptコードを多数の小さなJavaScriptライブラリに分割することで、この方法ではラウンドトリップ数が大きくなります。どちらの方法でも初期ページをロードするためのユーザーの待ち時間が不必要に長くなります。

この問題を軽減するために、ADF FacesではJavaScriptコードがパーティションに集約されます。JavaScriptライブラリ・パーティションには、コンポーネントのコードまたは通常一緒に使用される機能、あるいはその両方が含まれています。ADF Facesではデフォルトで、ダウンロード・サイズ合計とラウンドトリップ数合計のバランスをとることを意図したパーティション化が行われます。

ADF Facesのライブラリ・パーティション化方式の利点の1つは、構成可能であることです。アプリケーションによって使用するコンポーネントおよび機能が異なるため、ADF Facesのデフォルトのパーティション化がすべてのアプリケーションに最適であるとはかぎりません。このため、ADF FacesのJavaScriptライブラリのパーティション化はアプリケーションごとにカスタマイズ可能になっています。このパーティション化により、アプリケーション開発者はJavaScriptライブラリのフットプリントをアプリケーションの要件に合せて調整できます。

ADF Facesは、そのコンポーネントのJavaScriptファイルをJavaScript機能にグループ化します。JavaScript機能は、その機能を記述する論理識別子に関連付けられたJavaScriptファイルのコレクションです。たとえば、panelStretchLayoutクライアント・コンポーネントは、次の2つのJavaScriptファイルで構成されます。

これらの2つのファイルは、AdfRichPanelStretchLayout機能にグループ化されます。

JavaScriptの機能は、JavaScriptパーティションにグループ化されます。JavaScriptパーティションでは、ダウンロード・サイズとラウンドトリップ数に影響を与えることを目標に、JavaScript機能をより大きなコレクションにグループ化できます。たとえば、panelStretchLayoutコンポーネントはpanelSplitterコンポーネントで使用されることが多く、この2つのコンポーネントの機能は、子を拡大できる他のADF Facesレイアウト・コンポーネントとともにストレッチ・パーティションにグループ化されます。実行時に、ページがロードされると、フレームワークはページで使用されるコンポーネントを決定し、必要な機能をそこから判断します(機能名は、コンポーネントのコンストラクタ名と同じです)。これらの機能を含むパーティションのみダウンロードされます。

機能およびパーティションは、構成ファイルを使用して定義されます。ADF Facesには、デフォルトの機能およびパーティション構成ファイルが含まれています。独自の実装を作成することでデフォルトのパーティションを上書きできます。カスタムADF Facesコンポーネントを作成する場合、これらのコンポーネントに独自の機能およびパーティション構成ファイルを作成できます。

デフォルトでJavaScriptのパーティション化は有効にされています。アプリケーションでJavaScriptのパーティション化を使用するかどうかは、web.xmlファイルのコンテキスト・パラメータによって決定されます。詳細は、A.2.3.17項「JavaScriptのパーティション化」を参照してください。

4.9.1 JavaScript機能の作成方法

adf-js-features.xmlファイルを作成してから機能にエントリを追加することでJavaScript機能を作成できます。


注意:

カスタムADF Facesコンポーネントを作成する場合に、JavaScript機能を作成できます。すべての既存のADF Facesコンポーネントには、すでにそれらのコンポーネント向けに作成された機能があり、これらは変更できません。


始める前に

JavaScriptのパーティション化の動作に関する知識が役立つ場合があります。詳細は、4.9項「JavaScriptライブラリのパーティション化」を参照してください。

JavaScript機能を作成する手順:

  1. コンポーネント用のMETA-INFディレクトリの作成がまだの場合は、これを作成します。

  2. META-INFディレクトリを右クリックし、ポップアップ・メニューから「新規」を選択します。

  3. 「新規ギャラリ」で、「一般」を展開し、「XML」「XMLドキュメント」を選択して、「OK」をクリックします。


    ヒント:

    「一般」ノードが表示されない場合、ギャラリの上部の「すべてのテクノロジ」タブをクリックします。


  4. ファイル名にadf-js-features.xmlと入力し、META-INFディレクトリに保存します。

  5. ソース・エディタで、生成されたコードを例4-21のコードに置き換えます。

    例4-21 adf-js-features.xmlファイルのXML

    <?xml version="1.0" encoding="utf-8" ?>
    <adf-js-features xmlns="http://xmlns.oracle.com/adf/faces/feature">
     
    </adf-js-features>
    
  6. 次の要素を追加すると、関連するコンポーネント・ファイルおよび依存性とともに機能が移入されます。

    • features: 構成ファイルのルート要素です。

    • feature: features要素の子として作成されます。この要素には1つのfeature-name子要素が含まれている必要があり、feature-class要素およびfeature-dependency要素はいくつでも含めることができます。

    • feature-name: feature要素の子として作成されます。機能の名前を指定します。この値にはクライアント・コンポーネントのコンストラクタ名を使用する必要があります。

    • feature-class: feature要素の子として作成されます。この機能に含める1つのJavaScriptファイルまたはクラスの場所を指定します。複数のfeature-class要素がある場合もあります。

    • feature-dependency: feature要素の子として作成されます。この機能が依存する別の機能の名前を指定します。たとえば、コンポーネントBでコンポーネントAを拡張する場合、コンポーネントAを示す機能はコンポーネントBへの依存性としてリストされている必要があります。依存性を記述することで、フレームワークは2つの機能が同じパーティションになくても、依存するクラスが使用できることを確認できます。

    例4-22に、ポップアップ・コンポーネントを使用し、ポップアップ機能への依存性を持つ架空のカスタム・コンポーネントのfeature要素を示します。

    例4-22 JavaScript機能の構成

    <features xmlns="http://xmlns.oracle.com/adf/faces/feature">
      <feature>
        <feature-name>AcmeMyPane</feature-name>
        <feature-class>
          oracle/adfdemo/acme/js/component/AcmeMyPane.js
        </feature-class>
        <feature-class>
          oracle/adfdemo/acme/js/event/AcmePaneSelectEvent.js
        </feature-class>
        <feature-class>
          oracle/adfdemo/acme/js/component/AcmeMyPanePeer.js
        </feature-class>
    
      <!-- Dependencies -->
     
      <!-- Popup hints -->
      <feature-dependency>AdfRichPopup</feature-dependency>
     
    </feature>
    

4.9.2 JavaScriptパーティションの作成方法

adf-js-partitions.xmlファイルを作成してから機能にエントリを追加することでJavaScriptパーティションを作成できます。


注意:

ADF Facesには、デフォルトのadf-js-partitions.xmlファイルがあります(第F.1.1項「adf-js-partitions.xmlファイル」を参照)。パーティションの構成を変更する場合は、独自の完全なadf-js-partitions.xmlファイルを作成する必要があります。実行時にフレームワークは、そのファイルのWEB-INFディレクトリを検索します。見つからない場合は、デフォルトのパーティション・ファイルがロードされます。


始める前に

JavaScriptのパーティション化の動作に関する知識が役立つ場合があります。詳細は、4.9項「JavaScriptライブラリのパーティション化」を参照してください。

JavaScriptパーティションを作成する手順:

  1. WEB-INFディレクトリを右クリックし、ポップアップ・メニューから「新規」を選択します。

  2. 「新規ギャラリ」で、「一般」を展開し、「XML」「XMLドキュメント」を選択して、「OK」をクリックします。


    ヒント:

    「一般」ノードが表示されない場合、ギャラリの上部の「すべてのテクノロジ」タブをクリックします。


  3. ファイル名にadf-js-partitions.xmlと入力し、WEB-INFディレクトリに保存します。

  4. ソース・エディタで、生成されたコードを例4-23のコードに置き換えます。

    例4-23 adf-js-partitions.xmlファイルのXML

    <?xml version="1.0" encoding="utf-8" ?>
    <partitions xmlns="http://xmlns.oracle.com/adf/faces/partition">
     
    </partitions>
    
  5. 次の要素を追加すると、関連する機能とともにパーティションが移入されます。

    • partitions: 構成ファイルのルート要素です。

    • partition: partitions要素の子として作成されます。この要素には1つのpartition-name子要素および1つ以上のfeature要素が含まれている必要があります。

    • partition-name: partition要素の子として作成されます。パーティションの名前を指定します。この値は、このパーティションのJavaScriptライブラリに一意のURLを作成するために使用されます。

    • feature: partition要素の子として作成されます。このパーティションに含める機能を指定します。複数のfeature要素がある場合もあります。


    ヒント:

    adf-js-features.xmlファイルで構成され、パーティションに表示されない機能は、独自のパーティションに存在するものとして扱われます。


    例4-24に、AdfRichTree機能およびAdfRichTreeTable機能を含むtreeパーティションのpartition要素を示します。

    例4-24 JavaScriptパーティションの構成

    <partition>
      <partition-name>tree</partition-name>
      <feature>AdfUITree</feature>
      <feature>AdfUITreeTable</feature>
      <feature>AdfRichTree</feature>
      <feature>AdfRichTreeTable</feature>
    </partition>
    

4.9.3 実行時の処理: JavaScriptのパーティション化

ADF Facesによって、アプリケーションの初期化時にライブラリのパーティション構成ファイルがロードされます。まず、ADF Facesによって、META-INFディレクトリのすべてのadf-js-features.xmlファイルが検索され、見つかったすべてのファイルがロードされます(ADF Facesのデフォルトの機能構成ファイルを含む)。

パーティション構成ファイルについては、ADF FacesはWEB-INFディレクトリでadf-js-partitions.xmlという名前の1つのファイルを検索します。このファイルが見つからない場合は、ADF Facesのデフォルトのパーティション構成が使用されます。

レンダリング・トラバース中、ADF Facesはページによって必要とされるJavaScript機能に関する情報を収集します。トラバース終了時に(レンダリングされた)ページ・コンテンツによって必要とされるJavaScript機能の包括的なセットが認識されます。必要とされるJavaScript機能のセットが認識されると、ADF Facesはパーティション構成ファイルを使用して、この機能セットを必要とされるパーティションのセットにマップします。必要とされるパーティションのセットを使用して、これらのパーティションへのHTML <script>参照は、HTMLドキュメントの末尾直前でレンダリングされます。