始于 layui 的一个多选解决方案,前身 formSelects, 由于渲染速度慢, 代码冗余, 被放弃了。xm-select使用了新的开发方式, 利用preact进行渲染, 大幅度提高渲染速度, 并且可以灵活拓展。
来源:xm-select 开源文档
运行环境配置
js/jquery.2.14.js,实现对远程搜索API接口ajax的调用;
js/layui/layui.js,插件运行环境;
js/layui/xm-select.js,下拉多选插件
<script src="js/jquery.2.14.js" charset="utf-8"></script> <!--layui封装库--> <script src="js/layui/layui.js" charset="utf-8"></script> <link rel="stylesheet" href="js/layui/css/layui.css"> <script src="js/layui/xm-select.js" charset="utf-8"></script>
HTML容器
<div class="layui-input-inline"> <div id="demo1" class="xm-select-demo" style="width: 200px;"></div> </div> <div class="layui-input-inline"> <div id="btn" class="layui-btn layui-btn-normal">查询</div> </div>
核心代码
配置项
var demo1 = xmSelect.render({ el: '#demo1', tips: '选择ITEM',//选项提示文字 radio: true,//单选 paging: true,//是否翻页 pageSize: 10,//每页数量 filterable: true,//搜索模式 remoteSearch: true,//远程搜索 remoteMethod: function (val, cb, show) { //远程数据接口调用 })
远程数据接口
- 使用$.get获取远程数据,由于远程数据使用的非xm-select格式化数据
data: [ {label: '张三', id: 1, group: 1}, {label: '李四', id: 2, group: 1}, {label: '王五', id: 3, group: 2}, ]
为此需要将远程数据进行结构化数据的循环输出。当然,官网也提供了自定义属性prop:
prop: { name: 'label', value: 'id', },
即数据库返回的并不是name和value, 也许你提交的时候不止name和value, 需要根据自己需要的数据格式进行自定义。本案例由于需要对数据进行选择和排除禁用两项功能,使用数据循环方案予以解决。
使用selected属性
默认选中项,在数据后台编辑状态时使用或者在系统初始化默认使用。
data: [ {name: '水果', value: 1, selected: true}, ]
使用disabled属性
禁用项,即该状态下的选项无法被选择使用。
data: [ {name: '水果', value: 1, disabled: true}, ]
远程数据回调的数据格式处理
var selData = "", disData = '43725,43726,45327'; if (res[i].itemid == selData) { data.push({name: listName, value: res[i].itemid, selected: true}) } else if (disData.indexOf(res[i].itemid) > -1) { data.push({name: listName, value: res[i].itemid, disabled: true}) } else { data.push({name: listName, value: res[i].itemid}) }
远程核心代码
$.get('./api/api.php?act=getItem&token=3cab7ce4142608c0f40c785b5ab5ca24', { name: val, keys: '安防设备' }, function (res) { var data = []; var selData = "", disData = '43725,43726,45327'; for (var i = 0; i < res.length; i++) { var listName = res[i].name + "|" + res[i].itemid; if (res[i].itemid == selData) { data.push({name: listName, value: res[i].itemid, selected: true}) } else if (disData.indexOf(res[i].itemid) > -1) { data.push({name: listName, value: res[i].itemid, disabled: true}) } else { data.push({name: listName, value: res[i].itemid}) } } console.log(data); cb(data); }, 'json');
获值
$("#btn").click(function () { var selectArr = demo1.getValue(); console.log(selectArr[0].name); })
远程数据字段展示
{ "itemid": "43725", "type": "0", "snmp_oid": "", "hostid": "10084", "name": "百度|www.baidu.com", "key_": "ping.host[www.baidu.com]", "delay": "1m", "history": "30d", "trends": "30d", "status": "0", "value_type": "0", "trapper_hosts": "", "units": "", "formula": "", "logtimefmt": "", "templateid": "0", "valuemapid": "0", "params": "", "ipmi_sensor": "", "authtype": "0", "username": "", "password": "", "publickey": "", "privatekey": "", "flags": "4", "interfaceid": "1", "description": "", "inventory_link": "0", "lifetime": "30d", "evaltype": "0", "jmx_endpoint": "", "master_itemid": "0", "timeout": "3s", "url": "", "query_fields": [], "posts": "", "status_codes": "200", "follow_redirects": "1", "post_type": "0", "http_proxy": "", "headers": [], "retrieve_mode": "0", "request_method": "0", "output_format": "0", "ssl_cert_file": "", "ssl_key_file": "", "ssl_key_password": "", "verify_peer": "0", "verify_host": "0", "allow_traps": "0", "uuid": "", "state": "0", "error": "", "hosts": [ { "hostid": "10084", "proxy_hostid": "0", "host": "Zabbix server", "status": "0", "lastaccess": "0", "ipmi_authtype": "-1", "ipmi_privilege": "2", "ipmi_username": "", "ipmi_password": "", "maintenanceid": "0", "maintenance_status": "0", "maintenance_type": "0", "maintenance_from": "0", "name": "Zabbix server", "flags": "0", "templateid": "0", "description": "", "tls_connect": "1", "tls_accept": "1", "tls_issuer": "", "tls_subject": "", "proxy_address": "", "auto_compress": "1", "custom_interfaces": "0", "uuid": "", "inventory_mode": "-1" } ], "parameters": [], "triggers": [ { "triggerid": "23025", "expression": "{34226}=0", "description": "百度 Ping 不可达 / 安防设备", "url": "", "status": "0", "value": "0", "priority": "4", "lastchange": "1665649665", "comments": "", "error": "", "templateid": "0", "type": "0", "state": "0", "flags": "4", "recovery_mode": "0", "recovery_expression": "", "correlation_mode": "0", "correlation_tag": "", "manual_close": "0", "opdata": "", "event_name": "", "uuid": "" }, { "triggerid": "23029", "expression": "{34230}>1", "description": "百度 Ping 延迟大于 1000 毫秒 / 安防设备", "url": "", "status": "0", "value": "0", "priority": "2", "lastchange": "1660360605", "comments": "", "error": "", "templateid": "0", "type": "0", "state": "0", "flags": "4", "recovery_mode": "0", "recovery_expression": "", "correlation_mode": "0", "correlation_tag": "", "manual_close": "0", "opdata": "", "event_name": "", "uuid": "" } ], "itemDiscovery": { "itemdiscoveryid": "8222", "itemid": "43725", "parent_itemid": "43699", "key_": "ping.host[{#IP}]", "lastcheck": "1666920798", "ts_delete": "0" }, "lastclock": "1666920825", "lastns": "259796911", "lastvalue": "0.010557174682617188", "prevvalue": "0.010809659957885742", "tags": [ { "tag": "微信", "value": "c3e42012-621c-4948-8e3e-721defb7d6e9" }, { "tag": "用户名称", "value": "北师大附中" }, { "tag": "设备归属", "value": "安防设备" }, { "tag": "联系电话", "value": "刘先生 13333333333" }, { "tag": "归属区域", "value": "外围监控" } ] }
提供一种常规的数据合并模型算法
在xm-select时,需要设置默认使用selected属性选中属性,增加selected: true
的字段。为此,首先需要读取数据库中已经选择的选项,组成二维数组,然后和选项数据进行数组合并,组成新的data.
var demo2 = xmSelect.render({ el: '#demo2', data: [ {name: '水果', value: 1, selected: true, disabled: true}, {name: '蔬菜', value: 2, selected: true}, {name: '桌子', value: 3, disabled: true}, {name: '北京', value: 4}, ] })
数据库筛选数据
var data1 = [ {name: '水果', value: 1, selected: true}, {name: '蔬菜', value: 2, selected: true}, ]
原始数据
var data2 = [ {name: '水果', value: 1}, {name: '蔬菜', value: 2}, {name: '桌子', value: 3}, {name: '北京', value: 4} ]
合并计算
var a1 = data1.concat(data2); console.log(getUnique(a1));
封装函数
function getUnique(data) { var arr = []; if (data != null) { for (var i = 0; i < data.length; i++) { if (JSON.stringify(arr).toString().indexOf(data[i].name) == -1) { if (data[i].selected == undefined) { arr.push({ name: data[i].name, value: data[i].value, }); } else { arr.push({ name: data[i].name, value: data[i].value, selected: data[i].selected }); } } } return arr; } }
@lockdata.cn