SpringBootで作っているアプリに、テーブルメンテナンス画面が必要になったので、w2uiで作ってみる事にしました。
[blogcard url=”http://w2ui.com/web”]
テーブルメンテナンス画面といえば、一覧表示があって、選択したら登録フォームが表示されて、とか基本的な構成はどのテーブルも似たようなものですよね。w2uiのグリッドとフォームを使い、使いまわし出来るようjavascriptに機能を纏め、html側にテーブル固有の個別設定を寄せる事で、いろんなテーブルに対応出来るような形にしていきます。
w2uiのformは、urlを指定するとthis.save()でフォームをPOSTしてくれるようなのですが、ちょっと扱いにくいのでsaveを使わずにjsonでPOSTするようにしました。
eclipse上のリソース構成はこんな感じです。

javascriptです。ちょっと変更後のUIの動きがアバウトではありますが。。
//編集表示
function showEditForm(isEdit){
$('#data-form').show();
$('#data-grid').hide();
w2ui['data_form'].clear();
w2ui['data_form'].header = uiName;
if(isEdit){
var sel = w2ui['data_grid'].getSelection();
if (sel.length == 1) {
var record = w2ui['data_grid'].get(sel[0]);
w2ui['data_form'].record = record;
}
}
w2ui['data_form'].refresh();
}
//一覧表示
function showGrid(){
$('#data-grid').show();
$('#data-form').hide();
$.ajax({
headers:{ "Accept":"text/html,application/xhtml+xml,application/xml,application/json",},
url:gridURL})
.fail((jqXHR, textStatus, errorThrown) => {
if( jqXHR.status == 404 ){
w2alert('該当するデータはありません'+ jqXHR.responseText, uiName);
}else{
w2alert('データが取得出来ませんでした。 ' + jqXHR.status + jqXHR.responseText, uiName);
}
})
.done((data, textStatus, jqXHR) => {
if(data == ""){
w2alert('該当する情報はありません', uiName);
return;
}
var json=JSON.parse(data);
var idx = 0;
if(!Array.isArray(json)){
json = JSON.parse('[' + JSON.stringify(json) + ']');
}
for(var item of json){
idx++;
item['recid']=idx;
}
w2ui['data_grid'].clear();
w2ui['data_grid'].records = json;
w2ui['data_grid'].refresh();
});
}
w2utils.locale({
"phrases" : {
"Save": "閉じる",
"Hide": "隠す",
"Add New": "追加",
"Edit": "編集",
"Delete": "削除",
"Confirmation": "確認",
"Yes": "はい",
"No": "いいえ",
"Reload data in the list": "一覧を再表示します",
"Edit selected record": "選択した設定を編集します",
"Required field": "入力必須項目です",
"Add new record": "新規に設定を追加します",
"Delete selected records": "選択した設定を削除します",
"Are you sure you want to delete selected records?": "選択した設定を削除します。よろしいですか?"
}
});
//更新要求
function ajaxRequest(url, method, JSON, msg){
var deferred = new $.Deferred();
w2confirm( msg +'します。よろしいですか?')
.yes(function () {
$.ajax({
type: method,
url: url,
data: JSON,
contentType: 'application/JSON',
dataType : 'JSON',
scriptCharset: 'utf-8',
})
.fail((jqXHR, textStatus, errorThrown) => {
w2alert(msg + 'に失敗しました' + jqXHR.status + jqXHR.responseText, uiName).done(function () {
deferred.resolve();
});
})
.done((data, textStatus, jqXHR) => {
w2alert(msg + 'しました', uiName).done(function () {
deferred.resolve();
});
});
});
return deferred;
}
$('#data-grid').w2grid({
header: uiName,
show: { header: true, toolbar: true, toolbarEdit: true, toolbarAdd: true, toolbarDelete: true, toolbarReload: true, toolbarColumns: false, toolbarSearch: false },
name: 'data_grid',
multiSelect : false,
onReload: function(event) {
showGrid();
},
onAdd: function (event) {
showEditForm(false);
},
onEdit: function (event) {
showEditForm(true);
},
onDelete: function (event) {
event.preventDefault();
var record = this.get(this.getSelection());
var deleteJSON = JSON.stringify(record[0]);
var deferred = ajaxRequest(formURL, 'delete', deleteJSON, '削除');
deferred.done(function(){
setTimeout(function(){showGrid()},500);
});
},
columns: gridColumns,
});
$('#data-form').w2form({
name : 'data_form',
header: uiName,
// url : formURL,
fields: formColumns,
actions: {
'更新': function (event) {
if( this.validate(true).length == 0 ){
var postData = this.record;
var postJSON = JSON.stringify(postData);
ajaxRequest(formURL, 'post', postJSON, '更新');
}
},
'キャンセル': function (event) {
showGrid();
this.clear();
}
}
});
htmlにはjsで定義済の要素とか変数を載せます。メンテ対象のテーブルが増えた場合を考慮しツールバーも入れてます。なお、項目の設定はw2uiのドキュメントを見ながら調整していきますが、結構融通が利きますね。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Customer API Tool</title>
<script src="javascript/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="javascript/w2ui-1.5.rc1.min.js"></script>
<link rel="stylesheet" type="text/css" href="css/w2ui-1.5.rc1.min.css" />
</head>
<body>
<div id="toolbar" style="padding: 4px; border: 1px solid #dfdfdf; border-radius: 3px"></div>
<div id="data-grid" style="width: 100%; height: 500px;"></div>
<div id="data-form" style="width: 100%; height: 350px;"></div>
<script type="text/javascript">
//w2ui-tablemaintenance.js グリッド設定
var uiName = "顧客設定"; // 画面表示名
var gridURL = location.href + 'customers'; //グリッド表示データ取得URL
var gridColumns = [ // グリッド項目
{ field: 'customerid', caption: '顧客ID', size: '35%' ,sortable: true, info: true},
{ field: 'customerCode', caption: '顧客契約CD', size: '35%' ,sortable: true},
{ field: 'customerName', caption: '顧客名 ', size: '130%' ,sortable: true},
{ field: 'apiUrl', caption: 'API URL', size: '100%' ,sortable: true},
{ field: 'user', caption: 'ユーザーID', size: '50%' ,sortable: true},
{ field: 'password', caption: 'パスワード', size: '40%', render: 'password', sortable: true},
{ field: 'mailadr', caption: '通知先メールアドレス', size: '100%' ,sortable: true},
{ field: 'insdate', caption: '作成日時', size: '60%' ,sortable: true},
{ field: 'updddate', caption: '更新日時', size: '60%' ,sortable: true},
];
//w2ui-tablemaintenance.js フォーム設定
var formURL = location.href + 'customers'; //フォーム更新URL
var formColumns = [ //フォーム項目
{ field: 'customerid', type: 'text', required: true, html:{caption: '顧客ID', attr: 'size=5 maxlength=4'}},
{ field: 'customerCode', type: 'text', required: true, html:{caption: '顧客契約CD', attr: 'size=10 maxlengh=8'}},
{ field: 'customerName', type: 'text', required: true, html:{caption: '顧客名', attr: 'size=60 maxlengh=60' }},
{ field: 'apiUrl', type: 'text', required: true, html:{caption: 'API URL', attr: 'size=60 maxlengh=60' }},
{ field: 'user', caption: 'login ID', type: 'text', required: true, html:{caption: 'login ID', attr: 'size=20 maxlengh=20' }},
{ field: 'password', caption: 'password', type: 'password', required: true, html:{caption: 'password', attr: 'size=20 maxlengh=20' }},
{ field: 'mailadr', caption: '通知先メールアドレス', size: '100%' ,sortable: true, html:{caption: '通知先メールアドレス', attr: 'size=40 maxlengh=40' }},
];
//ツールバー
$('#toolbar').w2toolbar({
name: 'toolbar',
tooltip: 'right',
items: [{ type: 'break' },{ type: 'html', html: '<strong><font color="red">Customer API Tool</font></strong>'},
{ type: 'button', id: 'customerBT', group: '1',text: '顧客設定', icon: 'fa-wrench', tooltip: '顧客設定を参照・編集します',
onClick: function (event) { showGrid();}},
{ type: 'break' },
]
});
$(document).ready(function(){
showGrid();
});
</script>
<script type="text/javascript" src="javascript/w2ui-tablemaintenance.js"></script>
</body>
</html>
最後にというか、本来なら最初にですがSpringBoot側は、w2uiの項目名と一致するエンティティクラス(ここではCustomer)と、CrudRepositoryを継承したインターフェースCustomerRepositoryを用意し、RESTコントローラーからアクセスさせるようにします。
@CrossOrigin
@RestController
public class CustomerController {
private CustomerRepository repository;
@Autowired
public CustomerController(CustomerRepository repository) {
this.repository = repository;
}
/**
* 顧客情報取得
* */
@RequestMapping(value="/customers",method = RequestMethod.GET)
private String getCustomers() throws Exception{
ObjectMapper jsonMapper = new ObjectMapper();
List<Customer> list = new ArrayList<>();
StreamSupport.stream(Spliterators.spliteratorUnknownSize(repository.findAll().iterator(), 0),false).forEach(o -> list.add(o));
return jsonMapper.writeValueAsString(list);
}
/**
* 顧客情報取得
* @param id customer id
* */
@RequestMapping(value="/customers/{id}",method = RequestMethod.GET)
private String getCustomers(@PathVariable(name = "id", required = false) String id
) throws Exception{
ObjectMapper jsonMapper = new ObjectMapper();
return jsonMapper.writeValueAsString(repository.findById(id));
}
/**
* 顧客情報更新
* */
@RequestMapping(value="/customers",method = RequestMethod.POST)
private Customer setCustomers(@RequestBody Customer customer) throws Exception{
if(customer.getInsdate()== null){
customer.setInsdate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
customer.setUpdddate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
return repository.save(customer);
}
/**
* 顧客情報削除
* */
@RequestMapping(value="/customers",method = RequestMethod.DELETE)
private String deleteCustomers(@RequestBody Customer customer) throws Exception{
repository.deleteById(customer.getCustomerid());
return customer.getCustomerid();
}
}
で、出来た画面です。


なお、今回セキュリティ要件は考慮していません。。