別のブラウザで表示すると、JavaScriptによってこのドキュメントの表示形式が変わる場合があります。ただしドキュメントの内容に影響はありません。

UIX開発者ガイド Go to Table of Contents
目次
Go to previous page
前へ
Go to next page
次へ

13. 部分ページ・レンダリング

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

uiXMLページへの対話性の追加

通常、Webページでは、フォーム・データの入力や送信、別のページへのナビゲートなどの様々な処理がサポートされています。この他に、多くのWebページでは、ユーザーが実際に別のページへナビゲートせずにWebページ自体のコンテンツを変更できるという処理もサポートされています。このような処理の例を次に示します。

これらの処理はすべて、同じページがわずかに異なる状態で再レンダリングされるという点で似ています。このような変更は、ユーザーがコンテキストを失って現在の作業から離れてしまうことがないように、できるかぎりシームレスに実装するのが理想的です。

開発者は、このような動作をWebページに追加する場合にしばしば困難な決定に直面します。これらの処理はすべて、ユーザー操作に応答してページ全体をリフレッシュするという非常に単純なソリューションを使用して実装できます。簡単ですが、このソリューションが常に望ましいわけではありません。全ページ・リフレッシュは時間がかかる場合があるため、アプリケーションの応答が遅いという印象をユーザーに与えてしまいます。別のオプションとして、JavaScript(またはその他のクライアント側スクリプト・テクノロジ)を使用してこのような処理を実装する方法があります。この場合、応答時間は短縮されますが、複雑性が増し、移植性が低下します。JavaScriptは、イメージの更新のような単純な処理には適しています。しかし、表内のデータのスクロールや、カスタムJavaScriptコードの記述といった複雑な処理の場合、非常に困難な作業になる可能性があります。

UIXでは、全ページ・リフレッシュとカスタムJavaScriptソリューションの欠点のいくつかを回避する、部分ページ・レンダリングというソリューションが用意されています。UIXの部分ページ・レンダリング機能では、ページの一部分のみを再レンダリングできます。部分ページ・レンダリングでは、全ページ・レンダリング・ソリューションと同様に、中間層のアプリケーションにリクエストを送り返して新しいコンテンツをフェッチします。ただし、部分ページ・レンダリングを使用してページが更新される場合は、変更されたコンテンツのみがブラウザに返されます。UIXでは、新しいコンテンツがWebページに自動的にマージされます。最終的に、カスタムJavaScriptコードを記述することも、全ページ・リフレッシュでよくあるようにコンテキストを失うこともなくページは更新されます。

部分ページ・レンダリングの仕組み

部分ページ・レンダリングのプロセスは、部分ページ・イベント、部分ページ・レンダリング渡しおよび部分ページ置換の3つの主要な領域に分けられます。

部分ページ・イベントは、ブラウザが新しいコンテンツを要求するためにアプリケーションに送信するリクエストです。部分ページ・イベントは、全ページ・イベントとよく似ています。たとえば、ユーザーがtable Bean内の新規レコードにナビゲートすると、部分ページ・イベントの場合でも全ページ・イベントの場合でも、valueイベント・パラメータを持つgotoイベントがアプリケーションに送信されます。部分ページ・イベントと全ページ・イベントの間には2つの重要な違いがあります。1つ目は、部分ページ・イベントでは、全ページ・イベントにはない部分ページ・レンダリング固有のイベント・パラメータが指定されることです。たとえば、部分ページ・イベントには、部分ターゲットのセットや、再レンダリングの必要なノードを識別するイベント・パラメータが含まれる場合があります。部分ページ・イベントと全ページ・イベントの2つ目の違いは、イベントが送信される方法です。

全ページ・イベントの場合と異なり、部分ページ・イベントの送信は、ブラウザによって現在のページが強制的に再ロードされないような方法で行う必要があります。この機能を実装するため、UIXの部分ページ・レンダリングでは、ブラウザと中間層で実行されているWebアプリケーションとの通信チャネルとして非表示インライン・フレーム(iframe)を使用します。部分ページ・イベントの送信は、非表示iframe内のナビゲーションを強制実行して行われます。これにより、リクエストが中間層のアプリケーションに送信されます。iframeは非表示なので、部分ページ・イベントを送信してページの一部をレンダリングするプロセスは、現在のページのコンテンツを破棄することなく内部で行われます。

