SpringBootで作っているアプリに、テーブルメンテナンス画面が必要になったので、w2uiで作ってみる事にしました。
テーブルメンテナンス画面といえば、一覧表示があって、選択したら登録フォームが表示されて、とか基本的な構成はどのテーブルも似たようなものですよね。w2uiのグリッドとフォームを使い、使いまわし出来るようjavascriptに機能を纏め、html側にテーブル固有の個別設定を寄せる事で、いろんなテーブルに対応出来るような形にしていきます。
w2uiのformは、urlを指定するとthis.save()でフォームをPOSTしてくれるようなのですが、ちょっと扱いにくいのでsaveを使わずにjsonでPOSTするようにしました。
eclipse上のリソース構成はこんな感じです。
javascriptです。ちょっと変更後のUIの動きがアバウトではありますが。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
//編集表示 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のドキュメントを見ながら調整していきますが、結構融通が利きますね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
<!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コントローラーからアクセスさせるようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
@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(); } } |
で、出来た画面です。
なお、今回セキュリティ要件は考慮していません。。