EditableHtmlTableクラスの解説
売上伝票等の入力フォームには複数行の明細入力がつきものです。しかし、これをWebで実装するのはなかなか面倒です。これを簡単に実装するためのクラスがEditableHtmlTableクラスです。
以下の通りEditableHtmlTableのインスタンスを配置したフォームクラスを作成します。
package pagesample.page;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import dataforms.annotation.WebMethod;
import dataforms.controller.Form;
import dataforms.controller.JsonResponse;
import dataforms.controller.Response;
import dataforms.field.base.FieldList;
import dataforms.field.base.TextField;
import dataforms.field.common.SortOrderField;
import dataforms.field.sqltype.DateField;
import dataforms.field.sqltype.IntegerField;
import dataforms.field.sqltype.NumericField;
import dataforms.htmltable.EditableHtmlTable;
import dataforms.validator.ValidationError;
import net.arnx.jsonic.JSON;
/**
* 編集可能テーブルフォーム。
*
*/
public class EditableHtmlTableForm extends Form {
/**
* Logger.
*/
private static Logger logger = Logger.getLogger(EditableHtmlTableForm.class);
/**
* コンストラクタ。
*/
public EditableHtmlTableForm() {
super(null);
FieldList flist = new FieldList();
flist.addField(new SortOrderField()).setComment("表示順");
flist.addField(new TextField("text1")).setComment("テキスト");
flist.addField(new IntegerField("integer1")).setComment("整数");
flist.addField(new NumericField("numeric1", 10, 2)).setComment("数値(10,2)");
flist.addField(new DateField("date1")).setComment("日付");
EditableHtmlTable list = new EditableHtmlTable("list", flist);
this.addHtmlTable(list);
}
@WebMethod
public Response submit(final Map<String, Object> p) throws Exception {
this.methodStartLog(logger, p);
List<ValidationError> errlist = this.validate(p);
Response ret = null;
if (errlist.size() == 0) {
Map<String, Object> d = this.convertToServerData(p);
logger.debug("d=" + JSON.encode(d));
ret = new JsonResponse(JsonResponse.SUCCESS, "");
} else {
ret = new JsonResponse(JsonResponse.INVALID, errlist);
}
this.methodFinishLog(logger, ret);
return ret;
}
}
このフォームクラスのインスタンスをPageクラスに配置します。このページクラスは開発ツールでページクラスのみを作成し、コンストラクタの太字部分を追記しています。
package pagesample.page;
import dataforms.app.page.base.BasePage;
import dataforms.dao.Dao;
import dataforms.dao.Table;
/**
* ページクラス。
*/
public class EditableHtmlTablePage extends BasePage {
/**
* コンストラクタ。
*/
public EditableHtmlTablePage() {
this.addForm(new EditableHtmlTableForm());
}
・・・ 中略 ・・・
}
このソースをコンパイルし解発ツールでHTMLを作成した後、太字部分の<button></button>タグを追加します。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="mainDiv">
<form id="editableHtmlTableForm">
<div class="formHeader">xxx</div>
<table class="responsive">
<tbody>
</tbody>
</table>
<div class="hScrollDiv">
<table id="list" class="editableTable">
<thead>
<tr>
<th colspan="2" nowrap>
</th>
<th nowrap>
No.
</th>
<th>
テキスト
</th>
<th>
整数
</th>
<th>
数値(10,2)
</th>
<th>
日付
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="buttonColumn">
<input type="button" id="list[0].addButton" value="+"/>
</td>
<td class="buttonColumn">
<input type="button" id="list[0].deleteButton" value="-"/>
</td>
<td style="text-align: right;" class="rowno">
<span id="list[0].no"></span>
</td>
<td>
<input type="text" id="list[0].text1" />
<input type="hidden" id="list[0].sortOrder" />
</td>
<td>
<input type="text" id="list[0].integer1" />
</td>
<td>
<input type="text" id="list[0].numeric1" />
</td>
<td>
<input type="text" id="list[0].date1" />
</td>
</tr>
</tbody>
<tfoot>
<tr>
<th class="buttonColumn">
<input type="button" id="list.addButton" value="+"/>
</th>
<th colspan="6">
</th>
</tr>
</tfoot>
</table>
</div>
<button type="button" id="sendButton">送信</button>
</form>
</div>
</body>
</html>
EditableHtmlTableに対応する<table></table>タグの特徴は、行の追加/削除ボタンが生成されていることです。また<tfoot></tfoot>タグが生成され、最後尾に行を追加するボタンが生成されています。
次に、EditableHtmlTableForm.javaに対応するEditableHtmlTableForm.jsを作成します。開発ツールでEditableHtmlTableForm.jsを自動生成した後、以下の太字部分を追記します。
/**
* @fileOverview {@link EditableHtmlTableForm}クラスを記述したファイルです。
*/
/**
* @class EditableHtmlTableForm
*
* @extends Form
*/
EditableHtmlTableForm = createSubclass("EditableHtmlTableForm", {}, "Form");
/**
* HTMLエレメントとの対応付けを行います。
*/
EditableHtmlTableForm.prototype.attach = function() {
Form.prototype.attach.call(this);
var thisForm = this;
this.find("#sendButton").click(function() {
thisForm.send();
});
};
/**
* 送信処理。
*/
EditableHtmlTableForm.prototype.send = function() {
this.submit("submit", function(r) {
logger.log("r=" + JSON.stringify(r));
});
};
下図は、このページを表示し、3行データを入力したところです。
このフォームを送信すると、以下のログのようにテーブルの各行の入力値のマップが入ったリストが送信されます。
2018-05-08 23:26:56,397 DEBUG EditableHtmlTableForm - d={
"list":[
{"text1":"aaa","sortOrder":0,"integer1":10,"numeric1":30.0,"date1":1525100400000}
,{"text1":"bbb","sortOrder":1,"integer1":20,"numeric1":20.0,"date1":1525186800000}
,{"text1":"ccc","sortOrder":2,"integer1":30,"numeric1":10.0,"date1":1525273200000}
]
}
伝票の入力時に、明細の入力順を変えたいことがあります。EditableHtmlTableは行をドラッグすることにより簡単に入力順を変更することができます。
EditableHtmlTableForm.javaのコンストラクタでは、EditableHtmlTableのインスタンス作成時にSortOrderFieldというフィールドを設定しています。このフィールドに対応するHTMLタグは<input type="hidden" id="list[0].sortOrder" />になり、行のドラッグが完了すると自動的に表示順が設定されるようになっています。
このSortOrderFieldの値をデータベースのテーブルに保存し、読み取る際のソート順に指定すれば入力順を保存することができます。
この機能はjQuery UIのSortableを使用して実現しています。タブレットなどのタッチパネルしかない端末の場合テーブルの各行にSortableを指定してしまうと、テーブル内のテキストボックスの入力ができなくなってしまいます。そのためこのページがタッチパネルしかない端末に表示されたと判断した場合、以下のように行入替モードと入力モードを切り替えるためのチェックボックスが表示されます。