アプリケーションは、部分ページ・イベントを受け取ると、レンダリングする部分ターゲット・セットを判別し、部分ページ・レンダリング渡しを実行します。部分ページ・レンダリング渡しは、全ページ・レンダリング渡しと似ています。どちらの場合も、UINodeツリー内の各ノード上でrender()をコールすることによってUINodeツリーが横断されます。ただし、部分ページ・レンダリングの場合は、部分ターゲットによって生成されたコンテンツのみが実際にブラウザに送り返されます。他のコンテンツはすべて破棄されます。したがって、部分ページ・レンダリング渡しと全ページ・レンダリング渡しのスコープは、レンダリングされるUINodeの数においては似ていますが、部分ページ・レスポンスの場合は変更されたコンテンツのみがブラウザに送り返されるため、一般に全ページの場合よりもはるかに小さくなります。

部分ページ・レンダリングのプロセスの最後は、部分ページ置換です。ブラウザが部分ページ・レスポンスを受け取ると、各部分ターゲット・ノードの新規コンテンツが非表示iframeからメイン・ブラウザ・ウィンドウにコピーされて、ターゲット・ノードごとに既存のコンテンツが置換されます。したがって、たとえば表のナビゲーションでは、ページ全体ではなく表自体のコンテンツだけが置換されます。ブラウザは変更に応答してリフローを行い、ページ全体を再レンダリングすることなく、ユーザーに新しいコンテンツを表示します。

まとめとして、部分ページ・レンダリングで行われる一連のステップを次に示します。

  1. 初期ページがレンダリングされます。
  2. ユーザーが、部分ページ・レンダリングを起動するなんらかの処理(リンクやボタンのクリックなど)を実行します。
  3. UIXで提供されたJavaScriptイベント・ハンドラにより、非表示iframe内のナビゲーションが強制実行されます。
  4. 部分ページ・イベントがアプリケーションに送信されます。
  5. アプリケーションにより、リクエストが部分ページ・イベントであるかどうか、および再レンダリングの必要な部分ターゲット・ノードが判別されます。
  6. 部分ページ・レンダリング渡しが実行されます。
  7. 部分ターゲット・ノードのコンテンツが、ブラウザのiframeに送り返されます。
  8. 部分ページ置換が実行され、この時点で新しいコンテンツがiframeからメイン・ブラウザ・ウィンドウ内にコピーされます。
  9. ブラウザがリフローを行い、エンド・ユーザーに新しいコンテンツが表示されます。

部分ページ・レンダリング・プロセスではカスタムJavaScriptコードは必要ないので注意してください。

サポートされるプラットフォーム

部分ページ・レンダリングの実装には、ブラウザのDOM APIを介して任意のコンテンツを変更できることが必要です。現在、部分ページ・レンダリングがサポートされているのは次のブラウザのみです。

その他のプラットフォームの場合、UIXでは自動的に全ページ・レンダリングが実行されます。将来的に、部分ページ・レンダリングはIE 5.0を含む広範囲のブラウザでサポートされる予定です。ただし、Netscape 4.xではDOMサポートに制限があるため、部分ページ・レンダリングがNetscape 4.xでサポートされる予定はありません。

また、部分ページ・レンダリングで使用されるクライアント側DOM変更によって、スクリーン・リーダーなどの補助テクノロジに関する問題が発生することがあります。このため、部分ページ・レンダリングが使用されるのは、UIXアクセシビリティ・モードが明示的にAccessibilityMode.INACCESSIBLE_MODEに設定されている場合にかぎられています。スクリーン・リーダーでuiXMLページを読むユーザーの場合も、全ページ・リフレッシュではコンテキストを失うことが多いため、部分ページ・レンダリングを使用すると便利です。部分ページ・レンダリングを補助テクノロジと互換性のある方法で使用できるかどうかを判断するには、さらに研究を行う必要があります。当面は、アクセス不可モードを除くすべてのアクセシビリティ・モードに対して全ページ・レンダリングが使用されます。アプリケーションで特定のユーザーのアクセシビリティ・モードを指定する方法の詳細は、「アクセシビリティ・モードの設定」を参照してください。

部分ページ・レンダリングの使用可能化

部分レンダリング・モードの設定

