ナビゲーション・ヘッダーをスキップ
Oracle ADF UIX開発者ガイド 目次へ
目次
前のページへ戻る
前へ
次のページへ進む
次へ

11. ADF UIXでのLOVの作成

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

概要

多くのWebページでは、エンド・ユーザーがテキスト・データを入力または更新できます。 場合によっては、入力値に対する制限がなく、ユーザーが任意の値を入力可能なこともあります。 ただし、多くの場合、ユーザーからの入力値を特定の選択可能な値のセットに制限する必要があります。 これを行うには、ラジオ・ボタン、チェック・ボックスまたはプルダウン・リストを使用します。 これらの要素は、選択肢の数が少ない場合には有効です。ただし、大規模なデータセットでは非効率的です。

大規模なデータセットを使用している場合、ユーザーに選択肢を提示する最も有効な方法は、値リスト(LOV)を使用することです。 多くの場合、LOVは別のウィンドウに表示されます。 データを表形式で表示すると、目的の値をより簡単に見つけることができるようになります。 多くのデータセットが存在する場合、データをソートしたり、表示される値の数を絞り込む機能は、非常に役立ちます。

Oracle ADF UIXでは、LOVをユーザーに示すための要素が提供されています。 これらの要素を使用すると、別のウィンドウの表示と管理、メイン・ウィンドウとLOVウィンドウ間のデータ転送の管理、フィルタリング・イベントの提供、および別のウィンドウでの適切なフィールドのレイアウトを実行できます。 主な要素は、lovInput要素とlistOfValues要素の2つです。

lovInput要素

まず、lovInput要素について説明します。 この要素は、単純なテキスト入力フィールドと、懐中電灯の形をした検索アイコンを実装します。 最も簡単な書式では、destination属性を使用します。 この属性は、別のウィンドウの移入に使用される、listOfValues要素を含むUIXページを指します。 次に、UIXタグの例を示します。


    <lovInput id="myLOV"
              name="myLOV"
              columns ="10"
              destination="LOVDlg.uix"
              partialRenderMode="self"/>

この例では、次のように表示されます。
レンダリングされたlovInput要素
図11-1: レンダリングされたlovInput

ユーザーがテキスト・フィールドにテキストを入力すると、部分ページ・イベントlovValidateが生成されます(PPRアーキテクチャの詳細は、「ADF UIXでの部分ページ・レンダリングおよびクライアント・アクション」のトピックを参照してください)。 このイベントでは、ユーザーのテキストがsearchTextパラメータに入力されます。 イベント・ハンドラのコードでsearchTextを評価して、そのフィールドの有効な値のいずれかに一致した場合にその値を許可することができます。 有効な値に一致しなかったときに、ユーザーが適切な値を選択できるようにするウィンドウを表示する場合があります。 このような動作を設定するには、前述の単純なlovInputを次のように拡張する必要があります。


   <lovInput id="myLOV"
             name="myLOV"
             columns ="10"
             destination="LOVDlg.uix" 
             text="${ui:defaulting(uix.data.fieldText,
                                   uix.data.defaultText)}"
             showWindow="${uix.eventResult.showWindow}"
             partialRenderMode="self"/>

これによって、テキスト・フィールドにデフォルトのテキストが表示されるようになります。また、さらに重要な点は、イベント・ハンドラによってfieldTextのプロバイダが新しく検証された値で更新されると、その値が自動的に表示されることです。 そのため、たとえば、値データセットが8000m級の14の山々である場合、ユーザーがAという文字を入力すると、一致する山はアンナプルナ(Annapurna)のみであることが検出され、このフルネームでfieldDataプロバイダが更新されます。 このような動作を設定する方法については、「ADF UIXでのデータ・バインディング」のトピックを参照してください。 このような自動一致/自動入力機能は、非常に役立ちます。 イベント・ハンドラは、次のようになります。


  public static EventResult handleLovValidateEvent(
    BajaContext context,
    Page        page,
    PageEvent   event
    )
  {
    String searchText = event.getParameter("searchText");

    // Implementation of matchPeak and MatchClass not shown, but
    // matchPeak will validate the search text. MatchClass will keep
    // the match data.
    MatchClass matches = matchPeak(searchText);
    if (matches.isValid())
    {
      // update the provider for the text attribute on the lovInput
      fieldText.put(matches.getValidText());
    }
    return new EventResult(page);
  }

