前編で画面デザインが完成した XPage に、経費項目の新規入力、既存項目の修正や削除といった編集機能を実装していきます。これまでの作業で作成したフォームテーブルを利用すれば、新規費用項目のデータを入力することはできますが、このままでは入力データをNotes 文書として保存することができません。そのためのボタンを追加します。ボタンを配置する場所としてフォームテーブルの下部に行を1行追加してセルをマージし、ひとつの大きなセルとします。ボタンをきれいに配置するため、セルの属性を右詰とします。用意したセルにボタンコントロールを配置し、ラベルを「追加」とします (図1) 。
図1. 「追加」ボタンの追加
ボタンが押された際に処理を実行させるためには、アクションと呼ばれるロジックをコントロールでサポートされているイベントに登録します。通常はボタンやリンクといったコントロールのイベントにアクションを登録しますが、ラベルなどその他どんなコントロールにも登録することが可能です。アクションの種類にはシンプルアクションとスクリプトによるアクションがあります。シンプルアクションとは、文章の保存や別のページへのジャンプといったよく利用されるタイプの動作が事前に定義されており、簡単なパラメータを指定するだけで利用することができるアクションです。これに対して、スクリプトによるアクションでは JavaScript などを利用したプログラムを記述することが可能なため、より細かな動作を定義することができます。ここでは2つのシンプルアクションを利用します。最初のアクションとして、「追加」ボタンを押した際に発生するイベントに、入力したデータを新規文書として保存するアクションである「文書の保存」を追加します (図2)。
図2. 「文書の保存」アクションの追加
次に2つ目のアクションとして、フォームに入力したデータをクリアして新たに次のデータを入力できるようにする処理を追加します。現在表示中のページを新規文書用に再表示するアクションである「ページを開く」を登録します (図3)。
図3. 「ページを開く」アクションの追加
これら2つのアクションの登録はイベントビューから「onclick」イベントに対して行います (図4)。アクションは登録された順に実行されますので、順番が正しくない場合には右側の矢印ボタンを使って順番を入れ替えます。これにより、「追加」ボタンをクリックすると現在フォームパネルに入力されている値が新規文書として Notes のデータベースに保存され、その後同じ XPage が次の新規文書作成のためにリセットされて再表示されるようになります。これで入力したデータを保存することができるようになりました。適当なデータを入力して「追加」ボタンを押してみてください。ビューコントロールに追加した項目が表示されます。
図4. 追加された2つのイベント
新規項目追加の機能が完成しましたので、今度は入力済み項目に対する編集機能を追加します。はじめに、ビューコントロールで既存の項目を選択するとその内容がフォームテーブルに表示されるようにします。ビューコントロールには、任意の列をリンクとして表示し、そのリンクをクリックされた際にどのような動作をするのかを指定する機能がありますので、その機能を利用します。作成したビューコントロールの「摘要」列を選択しプロパティビューの「ビューの列」タブを表示します。「列の値をリンクとして表示する」オプションをチェックし、「文書のオープンモード」を「編集」とします (図5)。「勘定科目」列も同様に設定します。
図5. 列の値をリンクとして表示
次にビューコントロール全体を選択し、プロパティビューの「ビュー」タブを表示します。「実行時に、次を使用して選択した文書を開く」として「table」 XPage を指定します (図6)。これらの設定により、「摘要」列をクリックして選択された項目の内容が、同じ XPage 上に編集モードで表示されるようになります。
図6. 文書を開くページを指定
次に、編集機能を完全なものにするために、先ほど配置したボタンコントロールの横に新たに3つのボタンコントロールを追加します。編集内容を更新する「変更」、選択した項目を削除する「削除」、編集内容を取り消す「取消」です。それぞれ、名前が表す動作を行うよう、「追加」ボタンと同様にしてシンプルアクションを登録していきます。
| ボタン | 登録するアクション |
|---|---|
| 変更 | 「文書の保存」 |
| 削除 | 「文書の削除」
|
| 取消 | 「ページを開く」
|
ここまでの操作ですべての編集機能がそろいました。最後に、用意した4つのボタンを、それぞれ利用可能な場合にのみ表示するように設定します。新規項目入力の際には「追加」ボタン、既存項目を編集中には「変更」と「削除」を切り替えて表示します。「取消」ボタンは常に有効にします。この制御を行うためにはボタンコントロールの「表示」オプションを用います。「追加」ボタンを選択し、プロパティビューの「ボタン」タブを表示します。「表示」オプション右横の◇ボタンをクリックし、「値の計算」を選択してスクリプト入力エディタを起動します。そこで「itemDocument.isNewNote()」と入力して編集を終了します。これは、現在作成中の XPage にバインドされているitemDocument データソースが新規文書かどうかを確認する JavaScript のロジックです。itemDocument データソースは本稿の前編で定義され、Notesアプリケーションの item フォームに関連付けられています。表示されている文書が新規文書であれば 「itemDocument.isNewNote()」 は true を返すので、「追加」ボタンが表示されることになります。同様に、「変更」、「削除」ボタンにもスクリプトを設定します。これら2つを表示する条件は「追加」ボタンとは反対となりますので、スクリプトは「!itemDocument.isNewNote()」となります。式の先頭に「!」が付いていることに注意してください。このように、各コントロールのほとんどのプロパティ項目に対して、静的な値やスクリプトによる動的な値を設定して、その振る舞いを制御することが可能です。
以上ですべての編集機能が完成しました (図7)。それぞれのボタンを利用してその動作を確認してみてください。
図7. 完成した4つの編集ボタン
一般的に Web アプリケーションは複数のページから成り立っており、それらのページを遷移しながら処理が行われるようになっています。XPages でもそのような Web アプリケーションを簡単に実現できます。
ここからは2つ目のページを作成していきます。最初作成した「table」 XPage と同様にして、「summary」 XPage を新規作成します。このページには、入力した費用項目を勘定科目ごとに合計して一覧表示する機能を実装します。一覧表は勘定科目の種類の数だけ行を持ちます。勘定科目は自由に追加定義可能なため、何行用意しておけばすべて表示可能なのかが事前には判りません。このような場合に用いるのが繰り返しコントロールです。繰り返しコントロールとは、その子要素として任意のコントロールを含み、コレクションタイプのデータオブジェクトとバインドされ、コレクションに含まれるデータオブジェクトの数だけその子要素を繰り返してくれるコントロールです。
最初に、作成した「summary」 XPage に繰り返しコントロールを配置します (図8)。
図8. 繰り返しコントロール
次に、繰り返しコントロールの子要素としてパネルコントロールをその内部に配置します。パネルコントロールとは、複数のコントロールをグループ化し、ひとつの要素として扱えるようにするためのコントロールです。繰り返しコントロールの子要素には通常、複数のコントロールを配置することになりますが、その扱いが容易になるようこのよう、パネルコントロールをまず配置します。次に、1行 X 2列の表コントロールをその中に配置します。この表には勘定科目名とその合計をそれぞれのセルに配置します。この1行だけの表を、繰り返しコントロールを用いて勘定科目の数だけ繰り返して配置し、全勘定科目を含む最終的な表とします。更に、2つのセルに対してそれぞれ計算結果フィールドコントロールを配置します。計算結果フィールドコントロールとは、その表示内容がスクリプトによる計算結果から決定されるコントロールです。ここでは、繰り返される行に対して、勘定科目名とその合計値を計算して動的に埋め込むために利用します。この時点での編集結果はこのようになっています (図9)。
図9. 表と計算結果フィールドが配置された繰り返しコントロール
ここからは配置したコントロールに対する各種設定を行っていきます。最初に、繰り返しコントロールに対して、データコレクションをバインドします。繰り返しコントロールを選択して、プロパティビューの「繰り返し」タブを表示し、JavaScript によるデータバインディングを選択して「繰り返し限度」と「コレクション名」の設定を行います。
図10. 繰り返しコントロールに対するデータバインディング
利用する JavaScript は以下の通りです。
var accountlist = database.getView("accountlist");
return accountlist.getAllEntries();
|
このロジックは、「accountlist」ビューに含まれるすべてのエントリーをデータコレクションとして取得します。スクリプトの入力には「スクリプトダイアログを開く」ボタンを押すと表示されるスクリプトエディタを利用します (図11)。
図11. スクリプトエディタ
これまでも、「table」 XPage を作成する際に簡単な JavaScript を利用してきました。XPages では、サーバーサイドやクライアントサイドで動作させるロジックを JavaScriptで記述し、さまざまな場所に埋め込むことができます。Domino Designer のスクリプトエディタを利用して JavaScript の入力を行います。エディタ内には常に左側に利用可能なオブジェクトや関数の一覧が表示され、コード入力時には入力補完機能も利用できます。XPagesで利用するためにNotes アプリケーションのさまざまな要素にアクセスするためのオブジェクトや関数が提供されています。サーバーサイドの JavaScript では Java のコードを呼び出したり、Notes アプリケーション内のエージェントを実行したりすることも可能です。また、従来の Notes アプリケーション開発技術者が使い慣れた@関数を JavaScript に移植した関数群も用意されています。サーバーサイドのロジックの記述には JavaScript 以外にも JSF (Java Server Faces) のEL言語を利用することもできます。これらの言語仕様の詳細に関しては、ヘルプのXPages Referenceを参照してください(英語版オンライン情報はこちら)。
次に、各行の勘定科目名とその合計を表示する計算結果フィールドコントロールにも、JavaScript によるロジックを記述していきます。表コントロールの左側のセルにある計算結果フィールドコントロールを選択し、プロパティビューの「値」タブを開きます。ここには勘定科目名を表示しますが、先ほどと同様にして JavaScript を記述します (図12)。
図12. 「勘定科目」計算結果フィールドの設定
利用する JavaScript のソースコードは以下の通りです。
return account.getDocument().getItemValueString("title");
|
先ほど、繰り返しコントロールにバインドしたコレクションデータに対して「account」という名前を指定しました。このロジックの中ではその名前を利用しています。繰り返しコントロールの中で定義されるロジックでは、繰り返されている個々のデータオブジェクトをこの名前を利用してアクセスすることができます。データオブジェクトの中から Notes 文書を取り出し、更にその中から「title」というフィールドの値を取り出しています。
同様に、表コントロールの右側のセルにある計算結果フィールドコントロールに対しても設定を行います。ここには勘定科目の合計を表示しますが、計算結果は数値となるため、「表示タイプ」や「数値の表示形式オプション」も設定します (図13)。
図13. 「合計」計算結果フィールドの設定
利用する JavaScript のソースコードは以下の通りです。
var accountTitle = account.getDocument().getItemValueString("title"); --- (1)
var itemlist = database.getView("itemlist");
itemlist.FTSearch("FIELD account containes " + accountTitle); --- (2)
var items = itemlist.getAllEntries(); --- (3)
item = items.getFirstEntry();
var total = 0;
while (item) {
total += item.getDocument().getItemValueInteger("amount"); --- (4)
item = items.getNextEntry();
}
itemlist.clear();
return total; --- (5)
|
繰り返しデータオブジェクトの「account」の中から Notes 文書を取り出し、更にその中から「title」というフィールドの値を取り出しています (1)。これが合計を求める勘定科目名です。次に、「itemlist」ビューの中から「account」フィールドの値として用意した勘定科目名を含むものをすべて検索します (2)。ヒットしたすべてのエントリーを取り出し (3)、すべてのエントリーの「amount」フィールドの値をループして合計します (4)。最後に合計値を戻して完了です (5)。
ブラウザから「summary」 XPage をアクセスして、正しく動作することを確認します (図14)。
図14. 勘定科目の合計結果
最後のロジックとして、全勘定科目の総計を計算するコントロールを追加します。先ほどと同様に、外枠として最初にパネルコントロールを配置し、その中に 1行X 2列の表コントロールを起きます。左側のセルには「総計」のラベルコントロールを、右側のセルには計算結果フィールドコントロールを配置します (図15)。
図15. 「総計」計算結果フィールドの配置
配置した計算結果フィールドコントロールで利用するJavaScript のソースコードは以下の通りです。
var itemlist = database.getView("itemlist");
var items = itemlist.getAllEntries();
item = items.getFirstEntry();
var total = 0;
while (item) {
total += item.getDocument().getItemValueInteger("amount");
item = items.getNextEntry();
}
return total;
|
先ほどの合計計算結果フィールドのものと似ていますが、こちらでは勘定科目名による検索は行わず、すべてのエントリーの合計を求めています。その他の表示設定も「合計」計算結果フィールドと同様にします。動作を確認するとこのようになります (図16)。
図16. 総計の表示
以上で合計計算のロジックがすべて完成しました。最後に、画面デザインを整えます。ページのタイトル用ラベルコントロールをページ上部に配置します。その下に合計表全体の大枠としてパネルコントロールを配置します。その中に3つの要素を配置します。1つ目として新たに1行X 2列の表コントロールを配置し、その中に「科目」ラベルコントロールと「合計金額」ラベルコントロールを配置して、表のヘッダーとします。2つ目として先ほど作成した繰り返しコントロールをドラッグ&ドロップで移動します。3つ目としても先ほど作成した総計を含むパネルをドラッグ&ドロップで移動します。以上ですべての要素がそろいました (図17)。
図17. 合計ページの総要素
最後に、文字揃えやフォントのサイズ、色などの属性を指定し、CSS のクラスを設定して完了です。利用するCSS のクラスは以下の通りです。
| コントロール | CSS クラス |
|---|---|
| 外枠パネル | border |
| ヘッダー行用表 | panelHeader |
| 繰り返し内パネル | panelRow |
| 総計行用表 | panelTotal |
最終的な実行結果はこのようになります (図18)。
図18. 最終結果
これで2つの XPage を作成しました。今度はこれらのページ間を自由に遷移できるよう、両方のページへのリンクを含むページフッターを2つの XPage に付け加えます。しかし、まったく同じ内容のフッターを付け加えるために同じ編集を2つのページに行うのは効率的ではありません。また、フッターの内容に変更を加える必要ができた場合にも、同じ修正作業を両方のページに対して行わなければなりません。このような場合に用いるのがカスタムコントロールです。カスタムコントロールとは XPage と同様、任意のコントロールを組み合わせて自由にデザインすることができる設計要素です。XPage と異なるのは、カスタムコントロールはそれ単独でブラウザからアクセスされるのではなく、標準コントロールと同様 XPage の中に配置されて利用される点です。カスタムコントロールの作成は、アプリケーションビューの「XPage」設計要素のすぐ下に表示されている「カスタムコントロール」設計要素で行います。アプリケーションビューの「カスタムコントロール」の上で右ボタンをクリックし、表示されるコンテキストメニューから「新規 カスタムコントロール」を選択します。表示されたパネルでカスタムコントロールの名前を「footer table」と入力して作成します (図19)。
図19. カスタムコントロールの作成
作成したカスタムコントロールに、1行X3列の表コントロールを配置し、左端のセルにロゴを表示するためイメージコントロールを、残りの2つのセルに2つの XPage へのリンクを表示するようリンクコントロールを配置します。イメージコントロールを配置する際には、どのリソースを利用するのかを指定します。ここでは、本稿の前編の操作であらかじめインポートしておいたロゴのイメージを指定します (図20)。
図20. ロゴの配置
2つのリンクコントロールには、表示するラベルとクリックしたときに開く XPage を指定します。これらの設定は、プロパティビューの「リンク」タブで、「ラベル」に表示ラベルを、「オプション」の中の「オープンページ」にリンクする XPage を選択します (図21)。ここでは以下のように2つのリンクコントロールがそれぞれ別の XPage を指し示すように設定します。
| リンクコントロール | ラベル | オープンページ |
|---|---|---|
| 中央のセル | 入力画面へ | table |
| 右端のセル | 合計画面へ | summary |
図21. リンクコントロールの設定
編集の結果はこのようになります (図22)。
図22. 完成した「footer」カスタムコントロール
完成したカスタムコントロールはコントロールビューの一番下に表示されるようになります (図23)。
図23. コントロールビュー内のカスタムコントロール
次に、作成したカスタムコントロールを2つの XPage に配置します。
他の標準コントロール同様、ドラッグ&ドロップ操作で XPage に配置することができます。2つの XPage の最下部に同じように配置します。実行結果はこのようになります (図24)。
図24. フッターが配置された XPage
Web 2.0 スタイルのインターフェースにはさまざまな特徴がありますが、その中の典型的なものとして、ページの部分更新の機能とタイプアヘッドの機能を挙げることができます。XPages では設定オプションを指定するだけで、これらの機能を簡単に利用することができます。
タイプアヘッドの機能とは、入力フィールドに一部の文字列を入力するだけで、該当する入力値の候補を一覧表示しユーザーのデータ入力をサポートしてくれる機能です。新規費用項目の摘要を入力する際に、既に入力したことのある摘要をタイプアヘッドとして検索表示してくれるようにしてみましょう。「table」 XPage を表示し、「memo」編集ボックスを選択します。プロパティビューの「タイプアヘッド」タブを表示し、「タイプアヘッドを有効化」チェックボックスを選択してタイプアヘッドを有効にします (図25)。
図25. タイプアヘッドの設定
表示される候補は、静的な値リストを指定することもできますし、スクリプトにより動的に計算することも可能です。ここでは、以下の JavaScript を設定し動的に値リストを取得します。
@DbColumn(@DbName(), "itemlist", 3) |
このスクリプトは、現在のデータベースの「itemlist」ビューの3番目の列に表示されるすべての値を求めるものです。これにより、既に入力されているすべての費用項目の摘要がタイプアヘッドされる文字列の候補となります。ブラウザからアクセスして、動作を確認してみましょう (図26)。
図26. タイプアヘッドの実行例
次に、ページの部分更新の機能を利用してみます。表示中の Web ページで表示内容の更新が必要になった場合、通常はリロードによりページ全体の再描画を行います。しかし部分更新の手法を使うと、ページのリロードは行わずに必要最小限の部分のみを再描画します。ページをリロードしないためにネットワークへの負荷が少なく、画面更新が短時間で行える上にユーザーエクスペリエンスもより自然なものとなります。
ここでは「科目ごとの合計金額」のページに含まれる「総計」の表示のオン・オフを、部分更新の手法で切り替えられるようにアプリケーションを拡張します。切り替えはチェックボックスで指定するようにします。
「summary」 XPage を表示し、合計を表示しているパネルコントロールのすぐ下にチェックボックスコントロールを配置します。プロパティビューの「チェックボックス」タブで、「名前」と「ラベル」を指定します (図27)。名前は、スクリプトの中や他のコントロールからのアクセスのために必要となります。
図27. チェックボックスコントロールの設定
このチェックボックスをクリックした際に、総計を表示しているパネルコントロールを部分更新するように指定します。部分更新の対象を指定できるようにするため、パネルコントロールに名前を付けます。パネルコントロールを選択し、プロパティビューの「パネル」タブで「名前」に「tableTotal」と入力します (図28)。
図28. パネルコントロールの名前
次に、パネルコントロール内にある総計を表示している表コントロールを選択します。プロパティビューの「表」タブで「表示」の値を、チェックボックスの値に応じて切り替えるように、JavaScript を利用して設定します (図29)。スクリプトエディタを起動するためには、右端に表示されている菱形をクリックし、表示されるメニューから「値の計算」を選択します。
図29. 表コントロールの表示制御
ここで記述する JavaScript のソースコードは以下の通りです。
getComponent("optionTotal").value == "true"
|
getComponent() は XPages が用意している関数で、名前を指定してコントロールオブジェクトを取得するためのものです。この JavaScript により、先ほど用意したチェックボックスがチェックされていれば表示を行い、チェックされていなければ表示しないという設定となります。
最後に、チェックボックスをクリックした際にこのパネルコントロールの部分だけ部分更新をする設定を行います。チェックボックスコントロールを選択し、イベントビューを表示します。「onclick」イベントの設定として、パネルコントロールを指定した部分更新を指定します (図30)。
図30. 部分更新の設定
最後に、ブラウザからこの XPage をアクセスしてみます。チェックボックスをクリックするたびに総計の表示・非表示が切り替わること、その際にページのリロードが発生しないことを確認してください (図31)。
図31. 総計表示の切り替え
ここで注意するのは、チェックボックスの値に応じて表示設定を切り替えているのは表コントロールであるのに対して、部分更新の対象として指定しているのはその表コントロールを含む1つ上位のパネルコントロールである点です。部分更新の対象も表コントロールを直接指定すればよさそうにも思えますが、そのようにした場合、非表示の状態ではコントロールそのものがページ上に存在しなくなるため、部分更新の対象として指定した名前も存在しなくなってしまいます。その結果、非表示から表示に切り替える際、名前が見つからないというエラーとなってしまいます。そのため、この例のような表示・非表示を部分更新で行う場合には、その対象として必ず存在するより上位のコントロールを指定するようにします。表示の制御ではなく内容の更新を行うような場合にはこのような問題は発生しないため、直接対象を指定することができます。
Web アプリケーションは一般的に複数のページで構成され、通常ページ間を遷移してもセッション情報としてその状態が保存されます。今回作成したページでは、セッション情報保存のための指定が行われていないため、ページ間遷移の際に「総計を表示する」のオプションは保存されず、入力画面と合計画面を遷移すると設定がリセットされてしまいます。そこで、その情報をセッション情報として保存されるようにする方法を紹介します。チェックボックスコントロールを選択し、プロパティビューの「データ」タブを表示します。ここでは、コントロールの値をどこへどのようにバインドするのかを指定します。「詳細」オプションを選択した後、「使用」として「スコープ変数」を、「範囲」として「セッションの範囲」を指定し、変数名を「optionTotal」と定義します (図32)。
図32. セッション情報の保存
これにより、チェックボックスコントロールの値(選択・非選択の状態)が、セッション単位で有効なスコープ変数「optionTotal」に保存されるようになります。チェックボックスをクリックして選択・非選択を切り替えた際には、その結果がスコープ変数「optionTotal」に代入され、逆に、「summary」 XPage が更新される際には、スコープ変数「optionTotal」の値に基づいて表示されるチェックボックスの状態が決定されます。これにより、入力画面と合計画面を遷移しても、「総計を表示する」オプションが正しく保持されるようになります。
ここでは単純に、コントロールをスコープ変数に直接バインドしましたが、JavaScript によるプログラムで動的に計算した結果をバインドすることも可能です。また、セッションの範囲で有効なスコープ変数は他のページに遷移した後でも有効ですので、あるページでの入力結果を別のページで参照して処理を行うこともできます。その際、セッションの範囲で有効なスコープ変数は
sessionScope.optionTotal |
といった形式で指定します。この変数はJavaScript のプログラム内で参照可能です。「sessionScope」がセッション内で常に有効になるオブジェクトであり、すべてのセッションの範囲で有効なスコープ変数はそのプロパティとして保存されます。XPage で利用可能なスコープ変数には以下の種類があり、保存したい値の種類に応じて適切なものを選択して利用します。
| 種類 | 有効範囲の説明 | プログラムで参照する際のオブジェクト |
|---|---|---|
| アプリケーションの範囲 | アプリケーションが存在する限り有効。異なるセッション間でも保存される。 | applicationScope |
| セッションの範囲 | 1回のセッションを通じて有効。異なるセッション間では保存されない。 | sessionScope |
| 要求の範囲 | 1回のリクエスト(サーバーへのサブミットとそのレスポンス)の間のみ有効。 | requestScope |
| 表示の範囲 | 1つのページ内でのみ有効。ページを遷移すると無効となる。 | viewScope |
前編・後編を通じて、XPages を用いた Web 2.0 スタイルの Web アプリケーション開発の方法を紹介しました。GUI エディタを利用して簡単に画面デザインが行えることに加えて、画面上の入力データと Notes 文書を結び付けて編集すること、JavaScript を利用して Notes のデータにアクセスしながら画面更新を行うロジックを組み込めること、タイプアヘッドや部分更新といった Web 2.0 スタイルのインターフェースが簡単に利用できることなどを理解していただけたと思います。従来の Domino でも Web アプリケーションの開発は可能でしたが、XPages を利用することで、最新のユーザーエクスペリエンスを持つ、より美しい画面デザインのアプリケーションを、従来よりもはるかに簡単な方法で実現できることができます。皆さんも、ぜひ一度 XPages を用いたアプリケーション開発に挑戦してみてください。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| 参考ファイル | journal.nsf | 448KB | HTTP |
- IBM Lotus Notes/Domino 8.5 におけるアプリケーション開発
- IBM Lotus Notes ヘルプ (IBM Lotus Notes/Domino に同梱)
- IBM Lotus Domino and Notes Information Center (英語)
- Domino Designer Wiki (英語)