部分ページ・レンダリングを利用するために、tablehideShowhideShowHeaderおよびsubTabLayoutの4つのUIXコンポーネントが拡張されました。これらのコンポーネントはそれぞれ、partialRenderModeおよびpartialTargetsという2つの新しい属性をサポートしています。partialRenderMode属性は、特定のコンポーネントについて部分ページ・レンダリングを使用可能にするかどうかを制御します。この属性は、noneselfmultipleの3つのうちいずれかの値に設定できます。デフォルト値はnoneで、部分ページ・レンダリングを使用不可にすることを指定します。partialRenderMode属性をselfに設定すると、部分ページ・レンダリングを使用してコンポーネント自体を更新することを指定します。これが最も一般的な設定です。multipleモードはpartialTargets属性とともに使用され、各部分ページ・イベントに応答して複数の部分ターゲットを再レンダリングすることを指定します。

したがって、たとえば部分ページ・レンダリングを使用して表自体をリフレッシュするように指定するには、次のようにpartialRenderModeを設定します。


  <table id="table-id" partialRenderMode="self">

表が更新されるたびに複数の依存フィールドを更新するように指定するには、partialTargets属性とともにmultipleモードを使用します。


  <table id="table-id"
         partialRenderMode="multiple"
         partialTargets="dependent-id1 dependent-id2 dependent-id3">

複数の部分ターゲットを指定するとき、部分ページ・イベントを起動するコンポーネントのIDは、部分ターゲットのリストに暗黙的に含まれるので注意してください。このため、前述の例では、表のID(table-id)は自動的に部分ターゲットとみなされるので、このIDをpartialTargets値に含めないでください。

tableコンポーネントの場合、partialRenderModeselfまたはmultipleに設定すると、次の処理について部分ページ・レンダリングが有効になります。

hideShowおよびhideShowHeaderコンポーネントの場合、部分ページ・レンダリングを使用して非表示処理と表示処理の両方が最適化されます。subTabLayoutコンポーネントでは、タブの切替え時に、部分ページ・レンダリングを使用してそのコンテンツを更新します。

partialRenderMode属性の設定の他に、部分ページ・レンダリングを使用可能にするために必要な条件がいくつかあります。これらの条件については、以降の各セクションで説明します。

Body Beanの使用

部分ページ・レンダリングを使用可能にするためには、UINode階層内にbody Beanが存在している必要があります。部分ページ・レンダリングを利用するUIXページは、次のような構造を持つ必要があります。


<page  xmlns="http://xmlns.oracle.com/uix/controller">
<content>
  <document xmlns="http://xmlns.oracle.com/uix/ui">
  <contents>

    <!-- The body bean is required -->
    <body>
    <contents>

      <!-- Components which fire partial page events can go here -->

    </contents>
    </body>

  </contents>
  </document>
</content>
</page>

bodyが存在しないと、部分ページ・レンダリングは失敗します。ほとんどのuiXMLページでは、bodyは自動的に追加されます。documentを使用するページのみ、明示的にbody要素を追加する必要があります。ただし、JavaおよびUIX JSPの開発者は、BodyBean<uix:body>をそれぞれ明示的に使用する必要があります。

IDの定義

部分ページ・レンダリングを介して再レンダリングする可能性のあるノードには、ID属性の値を指定する必要があります。たとえば、hideShow Beanの部分ページ・レンダリングを使用可能にする場合、次のコードでは不十分です。


  <hideShow partialRenderMode="self">

次のようにID属性も指定する必要があります。


  <hideShow id="some-unique-id" partialRenderMode="self">

このIDは、部分ページ・レンダリング・プロセスの間、いくつかの重要な役割を果たします。まず、部分ページ・イベントでは、再レンダリングの対象となる部分ターゲットのセットがIDで識別されます。部分ページ・レンダリングの横断中は、各部分ターゲット・ノードのIDを調べることにより、これらのノードがUINodeツリー内に配置されます。最後に、部分ページ・コンテンツがブラウザに送り返されるとき、IDを使用して、部分ページ置換のためにブラウザのDOMツリー内にターゲット・ノードが配置されます。

アクセシビリティ・モードの設定