ユーザーが常に目的の山を正確に認識しているとは限りません。 山の名前の最初の文字のみがわかっている場合や、正しく綴りを覚えていない場合があります。また、入力ミスや、テスト目的のみの場合もあります。 このような場合に、新しいウィンドウを自動的に表示して、正しいLOVを表示できます。

これを行うのが、showWindow属性です。 ほとんどの場合、showWindowは、消去してfalseに設定する必要があります。 この属性が部分リフレッシュ時にtrueに設定されると、lovInput要素は、新しいウィンドウを開くスクリプトをクライアントに自動的に送信します。 showWindowはページ・レンダリング後まで値を保持する必要がないため、EventResultに直接渡すことができます。 イベント・ハンドラは、次のようになります。


  public static EventResult handleLovValidateEvent(
    BajaContext context,
    Page        page,
    PageEvent   event
    )
  {
    String searchText = event.getParameter("searchText");

    // Implementation of matchPeak and MatchClass not shown, but
    // matchPeak will validate the search text. MatchClass will keep
    // the match data. This matchPeak matches on the peak name.
    MatchClass matches = matchPeak(searchText);
    if (matches.isValid())
    {
      // update the provider for the text attribute on the lovInput
      fieldText.put(matches.getValidText());
    }
    else
    {
      // Save the MatchClass off to some persistent store so that searchText
      // and possibly the matches are available for the LOV window.
    }
    EventResult result = new EventResult(page);

    // only pop up the LOV window if there isn't an exact match
    result.setProperty("showWindow", !matches.isValid());

    return result;
  }

ウィンドウが表示される前に、searchTextパラメータに同じテキストが含まれたlovFilterイベントを受け取ります。このイベントによって、その時点で実際のデータを取得できます。 部分ページ・レンダリング以外の場合はlovValidateイベントは生成されず、また、ユーザーがLOVウィンドウで検索条件を変更する場合があるため(詳細は後述の説明を参照)、このイベント処理は重要です。 lovFilterハンドラで特殊な操作を行う必要はありません。これは、次のようになります。


  public static EventResult handleLovFilterEvent(
    BajaContext context,
    Page page,
    PageEvent event)
  {
    // The source parameter tells you which lovInput field this came from
    String source = (String) event.getParameter("source");

    // Now do the search for the given text in the given category
    // categories may be name, location, altitude etc. for this example
    String cName = event.getParameter("choiceElementName");
    String searchText = event.getParameter("searchText");

    // Implementation of matchPeak and MatchClass not shown, but
    // matchPeak will validate the input text. MatchClass will keep
    //  the match data. This matchPeak matches on the given category.
    MatchClass matches = matchPeak(searchText, cName);

    // and build the display data for the table on the LOV window
    setTableDataProviderFromMatches(matches);

    return new EventResult(page);
  }

ユーザーがKと入力すると、次のようなウィンドウが表示されます。

2つの選択肢(K2およびKangchenjunga)が表示されたLOVウィンドウ
図11-2: 2つの値にフィルタリングされたデータセットが表示されたLOVウィンドウ

このようなページを作成してJavaScriptを記述するには若干の作業が必要ですが、 これを行う要素はすでに準備されています。 前述のように、lovInputのdestination属性は、listOfValues要素を使用して実際のLOVを表示するページを指しています。 ここに示したページは、listOfValues要素とその表を少し修正したものです。

listOfValues要素

このセクションでは、listOfValues要素について説明します。 この要素は非常に広範囲にわたっていますが、この要素を構成する他の要素は、ほとんど説明済です。 この要素は、次のようにまとめることができます。


   <listOfValues title="Available peak values"
                 id="lovHandler"
                 searchText="${uix.data.fieldData}">
    <headerInstructions>
     <styledText text="Choose a peak"
                 styleClass="OraInstructionText"/>
    </headerInstructions>

    <searchInstructions>
     <styledText text="You can also change or refine your search.
                       Try searching on peaks using a search text of 'A',
                       'K', or 'M'. Try searching locations using an 'N'."
                 styleClass="OraInstructionText"/>
    </searchInstructions>

    <filterChoice>
     <choice name="categoryChoice">
         <!-- fill in the choices from the column headers -->
     </choice>
    </filterChoice>

    <contents>
     <!-- Here's the table definition                 -->
     <!-- This must be a form submitted proxied table -->
     <table name="lovTbl"
            formSubmitted="true"
            proxied="true"
               ... >
     <!-- Populate with some data  -->
     </table>
    </contents>
   </listOfValues>

