< 前へ | 次へ >

演習 8: Rich UI ハンドラーへの変数および関数の追加

ユーザー・インターフェースをサポートするソース・コードを追加します。

演習 8 と 9 では、EGL ソース・コードを直接更新し、変更内容を「プレビュー」タブで確認します。

データ・グリッドをサポートするためのコードの追加

データ・グリッドの宣言を変更します。変更する目的は 2 つあり、1 つはユーザーがセルを選択したときに Web ページが対応するようにするためであり、もう 1 つはグリッド出力が正しくフォーマット設定されるようにするためです。
  1. 「プロジェクト・エクスプローラー」で、「PaymentClient」 > 「EGLSource」 > 「ハンドラー」を開き、PaymentFileMaintenance.egl をダブルクリックします。
  2. 「ソース (Source)」タブをクリックする。

エラー・マークは無視して、以下の変更を行います。

  1. allPayments_ui DataGrid 宣言で、columns プロパティーの直前に以下のコードを追加します。
    		selectionListeners ::= cellClicked,

    selectionListeners プロパティーは、ユーザーがグリッド内のセルを選択したときに常に呼び出される 1 つ以上の関数を指定します。このケースでは、関数名を既存の配列に追加します。この演習の後の方で、cellClicked 関数を作成します。

  2. フォーマッターは、DataGrid 列にある値の外観を変更する機能です。この機能を実演するために、カテゴリーの DataGridColumn 宣言を見つけてください。ユーザーが整数ではなくカテゴリー説明を確認できるように、以下のコードを width=90 の後に追加します。
    , formatters = [ formatCategory ]
  3. 列にドル額を表示する場合、通常、値は右揃えにします。右揃えにするための関数をコーディングする必要はありません。その代わり、以下のコードを amount の width 項目の後に追加します。
    , alignment = DataGridLib.ALIGN_RIGHT
    allPayments_ui 宣言は、以下のようになります。cellClickedformatCategory についてはエラー・マークが示されます。
    allPayments_ui DataGrid {
                   layoutData = new GridLayoutData
                                {row = 2, column = 1,
                                 verticalAlignment = GridLayoutLib.VALIGN_TOP},
                   selectionListeners ::= cellClicked,
                   columns =[
                      new DataGridColumn{name = "category", 
                                         displayName = "Type", 
                                         width = 90,
                                         formatters = [formatCategory]},
                      new DataGridColumn{name = "description", 
                                         displayName = "Description", 
                                         width = 120},
                      new DataGridColumn{name = "amount", 
                                         displayName = "Amount due", 
                                         width = 90,
                                         alignment = DataGridLib.ALIGN_RIGHT}
                   ],
                   data = allPayments as any[],
                   selectionMode = DataGridLib.SINGLE_SELECTION};
  4. ファイルを保存します。

ユーザーがデータ・グリッドをクリックしたときに対応する関数のコーディング

cellClicked 関数は、ユーザーがデータ・グリッド内のセルをクリックしたときに呼び出されます。

start 関数の直後に、以下の行を追加します。
function cellClicked(myGrid DataGrid in)
   selectedPayment = allPayments_ui.getSelection()[1] as paymentRec;
   selectedPayment_form.publish();
end

まず cellClicked 関数は、selectedPayment レコードを、データ・グリッドの単一行のデータで更新します。この行には、ユーザーに表示されるフィールドよりも多くのフィールドを含めることができます。このアプリケーションでは、データ・グリッドの単一行は、データベースの単一行に基づきます。

次に、publish 関数により、selectedPayment レコードから selectedPayment_ui レイアウトにデータが転送されます。 この転送は、Web ページの右側にある単一レコード・レイアウトである selectedPayment_ui レイアウトを作成したときに提供されたコードによって可能になります。コードを確認すると、以下のような関係をトレースできます。
  • 書式マネージャー宣言には、書式フィールドが含まれています。
  • 各書式フィールドはコントローラー宣言を参照します。
  • コントローラー宣言は、モデルをビューに関連付けます。このケースでは、selectedPayment レコードのフィールドを selectedPayment_ui レイアウトの子に関連付けます。

書式マネージャーは、さまざまな利点を備えていますが、本質的にはコントローラーの集合です。