部分ページ・レンダリングは、エンド・ユーザーがアクセス可能コンテンツを必要としないことが既知の場合にのみ使用可能になります。この情報はAccessibilityModeによって伝達されます。これはConfiguration.ACCESSIBILITY_MODEプロパティを介して指定されます。このプロパティは、1つのメソッド・コールで設定できます。


  ConfigurationImpl configImpl = ...
  configImpl.putProperty(Configuration.ACCESSIBILITY_MODE,
                         AccessibilityMode.INACCESSIBLE_MODE);

ただし、UIX Controllerクライアントは、uix-config.xml構成ファイルを介して宣言的にこの情報を指定できます。次のように新しいconfiguration要素を追加するだけです。


  <configuration name="noADA">
    <accessibility-mode>inacessible</accessibility-mode>
  </configuration>

次に、UIXPageBroker.getConfigurationName()のオーバーライドによって、各リクエスト単位で使用する構成を指定できます。


  protected String getConfigurationName(
    BajaContext context,
    Page page)
  {
    if (_useInaccessibleConfiguration(context))
      return "noADA";
    return super.getConfigurationName(context, page);
  }

この例では、_useInaccessibleConfiguration()メソッドが、特定のリクエストについてアクセス不可コンテンツをレンダリングするかどうかを判断する必要があります。このようなメソッドの実装は、アプリケーション固有のものになります。たとえば、ユーザーの作業環境用の永続格納域を持つアプリケーションでは、ユーザーが指定したアクセシビリティ・モードをリポジトリから取得できます。リポジトリにユーザー作業環境が格納されていないアプリケーションでは、CookieまたはHttpSession値を使用して、ユーザーがアクセス可能コンテンツを必要としているかどうかを調べます。

Configuration APIの取扱いの詳細は、「構成」のトピックを参照してください。

コンテンツを生成するスクリプトの指定

部分ページ置換の際、新しく生成されたコンテンツは、非表示iframeからiframeの親ウィンドウに表示のためコピーされます。新しいコンテンツにスクリプトが含まれる場合、それらのスクリプトも同様に親ウィンドウ内で明示的に実行されます。この処理が必要なのは、スクリプトで定義されている関数または変数を親ウィンドウから利用可能にするためです。ただし、スクリプトそのものがコンテンツを生成するような場合、親ウィンドウ内でのスクリプトの実行によって問題が発生することがあります。document.write()またはdocument.writeln()をコールすると親ウィンドウのコンテンツが完全に置換されるため、これらをコールするスクリプトを親ウィンドウ内で実行しないでください。

UIXでは、ある特定のスクリプトがコンテンツを生成する(つまり、document.write()またはdocument.writeln()をコールする)かどうかを自動的に判別できないため、クライアントがこのようなスクリプトを明示的に指定する必要があります。これを指定するには、script BeanのgeneratesContentブール属性を使用できます。generatesContent属性は、デフォルトで、スクリプトがコンテンツを生成しないことを示すfalseに設定されます。部分ページ・レンダリングを使用するクライアントは、document.write()またはdocument.writeln()をコールするスクリプトがあれば、例として次のように属性をtrueに設定してください。


  <!-- Explicitly specify generatesContent="true", since
          this script calls document.write() -->
  <script generatesContent="true">
    document.write("Hello, World!");
  </script>

コンテンツを生成するスクリプトをこの方法で指定しない場合、部分ページ・リクエスト置換により、スクリプトによって生成されたコンテンツのみでページ全体が置換されることがあります。

部分ページ・イベントへの応答

部分ページ・レンダリングが使用可能になると、コンポーネントは非表示iframeを使用して部分ページ・イベントをアプリケーションに送信します。UIX Controllerは、部分ページ・イベントで指定された部分ターゲット・ノードをレンダリングすることにより、これらのイベントを自動的に処理します。このため、UIX Controllerのクライアントは、部分ページ・イベントを取り扱う際に何も変更する必要はありません。既存のUIX Controllerイベント・ハンドラは、部分ページ・イベントと全ページ・イベントの両方にわたって再利用できます。ただし、カスタム・コントローラを使用するアプリケーションについては、部分ページ・イベントの検出、レンダリングする部分ターゲットのセットの判別、および要求されたコンテンツのレンダリングを行うようにその機能を拡張する必要があります。

PartialPageContextの作成