順を追って少しずつ説明します。 主な属性は単純で、すべて説明済です。 id属性は単純で、説明済です。 title属性は、ページの最上位レベルのヘッダーを指定します。これは、ウィンドウ上部の(翻訳された)「検索および選択:」の直後に表示されます。 searchTextは、lovInputtextフィールドと同じデータにバインドされています。 そのフィールドから検索テキストが取得されるためです。

次に、2種類の名前の付けられた子が記述されています。これは、説明テキストです。


    <headerInstructions>
     <styledText text="Choose a peak"
                 styleClass="OraInstructionText"/>
    </headerInstructions>

    <searchInstructions>
     <styledText text="You can also change or refine your search.
                       Try searching on peaks using a search text of 'A',
                       'K', or 'M'. Try searching locations using an 'N'."
                 styleClass="OraInstructionText"/>
    </searchInstructions>

最初のheaderInstructionsは、このページでユーザーが行う操作の概要を示すために使用されています。 2番目のsearchInstructionsは、検索方法を変更するための詳細な指示を示しています(後述の説明を参照)。

次に、filterChoiceという名前の付けられた子があります。


    <filterChoice>
     <choice name="categoryChoice">
         <!-- fill in the choices from the column headers -->
     </choice>
    </filterChoice>

この子には、選択可能な検索カテゴリのプルダウン・リストを表示するchoice要素のみが含まれます。 これによって、ユーザーは検索方法を変更できます。 表示された値に目的の山が含まれておらず、その山がパキスタンにあることがわかっている場合、カテゴリの選択を場所(表の列ヘッダーの1つ)に変更し、検索テキスト・フィールドにPaを入力して「実行」をクリックします。 lovFilterイベントが再度生成され、同じハンドラを使用して、表データを更新できます。

最後に、唯一の索引付けされた子があります。これは、ユーザーのsearchTextを使用して基のデータをフィルタリングして得た検索結果を表示するためのtable要素です。


    <contents>
     <!-- Here's the table definition                 -->
     <!-- This must be a form submitted proxied table -->
     <table name="lovTbl"
            formSubmitted="true"
            proxied="true"
               ... >
     <!-- Populate with some data  -->
     </table>
    </contents>

table要素の詳細は、「ADF UIXでの表の作成」のトピックを参照してください。 通常、contents要素はtable要素を含みますが、実際には任意のUINodeを含むことができます。 この特長を利用して次のようにcontentsを設定すると、表で取得する送信(または検索カテゴリの選択)にデータを追加できます(送信も検索カテゴリの選択も同じ形式です)。


    <contents>
     <flowLayout>
      <contents>
       <table>
        ...
       </table>
       <formValue name="extraParam" value="${uix.current.secretParam}"/>
      </contents>
     </flowLayout>
    </contents>

lovOpenWindowActionクライアント・アクション

選択された値をテキスト入力フィールドに送り返す以外の動作を行う場合があります。 そのような場合、lovOpenWindowActionクライアント・アクションを使用します(クライアント・アクションの詳細は、「ADF UIXでの部分ページ・レンダリングおよびクライアント・アクション」のトピックの「クライアント・アクション」セクションを参照してください)。

lovOpenWindowActionクライアント・アクションは、LOVウィンドウを起動するために必要なコードを生成することのみを行います。 これは、lovInput要素で検索アイコンを使用する場合とほぼ同じです。 この要素を使用すると、任意の要素からLOVを起動できます。 これは、ユーザーが表へ行を追加することを許可し、行が正しいことを確認する場合に有効です。 次に例を示します。


      <button id="lovAddButton"
              text="add rows"
              shortDesc="Add more rows to the table">
       <primaryClientAction>
        <lovOpenWindowAction destination="LOVDlg.uix"
                             targets="peaksAddTable"/>
       </primaryClientAction>
      </button>

アクションに初期searchTextを追加すると、LOVを事前にフィルタリングすることもできます。


      <button id="lovAddButton"
              text="add more 'G' rows"
              shortDesc="Add more 'G' rows to the table">
       <primaryClientAction>
        <lovOpenWindowAction destination="LOVDlg.uix"
                             searchText="G"
                             targets="peaksAddTable"/>
       </primaryClientAction>
      </button>

まとめとデモ

これで、 独自のLOVを構築するために必要な基本手順についてすべて説明しました。 JavaScriptのコールバックなどのより高度な機能については、ここでは説明しません。 コード例およびデモについては、Oracle Technology Networkを参照してください。