ここで、他の 2 つの事項 (大括弧で囲まれた配列添字 ([1]) の使用と、as 演算子の使用) について説明します。
  • getSelection 関数は常に、データ・グリッドの data 配列にある行のサブセットを返します。ただし、データ・グリッドを宣言したときに、selectionMode = DataGridLib.SINGLE_SELECTION 設定を指定して、ユーザーが一度に選択できるのは 1 つの行のみであることを示しました。 ユーザーが選択できるのが 1 つの行のみである場合、1 つの要素のみ使用可能です。
  • getSelection 関数により返される配列のすべての要素は、ANY タイプです。通常、同一のレコード・パーツを使用して、グリッドへの入力とグリッドからの出力を処理します。このチュートリアルでは、レコード・パーツは paymentRec です。レコード・パーツの使用法は以下のとおりです。
    • 次の設定に示すように、データ・グリッドの data プロパティーに割り当てる配列要素の基礎になります。
      data = allPayments as any[]
    • 次に示すように、データ・グリッドの getSelection 関数によって返される配列要素をキャストします。
      allPayments_ui.getSelection()[1] as paymentRec

    いずれのケースでも、as 節が、必要なキャストを提供します。

グリッド内の列値のフォーマット設定

フォーマッター関数を追加するには、以下のステップを実行します。

  1. ファイル内で、最終行である end ステートメントの前に以下のコードを追加します。
    function formatCategory(class string, value string, rowData any in)
       value = PaymentLib.getCategoryDesc(value as INT);
    end

    ご覧のとおり、フォーマッターにはパラメーターがあります。このケースでは、フォーマッターは、以前作成したライブラリー関数をラップします。

  2. Ctrl-Shift-O を押して必要な import ステートメントを編成し、ファイルを保存します。すべてのエラー・マークが消えます。

データ・グリッドのフォーマット設定のテストおよび単一レコード・レイアウトへのデータ転送のテスト

データベースへのアクセス権限を取得する前でも、これまでに加えた変更内容をテストできます。

  1. 「プレビュー」タブをクリックし、カテゴリーが説明になっていることに注目してください (例えば、「1」ではなく「Rent」になっています)。
    フォーマット済みデータ・グリッド
  2. データ・グリッド内のいずれかの行をクリックして、単一行レイアウトが適切に更新されていることを確認してください。ただし、フォーマッターはデータ・グリッドのみに作用したので、単一行レイアウトの「Description」フィールドには数値が含まれています。この問題については、このチュートリアルの後の方で対処します。
  3. 「ソース」タブをクリックし、start 関数を変更して、プロトタイプ・データの最初のレコードに payeeName の値が含まれるようにします。このデータは、データ・グリッドで表示されない paymentRec レコード・フィールドです。
    function start()
       allPayments_ui.data =[
          new paymentRec{
             category = 1, description = "test01", amount = 100.00
             , payeeName = "Someone"},
          new paymentRec{category = 2, description = "test02", amount = 200.00},
          new paymentRec{category = 3, description = "test03", amount = 300.00}];
        end
  4. 「プレビュー」タブをクリックし、データ・グリッド内の最初の行をクリックします。
    データ・グリッドから単一レコード・レイアウトに転送されるデータ
このように、Rich UI エディターのあるタブから別のタブに素早く切り替えることができ、わずかな変更でもテストできます。

プロトタイプ・データのコメント化