部分ページ・レンダリングを利用するアプリケーションは、部分ページ・イベントと全ページ・イベントを区別できる必要があります。その区別は、アプリケーションのコントローラが行います。コントローラは、リクエストのたびに(HttpServletRequestオブジェクトまたはoracle.cabo.share.data.ServletRequestParametersオブジェクトを指定して)UIX PartialPageEventUtils.createPartialPageContext()メソッドをコールすることによって、部分ページ・イベントと全ページ・イベントを区別します。このメソッドは、到着したリクエストを調べて、そのリクエストが部分ページ・イベントかどうかを判別します。リクエストが部分ページ・イベントであれば、PartialPageContextオブジェクトが作成され、返されます。PartialPageContextオブジェクトは、部分ページ・レンダリングに関連する状態をカプセル化します。たとえば、PartialPageContextは、レンダリングする部分ターゲットのセットを定義します。

全ページ・イベントの場合、createPartialPageContext()はNULLを返します。このように、コントローラは、このメソッドにより返された値をチェックするだけで、全ページ・イベントと部分ページ・イベントを区別できます。全ページ・イベントの場合、コントローラは通常の処理を続行できます。部分ページ・イベントの場合、コントローラは、必要なターゲット部分のみがレンダリングされるように追加の処理を実行する必要があります。

部分ターゲットのセットの変更

それぞれの部分ページ・イベントで、再レンダリングする必要のある部分ターゲットを1つ以上指定できます。createPartialPageContext()は、要求されたターゲットのセットを使用してPartialPageContextを自動的に初期化します。ただし、特定のイベントを処理する場合に、レンダリングする部分ターゲットのセットの変更が必要なアプリケーションもあります。たとえば、表とグラフのイメージの両方が含まれるページで、表が更新されるたびに表とグラフの両方を再レンダリングする必要がある場合などです。この場合、部分ページ・イベントで表の再レンダリングしか指定されていなくても、アプリケーションが介入して、グラフも同様にレンダリングされるように部分ターゲットのセットを明示的に変更することができます。

PartialPageContextには、部分ターゲットの追加と削除を行うためのaddPartialTarget()およびremovePartialTarget()というメソッドがあります。これらのメソッドをレンダリングの前にコールして、レンダリングする部分ターゲットのセットを変更できます。UIX Controllerクライアントの場合、これらのメソッドをコールする場所として最もわかりやすいのは、UIX Controllerイベント・ハンドラです。クライアントは、PartialPageEventUtils.getPartialPageContext()メソッドをコールすることにより、UIXイベント・ハンドラからPartialPageContextを取得できます。

部分ページ・レンダリングの実行

部分ターゲットのセットが判別され、アプリケーション・ロジックが実行されたら、必要なコンテンツをレンダリングして部分ページ・イベントに応答します。部分ページ・レンダリングの実行は、全ページ・レンダリングの場合と非常に似ています。唯一の違いは、レンダリングに先立ってRenderingContextPartialPageContextを設定する必要があることです。これは、PartialPageUtils.setPartialPageContext()メソッドを使用して設定できます。UIX Controllerは部分ページ・イベントを処理するときにこのメソッドを自動的にコールするため、UIX Controllerクライアントが特別な操作を行う必要はありません。

また、カスタム・コントローラを使用するアプリケーションの場合は、RenderingContextPartialPageContextを設定し、なおかつレンダリングを実行するPartialPageUtils.renderPartialPage()という便利なメソッドをコールすることもできます。

つまり次のようになります。


  node.render(renderingContext);

このメソッドではなく、アプリケーションは次のメソッドをコールします。


  PartialPageUtils.renderPartialPage(renderingContext,
                                     node,
                                     partialPageContext);

部分ページの場合も全ページの場合も、UINodeツリーの同じルート・ノードをレンダリングする必要があるので注意してください。つまり、部分ページ・レンダリング渡しで部分ターゲット・ノードのセットのコンテンツしか生成されない場合でも、UINodeツリー全体を横断することが必要になります。また、NULLのPartialPageContextを使用してrenderPartialPage()をコールする方法も便利です。この場合、通常の全ページ・レンダリングが実行されます。

エラーの処理

