前言

继续接着上一篇的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分钟从入门到吐槽:

[入门到吐槽系列] Webix 10分钟入门 二 表单Form的使用的更多相关文章

  1. [入门到吐槽系列] Webix 10分钟入门 一 管理后台制作

    前言 本人是服务端程序员,同时需要兼职前端开发.常用的就是原生态的HTML.Javascript,也用过ExtJS.Layui.可是ExtJS变公司后非常难用.Layui上手还行,用过一段时间,会觉得 ...

  2. HTML--HTML入门篇(我想10分钟入门HTML,可以,交给我吧)

    我要正经的讲一节课,咳咳! HTML简介(废话) HTML称为超文本标记语言,是一种标识性的语言.它包括一系列标签.通过这些标签可以将网络上的文档格式统一,使分散的Internet资源连接为一个逻辑整 ...

  3. Apache Shiro系列三,概述 —— 10分钟入门

     一.介绍 看完这个10分钟入门之后,你就知道如何在你的应用程序中引入和使用Shiro.以后你再在自己的应用程序中使用Shiro,也应该可以在10分钟内搞定. 二.概述 关于Shiro的废话就不多说了 ...

  4. kafka原理和实践(一)原理:10分钟入门

    系列目录 kafka原理和实践(一)原理:10分钟入门 kafka原理和实践(二)spring-kafka简单实践 kafka原理和实践(三)spring-kafka生产者源码 kafka原理和实践( ...

  5. JavaScript 10分钟入门

    JavaScript 10分钟入门 随着公司内部技术分享(JS进阶)投票的失利,先译一篇不错的JS入门博文,方便不太了解JS的童鞋快速学习和掌握这门神奇的语言. 以下为译文,原文地址:http://w ...

  6. Markdown - Typora 10分钟入门 - 精简归纳

    Markdown - Typora 10分钟入门 - 精简归纳 JERRY_Z. ~ 2020 / 8 / 22 转载请注明出处! 目录 Markdown - Typora 10分钟入门 - 精简归纳 ...

  7. struts2官方 中文教程 系列十一:使用XML进行表单验证

    在本教程中,我们将讨论如何使用Struts 2的XML验证方法来验证表单字段中用户的输入.在前面的教程中,我们讨论了在Action类中使用validate方法验证用户的输入.使用单独的XML验证文件让 ...

  8. [入门到吐槽系列] 微信小程序 敏感违规图片检测 mediaCheckAsync,客服接口 消息推送 的各种坑分享!

    前言: 最近需要做个用户上传图片,服务端校验图片问题的需求.需要使用小程序消息推送,异步接受腾讯的图片验证回调.实在太多坑了. 相信10分钟看完本文的朋友,可以非常顺利避坑. 前期准备: 首先需要一个 ...

  9. UWP开发入门(十九)——10分钟学会在VS2015中使用Git

    写程序必然需要版本控制,哪怕是个人项目也是必须的.我们在开发UWP APP的时候,VS2015默认提供了对微软TFS和Git的支持.考虑到现在Git很火,作为微软系的程序员也不得不学一点防身,以免被开 ...

随机推荐

  1. js复制文本到剪贴板

    execCommand是document的一个方法,返回值是布尔值(true,false) true表示操作被支持,false表示操作不被支持 此方法只针对于input和textarea,对里面的内容 ...

  2. Windows 重装系统,配置 WSL,美化终端,部署 WebDAV 服务器,并备份系统分区

    最新博客文章链接 最近发现我 Windows11 上的 WSL 打不开了,一直提示我虚拟化功能没有打开,但我看了下配置,发现虚拟化功能其实是开着的.然后试了各种方法,重装了好几次系统,我一个软件一个软 ...

  3. 性能优化-使用双buffer实现无锁队列

    借助本文,实现一种在"读多写一"场景下的无锁实现方式 在我们的工作中,多线程编程是一件太稀松平常的事.在多线程环境下操作一个变量或者一块缓存,如果不对其操作加以限制,轻则变量值或者 ...

  4. 2022GDUT寒训专题一I题

    题目 题面 给一个长度为 N的数组,一个长为 K的滑动窗体从最左端移至最右端,你只能看到窗口中的 K 个数,每次窗体向右移动一位,如下图: 窗口位置 最小值 最大值 [1 3 -1] -3 5 3 6 ...

  5. 分治FFT小记🐤

    分治FFT:在 $O(n \log^2 n)$ 的时间内求出类似于 $f_i=\sum\limits_{j=0}^{i-1}g(i-j)f(j)$ 之类的递推式 思想:同 CDQ 分治的思想,先分成左 ...

  6. 幸运转轮(Cakra)

    题目描述 lxx参加了某卫视举办的一场选秀节目,凭借曼妙的舞姿和动人的歌声,他在众多idol中脱颖而出.现在在他的面前,有四个大转轮,这四个转轮将决定他能否赢得最终大奖--出道,机会只有一次!   每 ...

  7. 如何在 VS Code 中搭建 Qt 开发环境

    前言 VS Code 高大上的界面.强大的智能联想和庞大的插件市场,着实让人对他爱不释手.虽然可以更改 Qt Creator 的主题,但是 Qt Creator 的代码体验实在差劲.下面就来看看如何在 ...

  8. Win11怎么启动任务管理器?Win11启动任务管理器的四种方法

    Win11怎么启动任务管理器?小编为大家带来了Win11启动任务管理器的四种方法,感兴趣的朋友一起看看吧 任务管理器是Windows系统中一项非常实用的功能.不过在最新版Win11中,右击任务栏启动任 ...

  9. webpack学习:uni运行时代码解读一 (页面初始化加载)

    uni的vue代码是如何在微信小程序里面执行的,对此比较感兴趣所以去调试学习了一波. 准备工作 // 在vue.config.js里打开非压缩的代码 module.exports = { config ...

  10. Matplotlib 3.0 秘籍·翻译完成

    原文:Matplotlib 3.0 Cookbook 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远. 在线阅读 ApacheCN 面试求职交 ...