SpringBoot+HandsOnTableで、テーブルの一覧をExcel風に編集できる画面を作成する
従業員マスタを編集するイメージです。
1.従業員マスタ
Employee.java
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
@Data
public class Employee implements Serializable {
//選択の有無
private boolean selected;
//従業員番号
private long empNo;
//従業員氏名
private String empName;
//役職
private String position;
//採用日
@JsonFormat(pattern = "yyyy/MM/dd")
private String hireDate;
public Employee() { }
public Employee(long empNo, String empName, String position, String hireDate) {
this.empNo=empNo;
this.empName=empName;
this.position=position;
this.hireDate=hireDate;
}
}
EmployeeListForm.java
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
@Data
public class EmployeeListForm implements Serializable {
List<Employee> list=new ArrayList<Employee>();
}
2.Controller
(1) 初期表示用
HeloController.java
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class HeloController {
@RequestMapping("/")
public String top() {
return "index";
}
@RequestMapping(value="/regist", method=RequestMethod.POST)
public String regist(
@ModelAttribute EmployeeListForm form,
Model model) {
model.addAttribute("form", form);
for (Employee emp: form.getList()) {
System.out.println(emp.toString());
}
return "index";
}
}
(2) HandsOnTableのData
HandsOnTableにマッピングする従業員マスタの一覧を取得するメソッド。
HeloRestController.java
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HeloRestController {
@RequestMapping("/getEmpoyeeList")
public List<Employee> getEmpoyeeList() {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
List<Employee> list = new ArrayList<>();
for (int i=0; i< 1000; i++) {
list.add(
new Employee((i+1),
"name-"+String.valueOf((i+1)),
String.valueOf(i%4 + 1),
LocalDate.now().format(dateTimeFormatter)));
}
return list;
}
}
3.html
index.html
<!DOCTYPE html>
<html lang="ja" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link th:href="@{/handsontable/handsontable.full.min.css}" rel="stylesheet" />
<script th:src="@{/webjars/jquery/3.3.1/jquery.min.js}"></script>
</head>
<body>
<input type="hidden" id="posturl" th:value="@{/getEmpoyeeList}"/>
<form id="postform" th:action="@{/regist}" method="post">
</form>
<H3>Hands on Table サンプル</H3>
<p>行を追加するには、右クリックして「上に行を挿入」を選択します<p>
<div style="height:600px;width:1000px;padding:10px;">
<div id="grid" class="handsontable"></div>
</div>
<button type="button" id="send">送信</button>
<br>
<script th:src="@{handsontable/handsontable.full.min.js}"></script>
<script th:inline="javascript">
/*<![CDATA[*/
/** HandsOnTableのコンテナ */
var container = document.getElementById('grid'); //後ほど表を展開する要素を指定
/** HandsOnTableオブジェクト */
var htable;
/** HandsOnTableのヘッダ */
var header;
/** HandsOnTableのData */
var jsondata;
/** ajaxを実行する */
function executeAjax(ajaxUrl, ajaxType, formData){
return $.ajax({
url: ajaxUrl,
type: ajaxType,
contentType:false,
processData: false,
cache: false,
data: formData,
timeout: 30000
});
}
//HandsOnTableオブジェクト作成
function createHandsOnTable(jsonData){
jsondata = jsonData;
//ヘッダを編集
header = new Array();
var count = 0;
for(key in jsondata[0]){
header[count] = key;
count++;
}
htable = new Handsontable(container, {
//以下はデータ指定と表示オプション
data: jsondata, //JsonData
// minSpareRows: 1, //表の一番下にいくつ空行を表示するか。今回は1行を空行にして表示する。
colHeaders: header, //カラムの名前を表示するかどうか colheader: true 表示/false 非表示
//カラムの名前を任意の名前にする colheader: 配列(カラム名)
columns: [
//選択
{data:"selected",type: 'checkbox'},
//従業員番号
{data:"empNo",type: 'numeric'},
//従業員氏名
{data:"empName",type: 'text'},
//採用日は、autocomplete
{
data:"position",
type: 'autocomplete',
source: ['1', '2', '3', '4'],
strict: true,
allowInvalid: false,
filter: false
},
//入社日
{data:"hireDate",type: 'date',dateFormat: 'YYYY/MM/DD'}
],
rowHeaders: true, //行番号の表示
height: 600, //テーブルの高さ
contextMenu: {
items: { row_above: {name: '上に行を挿入'}
}
}, //セルを右クリックしたときの行挿入を表示する。
columnSorting: true, //カラムのヘッダーをクリックした際に昇順、再クリックで降順にソート
enterBeginsEditing: false, //true=Enterで次の行に移動する
search: true
});
}
function postSelectedRows(form){
//HandsOnTableで選択された行をサーバにPOST送信する。
var cols = htable.countCols();
var rows = htable.countRows();
list_idx=0;
for (i=0; i< rows; i++) {
//選択しているデータのみを送信する。
if (htable.getDataAtCell(i,0)==true){
for (j=0; j< cols; j++) {
var paramname="list["+list_idx+"]." + htable.getColHeader(j);
var paramvalue= htable.getDataAtCell(i,j);
$("<input>",{
type:"hidden",
name:paramname,
value:paramvalue
})
.appendTo($(form));
}
list_idx++;
}
}
$(form).submit();
}
$(document).ready(function () {
//handsOnTableのデータをサーバからAjaxをcallして取得します。
var urladdress=$('#posturl').val();
var fd = new FormData();
executeAjax(urladdress, "post",fd)
.done(function(data, textStatus, jqXHR) {
createHandsOnTable(data);
})
.fail(function(jqXHR, textStatus, errorThrown){
console.log('通信失敗');
});
$("#send").click(function() {
postSelectedRows($('#postform'));
return false;
})
});
/*]]>*/
</script>
</body>
</html>
createHandsOnTable・・HeloRestController#getEmpoyeeListからJSONオブジェクトをAjaxで取得してHandsOnTableにデータをセットします。
postSelectedRows・・・画面上で「checkbox」をチェックした行をフォームに追加してサーバに送信します。この処理で、input要素を生成していますが、name属性は、list[].変数名とすることで、post送信(HeloController#regist)したときに、ModelAttirbuteのフォーム属性にマッピングできるようにしています。
マッピングできれば、あとはデータベースに登録するなり処理できます。
HandsOnTableは、Excel風の編集ができるので通常の入力フォームより受けがよいと考えます。
参考にしたサイト
Handsontable 使い方メモ3(カラム・セルオプション)
以上