部分ページ・イベントの処理でエラーが発生した場合、要求された部分ターゲット・ノードをレンダリングするだけでは不十分である可能性があります。アプリケーションではエラーに関する追加情報をエンド・ユーザーに提供する必要があります。エラーがいつ検出されたかによって、2つのうちどちらかのオプションを使用して追加情報を提供します。エラーがレンダリングの開始前に発生した場合、アプリケーションは新しいエラー・ページを表示できます。レンダリングの途中で発生したエラーについては、エラー・ページへナビゲートすることはできません。このような場合は、明示的に要求されていないノードを部分ページ・イベントに追加するために部分ターゲットのセットを拡張すると、追加情報の提供が可能になります。

部分ページ・イベントに応答してエラー・ページをレンダリングするには、エラー・ページのUINodeツリー上のUINode.render()をコールするだけでは不十分です。部分ページ・イベントは非表示インライン・フレームを介して送信されることに注意してください。ブラウザに送り返されたコンテンツは、まずインライン・フレーム内に表示されます。エンド・ユーザー向けに表示するには、親ドキュメント・ウィンドウにコンテンツを明示的にコピーする必要があります。このため、新しいUINodeツリー上のUINode.render()をコールした場合、必要なエラー・ページ・コンテンツは生成されても表示されません。アプリケーションは、PartialPageUtils.renderFullPage()メソッドをコールして新しい全ページのコンテンツをレンダリングする必要があります。renderFullPage()メソッドを使用すると、確実に、UINodeツリーの全コンテンツがブラウザに送り返され、表示のために非表示iframeから親ウィンドウ内にコピーされます。

UIX Controllerをベースにしたアプリケーションでは、部分ページ・イベントを取り扱うEventHandlerから別のPageを返すだけで、これと同じ結果を達成できます。この場合、UIX ControllerがアプリケーションにかわってrenderFullPage()を自動的に呼び出します。

レンダリングが一度開始されると、エラー情報を表示する新しいページにナビゲートすることはできません。ただし、部分ページ・レンダリング渡しの間にエラーが検出された場合は、新しい部分ターゲットを追加することによって、部分ページ・レスポンスにエラー情報を組み込むことができます。たとえば、部分ターゲットを移入するための問合せ中にエラーが発生した場合、要求された部分ターゲットのセットにMessageBox BeanのIDが明示的に含まれていなかったとしても、アプリケーションはMessageBox Bean内にエラー・メッセージを表示します。PartialPageContext.addPartialTarget()メソッドをコールして、ID属性値で指定された新しいUINodeを、部分ページ・レンダリング渡しでレンダリングされるノードのセットに追加することを指定できます。

新しく追加された部分ターゲットを適切にレンダリングして表示するには、必要な条件がいくつかあります。最もわかりやすい条件は、部分ターゲットの候補であるUINode上にID属性が指定されていることです。また、新しい部分ターゲットのレンダリングはaddPartialTarget()のコール後に行われる必要があります。これは、一般的に、エラー情報の表示に使用されるUINodeを、そのUINodeツリー内の対象となる可能性のある部分ターゲットより下に配置するということを意味しています。最後の条件は、新しい部分ターゲットが、現在のページの以前の全ページ・レンダリングによってなんらかの形態でレンダリングされていることです。少なくとも、クライアント側のDOMツリーに、エラー・ノードのIDを持つノードが存在している必要があります。このノードでコンテンツが表示されない場合でも同じです。必要なIDを持つノードがクライアント側のDOMツリー内に見つからない場合、エラー・メッセージの内容はドキュメントにコピーされません。

将来的な方向

これまでに、tablehideShowhideShowHeaderおよびsubTabLayoutコンポーネントについて部分ページ・レンダリングを使用可能化する方法について説明しました。では、このトピックで前述されている他の使用方法についてはどうでしょうか。部分ページ・レンダリングのアーキテクチャは、リンクやボタンのクリック、選択ボックスからの項目の選択といった任意のユーザー操作に応答して部分ページ・イベントを起動する機能をサポートするように設計されたものです。しかし、現時点では、UIXはこのようなイベントを起動するためのパブリックAPIを公開していません。UIXの将来のバージョンでは、このようなAPIが提供される予定です。これにより、ユーザー操作を最適化するために部分ページ・レンダリングを使用できる範囲が大幅に拡大するはずです。当面、UIXクライアントはtableおよびhideShowコンポーネントについて部分ページ・レンダリングを利用することをお薦めします。