この章では、Oracle FormsのEnterQuery/ExecuteQuery検索のように機能する検索フォームや、Webサイトで使用されている検索フォームのようなフォームなど、各種の検索ページを作成する方法について説明します。
この章の内容は次のとおりです。
開発者は、オブジェクトの既知の属性に基づいてユーザーが基準を入力できる検索フォームを作成できます。入力された基準は問合せに組み込まれ、Query By Example(QBE)検索が実行されます。入力された基準に一致する属性を持つすべてのレコードが戻され、これらのレコードは、別のページまたは同じページの表に表示できます。QBE検索フォームを作成するには、コレクションをデータ・コントロール・パレットからADF検索フォームとしてドロップします。この方法では、入力テキスト・コンポーネントに関連付けられているバリデータまたはコンバータがないため、エンド・ユーザーは数値フィールドに> 1500のような検索基準を入力できます。この検索基準がない場合、検証または変換が失敗する可能性があります(変換および検証の詳細は、第20章「検証と変換の使用」を参照)。
イテレータ・バインディングには、コレクションの反復処理の他にQBE機能もあり、QBE基準行のコレクションの反復処理も実行できます。これらの行は、ユーザー入力の基準によって作成されます。各基準行の属性の構造は、属性値がすべてStringデータ型として処理されること以外は、関連付けられているデータ・コレクション内の行と同じです。このデータ型では、ユーザーは、比較演算子やワイルドカード文字を含む問合せ基準をフォーム・フィールドに入力できます。
イテレータ・バインディングでこの機能を有効にするには、バインディングをFindモードに設定する必要があります。イテレータ・バインディングがFindモードで機能するように設定されている場合、標準コレクション・データではなく、これらの基準行の反復処理を行います。次に、Execute操作を使用してコレクションに対する問合せが実行されます。Execute操作は、ユーザーの問合せ基準を適用するだけでなく、イテレータ・バインディングのFindモードの無効化も行うため、フォームでは、基準ではなくコレクションから戻されたデータを表示できます。検索モードの詳細は、10.5.3項「検索モードによるQuery By Example(QBE)の実装方法」を参照してください。
デフォルトでは、ADF検索フォームには、Find操作およびExecute操作にバインドされているコマンド・ボタンがあります。これらのボタンは、レコードの検索と戻された現在レコードの表示の両方にフォームを使用する場合に便利です。ユーザーは、「検索」ボタンをクリックしてイテレータをFindモードにすることで、入力テキスト・フィールドに基準を入力可能にします。ユーザーが次に「実行」ボタンをクリックすると、基準を使用して問合せが作成され、検索が実行され、フォームで結果の表示が可能になります。このタイプの検索フォームは、Oracle FormsのEnterQuery/ExecuteQuery検索のように機能します。このような検索フォームの作成方法の詳細は、18.2項「EnterQuery/ExecuteQuery検索フォームの作成」を参照してください。
また、イテレータを常にFindモードに強制できるため、「検索」ボタンが不要になり、ユーザーは自分の検索基準と結果の両方を確認できます。ユーザーには、Execute操作にバインドされているボタンのみが表示されます。ユーザーがこのボタンをクリックすると、イテレータはFindモードではなくなります。Findモードに戻るようにプログラムで設定して、ユーザーによる基準入力を常に可能にするには、イテレータがFindモードでない場合(Execute操作の起動後など)に必ず実行されるアクション・バインディングをページ定義ファイルに挿入します。ただし、この場合、検索フォームのイテレータは常にFindモードになるため、結果を別のフォームまたは表で表示する必要があります。一般的なWebページの検索は、このタイプの検索です。詳細は、18.3項「Webタイプ検索フォームの作成」を参照してください。
このタイプのWeb検索では、検索フォームと結果表を別のページ、または同じページに配置できます。ただし、検索と結果が同じページにある場合は、検索フォーム用の常にFindモードのイテレータと、結果用の別のイテレータが必要になります。詳細は、18.3.4項「同じページでの検索および結果の作成の考慮事項」を参照してください。SRSearchページでは、このQBE検索機能を使用して、図18-1に示すように、検索フォームと結果表を同じページに表示します。
また、検索専用に作成されたビュー・オブジェクトの名前付きバインド変数を使用すると、クイック検索フォームも作成できます。たとえば、SRDemoアプリケーションのSRStaffSearchページでは、StaffListByEmailNameRoleビュー・オブジェクトを使用して検索フォームを作成しています。コレクションをADF検索フォームとしてドロップするのではなく、ExecuteWithParams操作をパラメータ・フォームとしてドロップします。この検索が実行されると、検索が実行されるたびにQBE問合せを動的に作成するのではなく、パラメータ・フォームでは、ビュー・オブジェクトの設計時SQL文を使用して問合せを実行します。SQL文のテキストは変更されないため、データベースではこれを効率的に再使用でき、パフォーマンスが向上します。
対照的に、QBE問合せでは、検索基準に応じたWHERE句条件が動的に生成されます。このため、基準を様々に組み合せて検索を続行する場合は、そのビュー・オブジェクトのSQL文のテキストは、実行ごとに変わります。たとえば、3回の検索により、そのSQL文に対して次の3つの異なるWHERE句が生成される場合があります。
AND (SVR_ID = 101)
AND (SVR_ID = 102
AND (PROBLEM_DESCRIPTION LIKE '%FOO%' AND ... )
SQL文のテキストはQBE検索では変わる可能性があるため、ビュー・オブジェクトによって新しいプリコンパイルされたSQL文が毎回作成され、問合せをデータベース側で再解析する必要があります。このため、検索を同じ文で繰り返し実行する予定の場合は、パラメータ検索フォームを使用するとパフォーマンスを向上できます。
ただし、パラメータ付き検索を作成するには、その検索用のビュー・オブジェクトを作成する必要があります。生成済のカスタム行インタフェースを使用して行をプログラムで操作する必要があり、検索のビュー・オブジェクトで既存のビュー・オブジェクトと完全に同じ構造および動作が必要な状況では、この方法は実用的ではない場合があります。たとえば、ServiceRequestsとServiceRequestSearchという2つのビュー・オブジェクトを作成し、この両方の構造が同じで、属性への型保証アクセスを取得するためクライアント・コードを編集する必要がある場合は、ServiceRequestsRowとSearchRequestsSearchRowの両方のクライアント・インタフェースを編集する必要があります。このため、問合せで既存のビュー・オブジェクトと同じビュー・オブジェクトが必要であり、パラメータ付き検索ではパフォーマンスの向上があまり期待できない場合は、QBEタイプの検索を使用してください。
SRDemoアプリケーションのSRSearchページでは、QBE問合せを使用して、ID、ステータス、問題の説明および製品名に基づいて、サービス・リクエストをServiceRequestsビュー・オブジェクトから検索します。この検索ページでは、SearchServiceRequestsという名前のServiceRequestsビュー・オブジェクトのインスタンスを使用しています。これはアプリケーション・モジュールによって検索ページ用にインスタンス化されています。ServiceRequestsビュー・オブジェクトの別のインスタンスであるServiceRequestsByStatusインスタンスは、SRListページでサービス・リクエストをステータス別にフィルタ処理したリストを表示するために使用されています。
ビュー・オブジェクト、ビュー・オブジェクト・インスタンスおよび名前付きバインド変数の詳細は、第5章「ビュー・オブジェクトを使用したデータの問合せ」を参照してください。
開発者は、ユーザーが検索基準を入力し、検索を実行してから、検索の結果を同じフォームで確認できるフォームを作成できます。ただし、検索用と結果用のフォームを1つずつ作成し、その2つが1つのフォームとして機能するようにする必要があります。
このためには、検索基準の入力に使用されるフォームを、イテレータがFindモードの場合にのみ表示されるように設定します。結果を表示するもう1つのフォームは、イテレータがFindモード以外の場合にのみ表示されるように設定します。各フォームの表示は、フォームのRendered属性にEL式を使用して制御します。この方法では、フォームがFindモードの場合、ユーザーは> 1500などの基準を数値フィールドに入力できますが、データの編集中は、同じ入力によってエラーが発生します。
前述のとおり、実際には、問合せ用と結果用の2つのフォームを作成します。EL式は、正しいフォームをいつ表示するかを判断するために使用されます。
データ・コントロール・パレットからコレクションをドラッグし、ポップアップ・メニューから「フォーム」→「ADF検索フォーム」を選択します。
たとえば、問合せをすべてのサービス・リクエストに対して実行するには、ServiceRequestsコレクションをドラッグします。
同じコレクションをドラッグしますが、今回は、それをADFフォームとしてドロップします。「フォーム・フィールドの編集」ダイアログで「ナビゲーション・コントロールを含める」を選択します。これは、結果を表示するフォームになります。ナビゲーション・コントロールによって、ユーザーは、問合せから戻されるオブジェクト全体を移動できるようになります。
構造ウィンドウで、最初のフォームのpanelFormコンポーネントを選択します。
プロパティ・インスペクタで、レンダリング・フィールドに次の式を入力します(<iterator>はイテレータの名前と置き換えてください)。
#{bindings.<iterator>.findMode == true}
この入力によって、イテレータがFindモードの場合は、常にこのフォームがレンダリングされるようになります。
名前が不明な場合は、図18-2に示すように、「データにバインド」ツールを使用して「式ビルダー」を開くことができます。
「式ビルダー」の「変数」ツリーで、適切なイテレータの下のfindModeプロパティを選択し、右矢印をクリックしてプロパティを「式」ペインに追加します。次に論理演算子を追加し、式がtrueをチェックするように設定します。図18-3は、ServiceRequestsIteratorイテレータに作成される式を示しています。
構造ウィンドウで、2番目のフォームのパネル・フォームを選択します。Renderedプロパティを次のように設定します。
#{bindings.<iterator_name>.findMode == false}
この式により、イテレータがFindモード以外の場合は、常にこのフォームが表示されるようになります。
データ・コントロール・パレットから、コレクションに関連付けられているFind操作をドラッグし、2番目のフォームのナビゲーション・ボタンの横に「ADFコマンド・ボタン」としてドロップします。このボタンを使用すると、ユーザーはFindモードに戻すことができます。これによって最初のフォームが表示され、ユーザーは別の問合せを実行できます。
「検索」ボタンおよび「実行」ボタンの名前を、ユーザーにわかりやすい名前に変更します。たとえば、最初のフォームの「検索」ボタンの名前は、「Cancel Query」に変更できます。これは、このボタンをクリックすると、イテレータがFind モードではなくなるためです。最初のフォームの「実行」ボタンの名前は、「Execute Query」に変更できます。また、2番目の「検索」ボタンの名前は、「Enter Query」に変更できます。このボタンは、イテレータを検索モードにして、最初のフォームの表示に使用されるためです。
検索フォームをページにドロップすると、例18-1に示すように、Find操作にバインドされているコマンド・ボタンと、Execute操作にバインドされているコマンド・ボタンが追加されます。Find操作により、関連付けられているイテレータがFindモードになります。Execute操作は、問合せを実行し、イテレータのFindモードを終了します。
例18-1 Find操作およびExecute操作のページ定義コード
<action id="Find" RequiresUpdateModel="true" Action="3"
IterBinding="ServiceRequestsIterator"/>
<action id="Execute" RequiresUpdateModel="true" Action="2"
IterBinding="ServiceRequestsIterator"/>
次の表に、組込み検索操作および操作を起動した結果を示します。
表18-1 組込み検索操作
| 操作 | アクション属性値 | 関連イテレータ・バインディングによる起動時の処理 |
|---|---|---|
|
|
3 |
関連付けられているイテレータを |
|
|
2 |
|
また、「ADF検索フォーム」をドロップすると、「検索」ボタンおよび「実行」ボタンのあるpanelGroupコンポーネント内にoutputTextコンポーネントが追加されます。このoutputTextコンポーネントにより、イテレータがFindモードの場合は常に、「検索モード」という文字が表示されます。これは主に開発目的で使用され、この表示により、イテレータがFindモードであることを簡単に確認できます。このコンポーネントは削除しても問題ありません。
標準のWebタイプ検索フォームでは、ユーザーがフォームを手動でFindモードにできないようにする必要があります。かわりに、検索基準の入力と検索の実行のみを許可します。このためには、イテレータが常にFindモードになるように構成します。その後、結果を別のページまたは同じページで表示するように設定できます。同じページで表示する場合は、Findモード以外にもなる結果セット用の別のイテレータを作成する必要があります。
常に検索モードの検索フォームを作成するには、検索対象のコレクションを「ADF検索フォーム」としてドロップし、それをFindモードで保持する条件をイテレータに設定します。その後、同じコレクションを、結果を表示する別のページに表またはフォームとしてドロップします。
検索および結果を別々のページに作成する手順:
データ・コントロール・パレットからコレクションをドラッグし、ポップアップ・メニューから「フォーム」→「ADF検索フォーム」を選択します。
たとえば、問合せをすべてのサービス・リクエストに対して実行するには、ServiceRequestsコレクションをドラッグします。
同じコレクションを別のページでドラッグしますが、今回は、それを任意のタイプの表またはフォームとしてドロップします。
「実行」ボタンに、検索フォームと結果ページ間のナビゲーションを作成します。この機能により、問合せが終了すると、ユーザーは結果ページに移動できます。ナビゲーションの作成の詳細は、第16章「ページ・ナビゲーションの追加」を参照してください。
この時点で、ページ上の検索フォームがレンダリングされると、最初のレコードのテキスト・ボックスの値が表示されます。イテレータをFindモードに設定して検索基準を入力するには、ユーザーは「検索」ボタンをクリックする必要があります。ユーザーが次に「実行」ボタンをクリックすると、結果ページが開き、表に問合せの結果が表示されます。検索フォームに戻ると、結果セットの最初のレコードの属性値が表示されます。
次の一連の手順を実行すると、「検索」ボタンが不要になります。
検索フォームのイテレータを自動的に検索モードにするには、次の手順を実行します。
検索ページのページ定義ファイルを開きます。
構造ペインでExecutablesノードを右クリックし、「実行可能ファイルの中に挿入」→「invokeAction」を選択します。
「invokeActionの挿入」ダイアログで、アクションのID(AlwaysFindなど)を入力します。「バインド」ドロップダウン・リストから、「検索」を選択します。「OK」をクリックしたり、ダイアログを終了しないでください。
「invokeActionの挿入」ダイアログで、「アドバンスト・プロパティ」を選択します。
RefreshConditionに、次のEL式を入力します。この式により、アプリケーションは、ページがFindモード以外の場合は常にこのFindアクションを起動するように指示されます。<iterator>はイテレータの名前と置き換えてください。
${bindings.<iterator>.findMode == false}
検索JSFページで、「検索」ボタンを削除します。この操作では、JSFページからのコンポーネントの削除のみが行われます。バインディングは、RefreshConditionのEL式によって参照されているため、ページ定義に残ります。
検索フォームをページにドロップすると、Find操作にバインドされているコマンド・ボタンと、Execute操作にバインドされているコマンド・ボタンが追加されます。詳細は、18.2.2項「検索フォームの作成時の処理」を参照してください。
invokeActionsは、操作を暗黙的に起動する場合に使用します。たとえば、検索ページでは、ユーザーに「検索」ボタンのクリックを要求するかわりに、定義したタイミング、または定義した条件がtrueと評価されたときにこの操作を起動できます。
RefreshCondition属性では、アクションを起動する条件を指定します。Refresh属性では、RefreshConditionがtrueと評価された場合に、ADFmライフサイクルのどの時点でアクションが起動されるかを指定します。Webタイプの検索ページでは、イテレータがFindモード以外の場合は常にFindアクションを起動するように指示する条件に評価されるEL式を使用します。たとえば、SRSearchページのページ定義の内容は次のとおりです。
例18-2 Find InvokeActionおよび関連バインディングのページ定義コード
<executables>
<invokeAction id="AlwaysFind" Binds="Find" Refresh="ifNeeded"
RefreshCondition=
"${bindings.SearchServiceRequestsIterator.findMode == false}"/>
<iterator id="SearchServiceRequestsIterator" RangeSize="10"
Binds="SearchServiceRequests" DataControl="SRService"/>
</executables>
...
<bindings>
...
<action id="Find" RequiresUpdateModel="true" Action="3"
IterBinding="SearchServiceRequestsIterator"/>
...
</bindings>
イテレータを常にFindモードにする条件を作成することで、そのイテレータを参照する他のすべてのバインディングも、Findモードの間はそのイテレータを参照するようになります。このため、同じくそのイテレータを参照する必要があっても、Findモードである必要はない別のコンポーネントを同じページに設定する場合は、同じコレクションに基づく別のイテレータを作成する必要があります。この方法により、検索結果を検索フォームと同じページに配置できます。詳細は、次項第18章「同じページでの検索および結果の作成の考慮事項」を参照してください。
前述のとおり、イテレータをFindモードにすると、関連付けられているすべてのバインディングに対してそのイテレータはFindモードになります。同じコレクションを表としてドロップして検索結果を表示すると、その表のバインディングでは、検索フォームと同じイテレータを使用します。つまり、表コンポーネントはFindモードのイテレータ・バインディングにバインドされるため、「実行」を押してイテレータのFindモードを終了するまでは、表には、実際のデータではなく、図18-4に示すように、現在のQBEビュー基準行が表示されます。
これを回避するには、Findモードではなく、検索基準を満たすデータのコレクションを表示する表のために別のイテレータを作成する必要があります。
同じページに検索フォームと結果表を作成するには、この両方を別々のページに作成する場合と同じ手順を実行しますが、結果表のために別のイテレータを作成する必要があります。
同じページでの検索フォームおよび結果表の作成手順:
データ・コントロール・パレットからコレクションをドラッグし、ポップアップ・メニューから「フォーム」→「ADF検索フォーム」を選択します。
たとえば、問合せをすべてのサービス・リクエストに対して実行するには、ServiceRequestsコレクションをドラッグします。
同じコレクションをドラッグしますが、今回は、それを任意のタイプの表としてドロップします。
関連付けられているページ定義ファイルを開きます。
構造ペインでExecutablesノードを右クリックし、「実行可能ファイルの中に挿入」→「invokeAction」を選択します。
「invokeActionの挿入」ダイアログで、アクションのID(AlwaysFindなど)を入力します。「バインド」ドロップダウン・リストから、「検索」を選択します。「OK」をクリックしたり、ダイアログを終了しないでください。
「invokeActionの挿入」ダイアログで、「アドバンスト・プロパティ」を選択します。
RefreshConditionに、次のEL式を入力します。この式により、アプリケーションは、ページがFindモード以外の場合は常にこのアクションを起動するように指示されます。<iterator>はイテレータの名前と置き換えてください。
${bindings.<iterator>.findMode == false}
|
注意: invokeActionは、最初に実行されるように、イテレータの前にある必要があります。 |
構造ペインでExecutablesノードを右クリックし、「実行可能ファイルの中に挿入」→「イテレータ」を選択します。
検索フォームに使用されているものと同じコレクションを選択し、「イテレータID」フィールドにわかりやすい名前(ResultsIteratorなど)を入力して、「OK」をクリックします。
構造ペインでbindingsノードを拡張し、結果表のバインディングを右クリックして、「プロパティ」を選択します。
「表バインディング・エディタ」ダイアログで、正しいコレクションが「データ・コレクション」列で選択されていることを確認します。
新しく作成したイテレータを「イテレータ」ドロップダウン・リストから選択し、適切な属性がすべて「属性の表示」列にあることを確認して、「OK」をクリックします。
JSFページで、「検索」ボタンを削除します。
この操作では、JSFページからのコンポーネントの削除のみが行われます。バインディングは、ページ定義ファイルに残ります。
前述の手順では、表のための新しいイテレータを作成しました。このイテレータは、同じコレクションを使用して作成されましたが、Find操作が関連付けられていません。このため、検索の結果を常に表示します。
たとえば、SRSearchページのページ定義の内容は次のとおりです。
例18-3 2つのイテレータによる検索フォームおよび結果表の作成
<executables>
<invokeAction id="AlwaysFind" Binds="Find" Refresh="ifNeeded"
RefreshCondition=
"${bindings.SearchServiceRequestsIterator.findMode == false}"/>
...
<iterator id="SearchServiceRequestsIterator" RangeSize="10"
Binds="SearchServiceRequests" DataControl="SRService"/>
<iterator id="SearchServiceRequestsResultsIterator" RangeSize="10"
Binds="SearchServiceRequests" DataControl="SRService" />
. . .
</executables>
. . .
<bindings>
. . .
<action id="Find" RequiresUpdateModel="true" Action="3"
IterBinding="SearchServiceRequestsIterator"
. . .
<table id="AllServiceRequests" IterBinding="AllServiceRequestsResultsIterator">
. . .
</table>
</bindings>
検索フォームは、名前付きバインド変数によって対象のオブジェクトを検索する、ビュー・オブジェクトの問合せを使用して作成できます。たとえば、StaffListByEmailNameRoleビュー・オブジェクトでは、次の名前付きバインド変数を使用します。
TheFirstName
TheLastName
EmailAddress
Role
図18-5は、StaffListByEmailNameRoleビュー・オブジェクトを使用して作成されたSRStaffSearch検索フォームを示しています。このページでは、名、姓、電子メール・アドレスおよびロールを指定してスタッフ・ユーザーを検索します。
パラメータ付き検索では、パラメータを表す変数を使用するため、Execute操作を使用して問合せを起動するのではなく、ExecuteWithParams操作を使用します。検索フォームは、ExecuteWithParams操作をパラメータ付きフォームとしてドロップして作成します。その後、対応するコレクションを表としてドロップし、結果を表示します。図18-6に、StaffListByEmailNameRoleコレクションのExecuteWithParams操作を示します。
検索フォームおよび結果表の作成手順:
データ・コントロール・パレットから、ExecuteWithParams操作をドラッグします。
ポップアップ・メニューから、「パラメータ」→「ADFパラメータ・フォーム」を選択します。
「フォーム・フィールドの編集」ダイアログを使用して、フィールドの表示を変更します。
データ・コントロール・パレットから対応するコレクションをドラッグし、それを任意のタイプの表またはフォームとしてドロップします。
ExecuteWithParams操作をパラメータ・フォームとしてドロップすると、JDeveloperによって次の処理が行われます。
データ値を保持する変数、操作のアクション・バインディング、および関連付けられている属性の属性バインディングが、ページ定義ファイルで定義されます。
属性バインディングにバインドされているADF Faces inputTextコンポーネントおよびExecuteWithParams操作にバインドされているADF Faces commandButtonコンポーネントを使用して、JSFページにフォームのコードが挿入されます。このコードは、その他の入力フォームまたはコマンド・ボタンのコードと同じです。
ExecuteやNextなどの操作をドロップするときと同様に、ExecuteWithParams操作をドロップすると、JDeveloperによってアクション・バインディングが作成されます。ただし、実行するパラメータが操作によって要求されるため、JDeveloperによって、各パラメータのNamedData要素も作成されます。これらの要素は、関連付けられているビュー・オブジェクトの名前付きバインド変数を表します。各NamedData要素は、対応する属性の値バインディングにバインドされます。このバインディングにより、操作は、実行のパラメータに対する正しい属性の値にアクセスできます。
たとえば、StaffListByEmailNameRoleコレクションのExecuteWithParams操作のアクション・バインディングには、StaffListByEmailNameRoleビュー・オブジェクトのそれぞれの名前付きバインド変数に対するNamedData要素が含まれています。NamedData要素のEmailAddressは、EL式を使用して、StaffListByEmailNameRole_EmailAddres属性バインディングにバインドされます。例18-4は、アクション・バインディングおよびStaffListByEmailNameRoleコレクションのExecuteWithParameters操作をパラメータ・フォームとしてドロップしたときに作成される属性バインディングの一部を示しています。
例18-4 ページ定義ファイルでのメソッド・アクション・バインディング
<bindings>
<action id="ExecuteWithParams"
IterBinding="StaffListByEmailNameRoleIterator"
InstanceName="SRService.StaffListByEmailNameRole"
DataControl="SRService" RequiresUpdateModel="true" Action="95">
<NamedData NDName="EmailAddress" NDType="java.lang.String"
NDValue="${bindings.StaffListByEmailNameRole_EmailAddress}"/>
<NamedData NDName="Role" NDType="java.lang.String"
NDValue="${bindings.StaffListByEmailNameRole_Role}"/>
<NamedData NDName="TheFirstName" NDType="java.lang.String"
NDValue="${bindings.StaffListByEmailNameRole_TheFirstName}"/>
<NamedData NDName="TheLastName" NDType="java.lang.String"
NDValue="${bindings.StaffListByEmailNameRole_TheLastName}"/>
</action>
<attributeValues id="EmailAddress" IterBinding="variables">
<AttrNames>
<Item Value="StaffListByEmailNameRole_EmailAddress"/>
</AttrNames>
</attributeValues>
...
</bindings>
ExecuteWithParams操作をドロップしたため、属性はコレクションのイテレータではなく、変数にアクセスする変数イテレータを参照します。これは、操作は(戻されたコレクションとは異なり)オブジェクトのインスタンスにアクセスする必要がなく、ページに入力された値を保持するものがないためです。変数はこれらのデータ・ホルダーとして機能します。
JDeveloperによって、それぞれの名前付きバインド変数に対して変数が作成されます。これらの変数は変数イテレータの子として宣言され、ローカルであるため、単一のリクエストのみで有効になります。また、同じフォームへの後続の複数の返信には継承されますが、ユーザーが別のページに移動すると無効になります(そして再初期化されます)。例18-5は、変数イテレータおよびStaffListByEmailNameRoleコレクションのExecuteWithParameters操作のドロップ時に作成される変数を示しています。変数イテレータは、フォームおよびボタンの両方で使用されます。
例18-5 ページ定義ファイルでの変数イテレータおよび変数
<executables>
<iterator id="StaffListByEmailNameRoleIterator" RangeSize="10"
Binds="StaffListByEmailNameRole" DataControl="SRService"/>
<variableIterator id="variables">
<variableUsage DataControl="SRService"
Binds="StaffListByEmailNameRole.variablesMap.EmailAddress"
Name="StaffListByEmailNameRole_EmailAddress"
IsQueriable="false"/>
<variableUsage DataControl="SRService"
Binds="StaffListByEmailNameRole.variablesMap.Role"
Name="StaffListByEmailNameRole_Role" IsQueriable="false"/>
<variableUsage DataControl="SRService"
Binds="StaffListByEmailNameRole.variablesMap.TheFirstName"
Name="StaffListByEmailNameRole_TheFirstName"
IsQueriable="false"/>
<variableUsage DataControl="SRService"
Binds="StaffListByEmailNameRole.variablesMap.TheLastName"
Name="StaffListByEmailNameRole_TheLastName"
IsQueriable="false"/>
</variableIterator>
</executables>
ユーザーがデータを入力してフォームを送信すると、変数に値が移入され、NamedDataElementの値に対するEL式を使用して、属性バインディングによって名前付きバインド変数の値が提供されます。
|
ヒント: 検索フォームおよび結果表が同じページにある場合、ユーザーがそのページに初めてアクセスしたときに、イテレータからのすべてのレコードが表に表示されます。ユーザーが実際に検索を実行するまで結果表が表示されないようにすることができます。手順は、18.5項「検索ページの結果表の条件付き表示」を参照してください。 |
ユーザーが対応するinputTextコンポーネントに姓としてSmithを入力し、コマンド・ボタンをクリックすると、次の処理が実行されます。
StaffListByEmailNameRole_TheLastName変数に値Smithが移入されます。他のフィールドに値が入力されなかった場合は、該当する変数によって、ビュー・オブジェクトの名前付きバインド変数に設定されているデフォルト値が使用されます。詳細は、5.9項「名前付きバインド変数の使用」を参照してください。
次のように、この属性バインディングは変数イテレータを参照するため、TheLastNameの値および他の変数値を取得できます。
<attributeValues id="TheLastName" IterBinding="variables">
<AttrNames>
<Item Value="StaffListByEmailNameRole_TheLastName"/>
</AttrNames>
</attributeValues>
次のように、NamedData要素には属性バインディングのアイテム値に対して評価するEL式が含まれているため、パラメータは値にもアクセスできます。
<NamedData NDName="TheLastName" NDType="java.lang.String"
NDValue="${bindings.StaffListByEmailNameRole_TheLastName}"/>
NamedData要素から値を取得するパラメータを使用して、ExecuteWithParams操作が実行されます。
この操作により、名前付きバインド変数が適用され、問合せが実行されます。
StaffListByEmailNameRoleIteratorイテレータによってコレクションが反復処理されるため、表に結果が表示されるようになります。実行時の表の詳細は、14.2.2項「データ・コントロール・パレットを使用した表の作成時に発生する処理」を参照してください。
Web検索フォームおよび結果表が同じページにある場合、ユーザーがそのページに初めてアクセスしたときに、イテレータからの現在レンジのすべてのレコードが表に表示されます。ユーザーが実際に検索を実行するまで結果表が表示されないようにすることができます。図18-7は、ユーザーが初めてアクセスしたときのSRSearchページの表示を示しています。
ユーザーが検索を実行すると、図18-8のように結果表が表示されます。
条件付きで結果表を表示するには、UIコンポーネント(表自体または表コンポーネントを保持する別のコンポーネント)について、ユーザーによる検索ページへのアクセスが1回目かどうかに対して評価するEL式を入力する必要があります。マネージドBeanのフィールドには、式で使用された値が保持されます。
条件付きで結果表を表示する手順:
同じページで検索フォームおよび結果表を作成します。
マネージドBeanで、ユーザーによるページへのアクセスが1回目の場合に設定されるフラグを作成します。たとえば、SRDemoアプリケーションのuserStateマネージドBeanには、SEARCH_FIRSTTIME_FLAGパラメータが含まれます。結果表をレンダリングするかどうかを判断するために、ページのEL式は、このパラメータの値を認識する必要があります(手順4を参照)。このBeanがEL式に対してインスタンス化されると、isSearchFirstTimeメソッドによってこのフィールドがチェックされます。フィールドがnullの場合は、値がTrueに設定されます。マネージドBeanの作成方法の詳細は、17.2項「マネージドBeanを使用した情報の格納」を参照してください。
JSFページで、setActionListenerコンポーネントを、この検索の実行に使用されるコマンド・コンポーネントに挿入します。from属性を#{false}に設定します。to属性を、手順2で作成したマネージドBeanのフィールドに設定します。これにより、このボタンがクリックされるたびに、このフィールドがfalseに設定されます。setActionListenerコンポーネントの使用方法の詳細は、17.4項「コマンド・コンポーネントを使用したパラメータ値の設定」を参照してください。
例18-6は、SRSearchページの「検索」ボタンのコードを示しています。
JSFページでRendered属性の値としてEL式を使用し、変数が特定の値の場合のみUIコンポーネント(表または表を保持するUIコンポーネント)によってレンダリングが行われるようにします。
例18-7は、SRSearchページでpanelGroupコンポーネントのRendered属性の値に使用されるEL式を示しています。
このEL式により、searchFirstTimeフラグの値がFalseの場合のみ、panelGroupコンポーネントによってレンダリングが行われます。
マネージドBeanを使用して値を保持すると、その他のオブジェクトによる値の設定および値へのアクセスがともに可能になります。たとえば、パラメータ値の引渡しと同様に、setActionListenerコンポーネントを使用してマネージドBeanに値を設定すると、コンポーネントのrendered属性のEL式がその値にアクセスできるようになります。
たとえば、ユーザーが初めてSRSearchページにアクセスした場合は、次の処理が行われます。
表を保持するpanelGroupコンポーネントには、そのrendered属性のEL式が含まれており、EL式がuserState Beanを参照するため、このBeanがインスタンス化されます。
ユーザーはまだページにアクセスしていないため、userState BeanのSEARCH_FIRSTTIME_FLAGフィールドは未設定であり、値はnullです。
値がnullであるため、このBeanのisSearchFirstTimeメソッドによって、SEARCH_FIRSTTIME_FLAGフィールドがtrueに設定されます。
panelGroupコンポーネントのEL式が評価される際、SEARCH_FIRSTTIME_FLAGフィールドがtrueであることから、SRSearchページは表示されますが、panelGroupコンポーネントはレンダリングされません。これは、Rendered属性のEL式は、SEARCH_FIRSTTIME_FLAGフィールドがfalseの場合にのみ、Trueと評価されるためです。
ユーザーが検索条件を入力して「検索」ボタンをクリックすると、関連付けられているsetActionListenerコンポーネントによって、userState BeanのSEARCH_FIRSTTIME_FLAGフィールドがfalseに設定されます。
コマンド・ボタンの結果が定義されていないため、ユーザーは同じページにとどまります。
この時点ではSEARCH_FIRSTTIME_FLAGフィールドがfalseに設定されているため、結果を使用してページが再レンダリングされると、panelGroupコンポーネントによって結果を含む表が表示されます。