このステップで示すように、コードのコメント化とコメント解除を迅速に行うことができます。
  1. 「ソース」タブをクリックします。
  2. start 関数で、assignment ステートメント全体を選択し、選択した領域を右クリックして、「コメント」をクリックします。
    コードおよび「コメント」メニュー項目の選択
  3. コメント・マーク (//) が各行の先頭に表示されます。同じタスクを繰り返し、「コメント」ではなく「コメント解除」をクリックすることで、コメント化を除去できます。ただし、コメントはその行に記入したままにしてください。 以下に示すように、EGL では、スラッシュ・アスタリスク (/*) とアスタリスク・スラッシュ (*/) の区切り文字の使用もサポートしています。
    /*
     
        You can add comments in either of two ways.
     
    */

サービス・アクセス変数の宣言

ここでは、以前定義したサービスと相互作用できるようにするサービス・アクセス変数を宣言します。

変数を作成するには、以下のようにします。

  1. EGL ソース・コードの上部付近で、PaymentFileMaintenance のハンドラー宣言を見つけます。ブランク行を追加し、ui GridLayout 宣言の直前に、以下のステートメントを追加します。
    dbService SQLService{@dedicatedService};

    @dedicatedService プロパティーは、参照されるサービスが、Rich UI ハンドラーを使用してデプロイされる専用サービスであることを示します。

    以下の表示の余白にある赤色の X 記号は、コードに問題があることを示しています。

    コード内でのサービス・アクセス変数の宣言

    エラー・メッセージを表示するには、カーソルを X の上に移動させます。

  2. Ctrl+Shift+O を押して、「未解決タイプ」のエラーを修正します。 新規 import ステートメントは、PaymentService プロジェクト内にある services パッケージの SQLService パーツへのアクセスを提供します。SQLService への参照は解決されます。その理由は、このプロジェクトが PaymentClient プロジェクトの EGL ビルド・パス上にあるからです。
  3. ファイルを保存します。

サービス・アクセス変数を使用してサービスを呼び出す関数の作成

ここでは、専用サービスのさまざまな関数を呼び出すための、複数の関数を作成します。1 つの関数を呼び出すためのセットアップ方法を理解すれば、それ以外のセットアップも簡単に行えます。

すべてのデータを読み取る関数を作成することから始めます。

  1. cellClicked 関数の後に 1 行あけて、以下のコードを追加します。
    function readFromTable()
       call dbService.getAllPayments() returning to updateAll
          onException serviceLib.serviceExceptionHandler;
    end
    注:
    1. Rich UI の call ステートメントは、サービスにアクセスするだけの目的で使用される変化形です。 この場合の実行時通信は非同期です。つまり、サービスが応答している間に、ユーザーは引き続きハンドラーと対話できます。
    2. 非同期 call ステートメントには、以下の 2 つの関数名が含まれます。
      • updateAll
      • serviceLib.serviceExceptionHandler

      この 2 つはコールバック関数 であり、サービスが応答または失敗した後に EGL ランタイム・コードによって呼び出されます。サービスが正常に値を返した場合、updateAll 関数が呼び出されます。呼び出しが失敗した場合、EGL ランタイム・コードは、serviceLib.serviceExceptionHandler という名前に関連付けられている関数を呼び出します。

      デフォルトでは、エラーが発生するとエラー情報が「コンソール」ビュー (開発時) または Web ページの下部 (実行時) に表示されます。ただし、独自のエラー・ハンドラーを指定することができ、これを行う場合は通常、serviceLib.serviceExceptionHandler の代わりの関数名を割り当てます。

  2. call ステートメントの任意の場所をクリックし、さらに右クリックしてから「コールバック関数の作成」をクリックします。 あるいは、ステートメントの任意の場所をクリックし、Ctrl キーを押しながら 1 を押すと、同じ操作を実行できます。
    「コールバック関数の作成」オプション
    EGL は、空の updateAll 関数を作成します。 onException に対して serviceLib.serviceExceptionHandler とは別の関数名を指定した場合、エラー・ハンドラーも作成されます。
    作成した updateAll 関数のパラメーター・リストは、サービスから想定される戻り値の型と同等です。Rich UI エディターの動作を説明する関係性を、以下に示します。
    • サービス・パーツの getAllPayments 関数をエディターで使用できるため、コールバック関数のパラメーター・リストは正確です。
    • 以前のステップで SQLService パーツへの参照を解決したため、この関数は使用可能です。

次に、サンプル・データを追加する関数を作成します。

  1. Ctrl-F をクリックして「検索/置換」ダイアログにアクセスし、SampleData と入力して「検索」をクリックします。
  2. コードが以下のようになるように、sampleData 関数を更新します。
    function sampleData(event Event in)
       call dbService.createDefaultTable() returning to updateAll
          onException serviceLib.serviceExceptionHandler;
    end

    コールバック関数は存在しているため、「コールバック関数の作成」機能は使用しません。

次に、データを追加する関数を作成します。

  1. コードが以下のようになるように、addRow 関数を更新します。
    function addRow(event Event in)
       call dbService.addPayment(new paymentRec) returning to recordAdded
          onException serviceLib.serviceExceptionHandler;
    end
  2. call ステートメントの任意の場所をクリックし、さらに右クリックしてから「コールバック関数の作成」をクリックします。 EGL は、recordAdded 関数を追加します。

データを削除する関数を作成します。

  1. コードが以下のようになるように、deleteRow 関数を更新します。
    function deleteRow(event Event in)
    
       for(i INT from 1 to allPayments.getSize())
          if(allPayments[i].paymentID == selectedPayment.paymentID)
             allPayments.removeElement(i);
             exit for;
          end
       end
    
       call dbService.deletePayment(selectedPayment) returning to recordRevised
          onException serviceLib.serviceExceptionHandler;
    end
    この関数の動作は、以下のとおりです。
    • レコードのローカル配列から、選択した行を削除する
    • データベース・サービスを呼び出し、そのデータベース自体から行を削除する
  2. call ステートメントの任意の場所をクリックし、さらに右クリックしてから「コールバック関数の作成」をクリックします。 EGL は、recordRevised 関数を追加します。
  3. Ctrl-Shift-F を押して、コードのフォーマットを設定します。
  4. ファイルを保存します。

データベース行によりデータ・グリッドを初期化するための start 関数の更新

データ・グリッドを初期化するために、start 関数の end ステートメントの前に以下のコードを追加します。

readFromTable();

readFromTable 関数を onConstructionFunction プロパティーに直接割り当てることもできますが、Web ページのレンダリング前に実行される他のコードを後で追加する場合を考慮に入れて、start 関数は別のロジック単位として残しておくことをお勧めします。

データベースにアクセスせずに Web ページをテストする必要がある場合に備えて、start 関数のコメント化されたコードを残しておいてください。Rich UI エディターのコメント機能とコメント解除機能を使用して、関数呼び出しからプロトタイプ・データへの切り替え、およびその逆の切り替えを迅速に行うことができます。

コールバック関数の完了

ここでは、自動的に作成された以下のコールバック関数を完了させます。
  • updateAll
  • recordAdded
  • recordRevised

updateAll 関数は、専用サービスから paymentRec レコードの配列を受け取ります。 この関数は、次のようにして呼び出されます。

  1. コードが以下のようになるように、updateAll 関数を更新します。
    function updateAll(retResult paymentRec[] in)
       allPayments = retResult;
       allPayments_ui.data = allPayments as any[];
    end
    関数は、支払記録のグローバル配列をサービスから受け取ったデータで更新し、その後データ・グリッドを更新します。

recordAdded 関数は、サービス関数 addPayment に送信されて返されたレコードを受け取ります。

  1. コードが以下のようになるように、recordAdded 関数を更新します。
    function recordAdded(newPayment paymentRec in)
       readFromTable();
    end
    関数 readFromTable は、データベースからすべての行を読み取ります。グリッドによって保管されるデータに、paymentID 値などの新規行を含めることができるようになります。この値はデータベースによって自動生成されたもので、新規行を含めることができるようにならなければグリッドで使用できない値です。

recordRevised 関数は、サービス関数 addPayment に送信されて返されたレコードを受け取ります。

  1. コードが以下のようになるように、recordRevised 関数を更新します。
    function recordRevised(delPayment paymentRec in)
       allPayments_ui.data = allPayments as any[];
    end
    関数はデータ・グリッドを更新します。
  2. Ctrl-Shift-F を押して、コードのフォーマットを設定します。ソース・ファイルにエラーがある場合は、そのコードと演習 8 終了後の PaymentFileMaintenance.egl のコードのファイル内容を比較してください。
  3. ファイルを保存します。

インターフェースのテスト

データベースにアクセスしようとしている現在の状況で、作業内容をプレビューします。
  1. 「プレビュー」タブをクリックします。 プロトタイプ・データをコメント化したためデータ・グリッドにはコンテンツがなく、したがってデータベースには行がありません。
    初期データ・グリッド
  2. 「サンプル」をクリックして、サンプル・データを作成します。
  3. EGL がパスワードを要求したら、「ユーザー ID」「パスワード」の両方のフィールドに admin と入力します。 「ワークベンチが再始動するまで、ユーザー ID およびパスワードを記憶する」を選択し、「OK」をクリックします。
    ID とパスワードのウィンドウ

    このチュートリアルを完了する前にワークベンチを終了して再開すると、次にデータベースにアクセスしようとしたときにこのウィンドウが再表示される可能性があります。

    最終的に、グリッドにサンプル・データの行が組み込まれて再表示されます。
    「Apartment」、「Groceries」、および「ISP」という 3 つの支払い項目が表示されます
  4. 「追加」ボタンをクリックする。 単一のデフォルト値が組み込まれた新規行がグリッドの下部に表示されます。
    新しい行が追加されます
  5. 「Apartment」行を選択し、「削除」をクリックします。 この行が、ディスプレイおよびデータベースの両方から削除されます。
    「Apartment」行が削除されました。
  6. データ・グリッドの先頭行をクリックします。
    データ・グリッドと単一レコード・レイアウトの両方にはデータベースからのデータが含まれています。
    データベースのデータが、データ・グリッドから単一レコード・レイアウトに転送されました。「Key」フィールドの値が、データベースに追加された行の数を反映しており、ご使用の Web ページの値とはおそらく一致しないことに注意してください。

演習のチェックポイント

以下のタスクの実行方法を学習しました。
  • フォーマッターを作成する。
  • データ・グリッドでのユーザーの選択に応答する。
  • データ・グリッドからグリッド・レイアウトにデータを転送する。
  • コードをコメント化およびコメント解除する。
  • Rich UI アプリケーションからサービスにアクセスする。

次の演習では、Rich UI ハンドラーのコードを完成させます。

< 前へ | 次へ >

フィードバック