前言
繼續接着上一篇的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分鍾從入門到吐槽:

