DWR(5)

Get Ahead Ltd. – Work in Progress – Come back later.

これは動的にTableの行(row)を操作する例。これもAjaxというより、クライアントサイドでこういう操作がダイナミックにできます、という例だね。

このページをloadするとinit()が呼び出され、以下のようなコードが実行される。

function init() {
	DWRUtil.useLoadingMessage();
	update();
}

function update() {
	Demo.getAllPeople(fillTable);
}

var getName = function(person) { return person.name };
var getDoB = function(person) { return person.address }; // if we return to using dates, add .toLocaleDateString()
var getSalary = function(person) { return person.salary };
var getEdit = function(person) {
	return '<input type="button" value="Edit" onclick="readPerson('+person.id+')">';
};
var getDelete = function(person) {
	return '<input type="button" value="Delete" onclick="deletePerson('+person.id+', \''+person.name+'\')">';
};
function fillTable(people) {
	DWRUtil.removeAllRows("peoplebody");
	DWRUtil.addRows("peoplebody", people, [ getName, getDoB, getSalary, getEdit, getDelete ])
}

ページ後半のコードを見ると、getAllPeople()はPersonoオブジェクトを格納したHashMapが返されるんでしょう(本当はもっと複雑なはずだと思うけど。後述)。ここでの注目はfillTable関数で呼ばれている

  • DWRUtil.removeAllRows()
  • DWRUtil.addRows()

の2つ。まずremoveAllRows()は引数で指定されたidの子要素をすべて削除するもの。"peoplebody"は以下のように、テーブルのtbody要素を指しているので、これ以下のtr/td要素がごっそり消される。ちなみにソースを見るとtbody以外にtable, thead, tfootも指定できるようだ。

<table border="1">
<thead>
<tr>
<th rowspan="1" colspan="1">Name</th>
      <th rowspan="1" colspan="1">Address</th>
      <th rowspan="1" colspan="1">Salary</th>
      <th colspan="2" rowspan="1">Actions</th>
</tr>
</thead>
<tbody id="peoplebody">
</tbody>
</table>

次のaddRowsは複雑。機能としてはその名の通り行(row)を追加するもの。第1引数は追加先を表すid。第2引数は追加する。第3引数は第2引数で指定したデータからrowデータを作るのに使用する関数の配列。getName~getDeleteはその直前に定義されている。たとえばaddRows(ele, data, cellFuncs)を実行すると、次のような感じになるんじゃなかろうか(間違ってたらゴメン)。

for (i=0; i<data.length; i++){
    row生成;
    for (j=0; j<cellFuncs.length; j++){
        rowのj番目の要素←cellsFunc[j](data[i])
    }
    ele ← row追加
}

テーブルの下にあるテキストボックスとのやりとりにはDWRUtil.setValues()/getValues()が使われている。

しかし疑問が。このページの冒頭には

This demo stores the list of people in your session, so the editing relies on Cookies. DWR can use application, session and request scope to store beans

とある。なるほどテキストボックスの内容がテーブルに反映される。でもこれと同じ動作は「How it works」に書かれているコードだけではできない。これだと入力したデータがテーブルに反映されず毎回初期状態に戻ってしまう。クライアントサイドのJavaScriptコードには、セッションを維持するような処理は入っていないし...。良く見ると

The extra code in Demo looks like this:

だもんな。なんかサーバ側でやるんだろう。となるとDWRが呼び出すPOJOサーブレットの環境をアクセスする手段が必要。そういえばGet Ahead Ltd. – Work in Progress – Come back later.でそんな例があったな、と思って調べたらピンポン。POJOからはuk.ltd.getahead.dwr.ExecutionContext経由でsessionを取得できる。

javax.servlet.http.HttpSession session = ExecutionContext.get().getSession();

このsessionにpeopleオブジェクトをgetAttribute()/setAttribute()すれば良いみたい。一応それで同じような動きになりました。このページ(Get Ahead Ltd. – Work in Progress – Come back later.)では実際どうやっているか知らないけどw。

なおこのテーブルの動的な操作についてはGet Ahead Ltd. – Work in Progress – Come back later.にも解説あります。