前言
繼續接著上一篇的webix入門:https://www.cnblogs.com/zc22/p/15912342.html。今天完成剩下兩個最重要的控制元件,表單和表格的使用。掌握了這兩個,整個Webix就入門完成了,就會進入吐槽模式。
Webix 表單Form的使用
表單的初始化佈局
本章節介紹表單的獲取、設定、驗證;表單控制元件的資料繫結。
表單和一般控制元件,最大的區別,就是提供了批量操作。包括批量的設定取值、批量輸入驗證。先建立一個表單:
webix.ui({ id: 'webix_domasticparts', rows: [ { id: 'form', view: 'form', borderless: true, elements: [ { cols: [ { view: 'label', label: '無型號:', autowidth: true, }, { id: 'lb_title', name: 'lb_title', view: 'label', label: '0', width: 50, align: 'center', }, { id: 'sh_select', name: 'sh_select', view: 'switch', onLabel: "開啟", offLabel: '關閉', width: 120, value: 0 }, {}, ], }, { cols: [ { id: 'txt_input', name: "txt_input", view: 'text', width: 200, placeholder: '商家編碼', }, { id: 'btn_update', view: 'button', value: '設定', width: 150, }, {}, ], }, ], }, ] });
效果演示:
程式碼解釋:
- 程式碼建立了個基本行佈局,第一行放入一個view:form,表單控制元件。
- 表單內容預設是行佈局,使用elements,也可以使用rows,這裡需要吐槽作者,設計API的時候任意亂來,一會element,一會cell,一會rows/columns,一會options。往後這類非常low的問題會越來越多,先預告下。
- 表單的控制元件,如果需要通過方法返回集合,需要宣告name屬性。
表單資料獲取與設定
接下來就是表單繫結事件,實現設定、更新,先看程式碼:
$$('btn_update').attachEvent('onItemClick', function () { var values = $$('form').getValues(); console.log(values); values.lb_title = values.txt_input; values.sh_select = 1; $$('form').setValues(values, true); });
效果顯示:
程式碼解釋:
在輸入框輸入hello,點選設定,標籤會變成同樣內容,開關開啟。
- 獲取和設定都是通過getValues, setValues控制。
- 表單的控制元件通過attachEvent繫結點選事件
表單輸入校驗
繫結驗證方法很多,我們只分享最乾淨的一種:
webix.ui({ id: 'webix_domasticparts', rows: [ { id: 'form', view: 'form', borderless: true, elements: [ { cols: [ { view: 'label', label: '無型號:', autowidth: true, }, { id: 'lb_title', name: 'lb_title', view: 'label', label: '0', width: 50, align: 'center', }, { id: 'sh_select', name: 'sh_select', view: 'switch', onLabel: "開啟", offLabel: '關閉', width: 120, value: 0 }, {}, ], }, { cols: [ { id: 'txt_input', name: "txt_input", view: 'text', width: 200, placeholder: '商家編碼', }, { id: 'btn_update', view: 'button', value: '設定', width: 150, }, {}, ], }, ], rules: { txt_input: webix.rules.isNumber, }, }, ] }); $$('btn_update').attachEvent('onItemClick', function () { if (!$$('form').validate()) { webix.alert('輸入錯誤') return; } var values = $$('form').getValues(); console.log(values); values.lb_title = values.txt_input; values.sh_select = 1; $$('form').setValues(values, true); });
效果演示:
程式碼解釋:
- 在表單的elements節點下方,新增rules節點,裡面鍵值對繫結控制元件的驗證。webix預設內建了:
- isNotEmpty
- isNumber
- isEmail
- isChecked
- 更多參考:https://docs.webix.com/desktop__data_validation.html#validationrules
- 當然,rules節點的配置可以是自定義方法。具體不詳細解釋了。
- 呼叫form的validate方法,通過返回值判斷輸入是否正確。
小結
現在我們可以製作一個比較複雜的表單了,裡面包含了上傳、匯出等操作。先看程式碼:
<style> .warn_label .webix_el_box { color: red; font-size: 18px; font-weight: bold; } .default_label .webix_el_box { font-weight: bold; } a { color: #333; text-decoration: none; } </style> <script type="text/javascript" charset="utf-8"> const aadp_mixmode_cb = [ { id: 1, value: '自營模式', }, { id: 2, value: '淘寶國產代發', }, { id: 3, value: '淘寶全代發', }, { id: 4, value: '混採模式', }, ]; webix.ui({ id: 'webix_domasticparts', rows: [ { id: 'aadp_form', view: 'form', borderless: true, elements: [ { cols: [ { view: 'label', label: '無型號:', autowidth: true, }, { id: 'aadp_unknownpart', name: 'aadp_unknownpart', view: 'label', label: '0', width: 50, align: 'center', css: 'warn_label', }, { view: 'label', label: '無顏色:', autowidth: true, }, { id: 'aadp_unknowncolor', name: 'aadp_unknowncolor', view: 'label', label: '0', width: 50, align: 'center', css: 'warn_label', }, { view: 'label', label: '無庫存:', autowidth: true, }, { id: 'aadp_unknownstock', name: 'aadp_unknownstock', view: 'label', label: '0', width: 50, align: 'center', css: 'warn_label', }, { view: 'label', label: '零件總數:', autowidth: true, }, { id: 'aadp_totalpart', name: 'aadp_totalpart', view: 'label', label: '0', width: 50, align: 'center', css: 'default_label', }, { view: 'label', label: '總價格:', autowidth: true, }, { id: 'aadp_totalprice', name: 'aadp_totalprice', view: 'label', label: '0', width: 180, align: 'center', css: 'default_label', }, { view: 'label', label: '代發價格:', autowidth: true, }, { id: 'aadp_totaldiscount', name: 'aadp_totaldiscount', view: 'label', label: '0', width: 180, align: 'center', css: 'default_label', }, { id: 'aadp_unknownpart_cb', name: 'aadp_unknownpart_cb', view: 'switch', onLabel: "未知零件", offLabel: '未知零件', width: 120, value: 0 }, { id: 'aadp_unknowncolor_cb', name: 'aadp_unknowncolor_cb', view: 'switch', onLabel: "未知顏色", offLabel: '未知顏色', width: 120, value: 0 }, { id: 'aadp_unknownstock_cb', name: 'aadp_unknownstock_cb', view: 'switch', onLabel: "無庫存", offLabel: '無庫存', width: 120, value: 0 }, {}, ], }, { cols: [ { id: 'aadp_mixmode_cb', name: "aadp_mixmode_cb", view: 'richselect', label: '商家選擇', width: 250, options: [], }, { id: 'aadp_uploadsellercode', name: "aadp_uploadsellercode", view: 'text', width: 200, placeholder: '商家編碼', }, { id: 'aadp_reupload', view: 'uploader', value: '上傳零件表', inputName: 'file', width: 150, css: 'webix_normal' }, { id: 'aadp_download', view: 'button', value: '匯出零件表', autowidth: true, }, { id: 'aadp_createorder', view: 'button', value: '生成訂單', autowidth: true, css: 'webix_primary' }, { id: 'aadp_designcode', name: "aadp_designcode", view: 'text', width: 250, label: '零件編碼', labelAlign: 'right', }, { id: 'aadp_search', view: 'button', value: '搜尋', autowidth: true, }, {}, ], }, ], }, ] }); // 設定載入中特效 webix.extend($$("webix_domasticparts"), webix.ProgressBar); // 程式碼設定下拉框 $$('aadp_mixmode_cb').define('options', aadp_mixmode_cb); $$('aadp_mixmode_cb').refresh(); $$('aadp_mixmode_cb').setValue(2); // 程式碼設定上傳元件 $$('aadp_reupload').define('formData', function () { var formval = $$('aadp_form').getValues(); return { mixmode: formval.aadp_mixmode_cb, sellercode: formval.aadp_uploadsellercode, }; }); $$('aadp_reupload').define('upload', 'http://localhost:8001/sso/page/upload'); $$('aadp_reupload').refresh(); $$('aadp_reupload').attachEvent('onFileUploadError', function (file, err) { console.error(file, err); $$('webix_domasticparts').hideProgress(); // 做一些補救措施,然後自動再上傳 $$('aadp_reupload').send(); }); $$('aadp_reupload').attachEvent('onAfterFileAdd', function () { $$('webix_domasticparts').showProgress({ type: 'icon', delay: 1000, }); }); $$('aadp_reupload').attachEvent('onFileUpload', function (file, response) { console.log(response); }); // 下載檔案 $$('aadp_download').attachEvent('onItemClick', function (e) { window.open(createRequestUrl('/wxss/moc/analysis/auth_exportbricklinkdomastic?orderNo=' + orderno)); }); </script>
服務端程式碼:
@RequestMapping("/upload") @ResponseBody public ApiResponseBody upload(String name, @RequestParam("file") MultipartFile file) { return ApiResponseBody.success(file.getOriginalFilename().toLowerCase()); } // 管理員國產零件匯出
@GetMapping("/analysis/auth_exportbricklinkdomastic") @ResponseBody public ApiResponseBody authExportBricklinkDomastic(String orderNo, HttpServletResponse response) throws Exception {
// 這裡新增下載的資料組裝,filename等
try { response.setHeader("content-type", "application/octet-stream"); response.setContentType("application/octet-stream"); // 下載檔案能正常顯示中文 response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); OutputStream os = response.getOutputStream(); // 資料寫入返回 System.out.println("Download successfully!"); return null; } catch (Exception e) { System.out.println("Download failed!"); return null; } finally { wb.close(); } }
效果如下:
Label關鍵點說明:
- 如果要修改label的表現形式,需要增加css的屬性,這是個非常常用的功能,但是這裡有個巨坑,需要按照webix控制元件皮膚去改,改成:.warn_label .webix_el_box,原因是如果沒這個css宣告,會被官方的css覆蓋了,導致一直改不成功。
- 再分享一個巨坑,一旦用了自己的css屬性,設定了字型的大小等,會導致label的自動調整佈局resize() 全部失效,對不齊。因為官方用了預設的css去計算label的部局尺寸。
- 從這裡開始,大家應該可以理解到這個webix框架會有多爛。繼續。
Uploader關鍵點說明:
- 使用上傳控制元件,宣告一個view:'uploader'的控制元件,他本質和button基本一樣。同時要宣告上傳二進位制的名字inputName: 'file',後臺才能用file去接:@RequestParam("file")
- 動態繫結上傳地址,需要使用define('upload'這個最原始的方法,再refresh()。又是個無語的地方。
- 同理,動態修改提交的formData,也需要使用define,然後使用方法返回執行時資料。
- 上傳元件如果需要程式碼再次提交,使用send()方法。比如上傳的時候,服務端返回登入超時,那麼前端再做一次登入,然後直接再次上傳。
- 上傳元件幾個關鍵事件:onAfterFileAdd、onFileUploadError、onFileUpload
其他說明:
- 如果要使用載入遮罩,需要擴充套件控制元件webix.extend,對控制元件增加webix.ProgressBar,然後就可以呼叫對應的showProgress, hideProgress。這是個透明的懸浮窗,可以遮擋使用者操作行為,非常常用,但是webix竟然特麼沒有提供基礎loading方法。
- 動態修改下拉框的資料,同樣要非常弱智的使用define('options的方式,修改控制元件配置,再refresh。沒有提供一般性的繫結資料介面。
- 要實現檔案下載,建議使用window.open的方式。不然報錯或者在iframe下,會有各種奇怪不爽問題。
由於webix的坑實在多如天上繁星,接下里的datatable的坑數會翻倍。所以我們們新開一篇繼續。今天的分享完畢!
本文所有程式碼在這裡可以下載:
連結: https://pan.baidu.com/s/1jRk6Zo6YtIvNza-8I6rOtA
提取碼: eq2k
也歡迎大家關注我們們公眾號:辰同學技術 微信公眾號,同樣會分享各種技術10分鐘從入門到吐槽: