记录、总结Layui的form、table组件使用。
一、增删改查
要完成的页面样式为:
使用的是Layui中form、table组件。
HTML
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<link type="text/css" href="./js/layui-v2.6.3/css/layui.css" media="all">
<link type="text/css" href="css/public.css" media="all">
<title></title>
</head>
<body>
<div class="layuimini-container">
<div class="layuimini-main">
<fieldset class="table-search-fieldset" style="">
<legend>搜索</legend>
<div>
<form class="layui-form layui-form-pane">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">系统名称</label>
<div class="layui-input-inline">
<input type="text" id="systemName" name="systemName" class="layui-input" autocomplete="off"/>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">业务主管部门</label>
<div class="layui-input-inline">
<input type="text" id="bussinessDep" name="bussinessDep" class="layui-input" autocomplete="off"/>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">研发单位</label>
<div class="layui-input-inline">
<input type="text" id="developUnit" name="developUnit" class="layui-input" autocomplete="off"/>
</div>
</div>
<div class="layui-inline">
<!--
预设元素属性:lay-verify、lay-skin、lay-filter、lay-submit
lay-submit 绑定触发提交的元素,如button
lay-filter 主要用于事件的精确匹配 -->
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="search">查询</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
</fieldset>
<table id="accountsTable" lay-filter="accountsTable"></table>
</div>
</div>
<script type="text/javascript" src="./js/layui-v2.6.3/layui.js" charset="UTF-8"></script>
<script type="text/javascript" src="js/jquery/1.9.1/jquery.min.js" charset="UTF-8"></script>
<script type="text/javascript" src="js/h-ui/js/H-ui.min.js"></script>
<script type="text/javascript" src="data.js"></script>
<!-- 工具栏模板 -->
<script type="text/html" id="leftBar">
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="add">添加</a>
</script>
<script type="text/html" id="itemBar">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-warm" lay-event="detail">详情</a>
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
</script>
<script>
layui.use(['form','table','layer'],function(){
var form = layui.form
var table = layui.table
var layer = layui.layer
var $ = layui.$
var tableOptions = {
elem:'#accountsTable',
,data:allDataList.data,
,cols:[[
{
field:'systemName',
title:'项目名称',
align:'left',
width: 200,
fixed:'left',
event:'cell'//自定义单元格点击事件名,以便在tool事件中完成对该单元格的业务处理
},
{
field: 'businessDepartment',
title: '业务主管<br/>部门',
align: 'center'
},
{
field: 'businessCharger',
title: '业务负责人',
align: 'center'
},
{
field: 'businessChargerPhone',
title: '业务负责人<br/>联系方式',
align: 'center'
},
{
field: 'developUnit',
title: '研发单位(牵头)',
align: 'center'
},
{
field: 'projectLeader',
title: '研发单位(牵头)<br/>负责人',
align: 'center'
},
{
field: 'projectLeaderMobilePhone',
title: '研发单位(牵头)<br/>负责人联系方式',
align: 'center'
},
{
field: 'participatingUnit',
title: '研发单位(参与)',
align: 'center'
},
{
field: 'participatingContact',
title: '研发单位(参与)<br/>负责人',
align: 'center'
},
{
field: 'participatingContactPhone',
title: '研发单位(参与)<br/>负责人联系方式',
align: 'center'
},
{
field: 'operateUnit',
title: '研发单位(运营)',
align: 'center'
},
{
field: 'operateContact',
title: '研发单位(运营)<br/>负责人',
align: 'center'
},
{
field: 'operateContactPhone',
title: '研发单位(运营)<br/>负责人联系方式',
align: 'center'
},
{
title: '操作',
toolbar: '#itemBar',
align: 'center'
}
]],
toolbar:'#leftBar',
defaultToolbar: ['filter', 'print', 'exports'],
page: true,
limit:10,
limits:[10,20,30],
id:'accountsTableReload',//用于table.checkStatus(id)、table.reload(id, options, deep)等函数
}
table.render(tableOptions);
table.on("toolbar(accountsTable)",function(obj){
if(obj.event == "add"){
/**
* layer.open(options)
* 创建任何类型的弹层都会返回一个当前层索引,上述的options即是基础参数,
*
* 另外,该文档统一采用options作为基础参数的标识例子:
* var index = layer.open({
* content: 'test'
* });
* //拿到的index是一个重要的凭据,它是诸如layer.close(index)等方法的必传参数。
*/
var index = layer.open({
title:'新增项目',
type:2, //五种类型 0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)
shade:0.2, //遮罩层透明度
maxmin:true,//该参数值对type:1和type:2有效。默认不显示最大小化按钮。
shadeClose:true,//是否点击遮罩关闭
area:[100%,100%],
content:'accounts_add.html'
});
$(window).on("resize",function(){//on()方法在被选元素及子元素上添加一个或多个事件处理程序
layer.full(index);//full:在自定义元素上触发最大化
});
}
});
table.on('tool(accountsTable)',function(obj){
var data = obj.data;
var layEvent = obj.event;
if(layEvent == "edit"){ //编辑
var index = layer.open({
title:'编辑项目',
type:2,
shade:0.2,
maxmin:true,
area:['100%','100%'],
content:'accounts_edit.html?sId=' + data.id
});
$(window).on('resize',function(){
layer.full(index);
});
}else if(layEvent == "detail"){//详情
var index = layer.open({
title:'项目详情',
type:2,
shade:0.2,
maxmin:true,
shadeClose: true,
area:['100%','100%'],
content:'accounts_detail.html?systemId=' + data.id
});
$(window).on('resize',function(){
layer.full(index);
});
}else if(layEvent == "cell"){//项目进度
var index = layer.open({
title:'项目进度',
type:2,
shade:0.2,
maxmin:true,
shadeClose: true,
area:['100%','100%'],
content:'action.html?systemName=' + data.systemName
});
$(window).on('resize',function(){
layer.full(index);
});
}else if(layEvent == "del"){//删除
layer.confirm('确认要删除吗?',{title:'删除'},function(index){
$.ajax({
async:false,//true:异步请求 false:同步请求 注意,同步请求将锁住浏览器,用户其它操作必须等待请求完成才可以执行。
type:"post",
url:"http://loaclhost:8090/crei/system/delById",
data:JSON.stringify({//发送到服务器的数据。
//将 JavaScript 值转换为 JSON 字符串
"id":id
}),
dataType:"json",//预期服务器返回的数据类型
contentType:"application/json;charset=UTF-8",//发送信息至服务器时内容编码类型。
success:function(res){
if(res){
layer.msg('已删除!',{
icon:1,
time:1000// //1秒关闭(如果不配置,默认是3秒)
});
layui.table.reload('accountsTableReload',{
page:{
curr:1//重新从第 1 页开始
}
})
}
},
error:function(XMLHttpRequest,textStatus,errorThrown){}
});
});
}
})
from.on('submit(search)',function(data){
var dataList = [];
$.ajax({
async:true,
type:"post",
url:"http://localhost:8090/crei/system/search",
data:JSON.stringify(data.field),
contentType:"application/json;charset=utf-8",
success:function(res){
dataList = res;
},
error:function(XMLHttpRequest,textStatus,erroeThrown){}
});
return dataList;
})
})
</script>
</body>
</html>
【meta标签的使用】
https://www.runoob.com/w3cnote/meta.html
meta提供有关某个HTML元素的元信息 比如描述、针对搜索引擎的关键词、刷新频率。
用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 web 服务。
二、组件使用介绍
table.render()
table.render()中的url、data
-
url:文件路径时使用
-
data:直接赋值数据。注意可能是tableData.data。需要再取一层。
table.on()
table.on('event(filter)', callback);
event为内置事件名,filter为容器lay-filter设定的值
eg:table.on(‘toolbar(test)’, function(obj) 触发头部工具栏事件
table.on(‘tool(test)’, function(obj) 工具条事件(每一行"编辑、详情";单元格能编辑时,编辑单元格)
table.on(‘checkbox(test)’, function(obj) 触发复选框选择
table.on(‘radio(test)’, function(obj) 触发单选框选择
table.on(‘edit(test)’, function(obj) 触发单元格编辑
table.on(‘row(test)’, function(obj) 触发行单击事件
table.on(‘sort(test)’, function(obj) 触发排序切换
obj:当前行的一些常用操作集合 每个event对应的obj不同
obj.checked 当前是否选中状态
obj.data 选中行的相关数据
obj.type
checkbox事件:如果触发的是全选,则为:all,如果触发的是单选,则为:one
sort事件:当前排序类型:desc(降序)、asc(升序)、null(空对象,默认排序)
form.on()
form.on('event(过滤器值)', callback);
事件event有:
select 触发select下拉选择事件
checkbox 触发checkbox复选框勾选事件
switch 触发checkbox复选框开关事件
radio 触发radio单选框事件
submit 触发表单提交事件
默认情况下,事件所触发的是全部的form模块元素,但如果你只想触发某一个元素,使用事件过滤器lay-filter=""即可。
例如:
form.on(‘select(filter)’, function(data)
form.on(‘checkbox(filter)’, function(data){
form.on(‘switch(filter)’, function(data){
form.on(‘radio(filter)’, function(data){
form.on(‘submit(*)’, function(data){
回调函数中的data:
data.elem ——checkbox中:得到checkbox原始DOM对象
data.elem ——submit中:被执行事件的元素DOM对象,一般为button对象
data.form ——submit中:被执行提交的form对象,一般在存在form标签时才会返回
data.field ——submit中:当前容器的全部表单字段,名值对形式:{name: value}
templet
在cols中使用
https://layui.bigma.cc/doc/modules/table.html#templet
{field: 'tpye', title: '所属类别', align:"center",templet:'#typeBar'}
<script type="text/html" id="typeBar">
{{# if(d.tpye == 1){ }}
系统优化
{{# }else if(d.tpye==2){ }}
使用中问题
{{# }else { }}
使用中问题
{{# } }}
</script>
或者行内写:
{field: 'ordertype', title: '订单类型', align:'center',templet:function(d){
return d.ordertype == "elvan" ? "代购" : "私有";
}},
d:包含当前行数据及特定的额外字段
Layui中使用$
内置的jQuery模块去除了全局的$和jQuery
如果要使用$:
方法一:layui.use(‘jquery’)
方法二:加载layui中依赖jQuery的部分内置模块 如layer 可以直接得到
三、个性化需求实现
1、根据状态修改layui表格显示的文字及字体颜色
当表格有两个或多个不同的状态时,我们可以让不同的状态显示不同文字及字体颜色,比如有两个状态:true和false,我让为状态true的显示“已销售”,状态false的显示“已退货”并将字体改成红色,如
tabReceived = layuiTable.render({
//url: '/DayWorkManagement/FormerSell/selectReceived',
elem: '#tabReceived',
cols: [[
{ type: 'numbers', title: '序号' },
{ type: 'checkbox'},
{ field: 'MarketID', title: '单据ID', hide: true },
{ field: 'MarOddNumber', title: '单号', align: 'center'},
{ field: 'NumberDates', title: '单据日期', align: 'center'},
{ field: 'MarKetState', title: '状态', templet: ZhuangTai, align: 'center'},
{ field: 'MarAmount', title: '数量', align: 'center'},
{ field: 'ConMenyer', title: '金额', align: 'center'},
{ field: 'MarKetAddres', title: '备注', align: 'center'},
{ field: 'UserType', title: '操作人', align: 'center'},
{ field: 'OperationDates', title: '更新时间', align: 'center'}
]],
page: {
limit: 10,//每页显示的条数
limits: [5, 10, 15, 20, 25, 30, 35, 40, 45, 50],//每页条数的选择项
},
data: [],
});
//自定义“状态”列
function ZhuangTai(data) {
var MarKetState = data.MarKetState;
if (MarKetState == true) {
return "已销售";
}
if (MarKetState == false) {
return "已退货";
}
}
要加颜色的话,和加自定义按钮差不多,我的是给它加上一个a标签,从而改变它的字体颜色的。
function ZhuangTai(data) {
var MarKetState = data.MarKetState;
var btns = "";
if (MarKetState == true) {
return "已销售";
}
if (MarKetState == false) {
btns += '<a class="" style="color:#ed2a4a">已退货</a>';
}
return btns;
}
2、根据数据填充单元格的背景颜色
参考:https://www.cnblogs.com/showcase/p/10844568.html
- 前置知识:修改td的背景颜色——
<td bgcolor="red">First</td>
- 因为templet中d是该行的数据,无法修改单元格,所以使用render函数中done回调函数。
- 实现的是效果是:如果数据为0,该单元格的背景颜色为红。
done: function(res, curr, count){
//如果是异步请求数据方式,res即为你接口返回的信息。
//如果是直接赋值的方式,res即为:{data: [], count: 99} data为当前页数据、count为数据总长度
$('.layui-table').eq(1).find('td').each(function(){
if($(this).find('div').html=='0'){
$(this).attr('bgcolor','red');
}
})
- $(‘.layui-table’)、find(‘div’)等要去页面中查看结构。.layui-table是框架生成的class属性,不是自定义的。.eq是因为layui框架把表头和表格内容生成两个。
3、读取List数据,放入几个列中
cols:[{filed:“”}]
field中user.name直接取,不行
5、table中点击名称,进入新页面
(1)列参数中加上event: ‘cell’
{field: 'systemName',title: '系统名称',align: 'center',event: 'cell',width: 130}
(2)事件监听
table.on('tool(accountsTable)', function(obj) {
var data = obj.data;
var layEvent = obj.event;
……
//填报
else if(layEvent == "cell") {
var index = layer.open({
title: '项目填报',
type: 2,
shade: 0.2,
maxmin: true,
shadeClose: true,
area: ['100%', '100%'],
content: 'action.html?sysName=' + data.systemName + '&sysId=' + data.id
});
$(window).on("resize", function() {
layer.full(index);
});
}
6、请求得到的数据有list,需要再读一层
在templet中循环取出
{field: 'canyuList',title: '参与研发单位',align: 'center',width: 120,
templet: function(d){
var units;
d.canyuList.forEach(function(item){
units += item.unit + '<br>';
})
return units;
}
}
forEach 遍历Array
for…in 遍历object
7、合并单元格
使用layui-table-merge插件
8、刷新表格
- 查询框
重置按钮:清除表单数据、重载所有数据()
//重置按钮:重置表单、重新加载所有数据
$("#resetBtn").on('click', function() {
document.getElementById("searchT").reset();//重置表单
table.reload('accountsTableReload', {//重新加载所有数据
//data: tableData.data,
url: creiUrl + listUrl,
method: 'get'
});
})
-
添加一行
重点:
localStorage.getItem(“addID”)
oldData.unshift(newData);
if (obj.event == "add") {
var oldData = layui.table.cache["accountsTableReload"];//ID是render()中的id
var index = layer.open({
title: '新增统型项目',
type: 2,
shade: 0.2,
maxmin: true,
shadeClose: true,
area: ['100%', '100%'],
content: 'add.html',
end: function(){//layer层销毁之后的回调
$.ajax({
async: false,
type: "GET",
url: creiUrl + detailUrl + localStorage.getItem("addID"),//调用API,获得新增的数据
dataType: 'JSON',
contentType: "application/json;charset=UTF-8",
success: function(res) {
var detailData =res.data;//API请求后返回的数据
var newData = {//新增行的数据
abbreviation: detailData.abbreviation//abbreviation是cols参数中定义的各列的field
,belongBusinessDepartmentName: detailData.belongBusinessDepartmentName
,businessDepartment: detailData.businessDepartment
,systemName: detailData.systemName
,systemField: detailData.ffCatalog
,fCatalog: detailData.fcatalog
,catalog: detailData.catalog
,constructionType: detailData.constructionType
,runningState: detailData.runningState
,businessCharger: detailData.businessCharger
,businessChargerPhone: detailData.businessChargerPhone
,developmentUnitName: detailData.developUnit
,developUnitType: detailData.developUnitType
,deployLocation: detailData.deployLocation
,deployWay: detailData.deployWay
,classifiedProtectionLevel: detailData.classifiedProtectionLevel
,networkArea: detailData.networkArea
};
oldData.unshift(newData);//新数据放到第一个位置
table.reload('accountsTableReload', {
data: oldData,
page: {
curr: 1 //重新定位到第一页
}
});
},
error: function(XMLHttpRequest, textStatus, errorThrown) {}
});
还要在add.html中定义:
localStorage.setItem(“addID”,res.data);
form.on('submit(submit)', function(data) {
$.ajax({
async: false,
type: "post",
url: creiUrl + addUrl,
data: JSON.stringify(data.field),
dataType: 'json',
contentType: "application/json;charset=UTF-8",
success: function(res) {
localStorage.setItem("addID",res.data);
if(res.code == 0) {
layer.msg('新增成功!', {
icon: 1,
time: 1000
});
-
编辑行
重点:把行数据放入obj.update()
/**
* 列工具条
*/
table.on('tool(accountsTable)', function(obj) {
var data = obj.data;
var layEvent = obj.event;
//编辑
if (layEvent == "edit") {
var index = layer.open({
title: '编辑统型项目',
type: 2,
shade: 0.2,
maxmin: true,
shadeClose: true,
area: ['100%', '100%'],
content: 'edit.html?sysId=' + data.id,
end: function(){
$.ajax({
async: false,
type: "GET",
url: creiUrl + detailUrl + data.id,
dataType: 'JSON',
contentType: "application/json;charset=UTF-8",
success: function(res) {
var detailData =res.data;
// console.log(detailData)
obj.update({
abbreviation: detailData.abbreviation
,belongBusinessDepartmentName: detailData.belongBusinessDepartmentName
,businessDepartment: detailData.businessDepartment
,systemName: detailData.systemName
,systemField: detailData.ffCatalog
,fCatalog: detailData.fcatalog
,catalog: detailData.catalog
,constructionType: detailData.constructionType
,runningState: detailData.runningState
,businessCharger: detailData.businessCharger
,businessChargerPhone: detailData.businessChargerPhone
,developmentUnitName: detailData.developUnit
,developUnitType: detailData.developUnitType
,deployLocation: detailData.deployLocation
,deployWay: detailData.deployWay
,classifiedProtectionLevel: detailData.classifiedProtectionLevel
,networkArea: detailData.networkArea
});
},
error: function(XMLHttpRequest, textStatus, errorThrown) {}
});
}
});
$(window).on("resize", function() {
layer.full(index);
});
}
- 删除该行:
方法一:先发送删除请求,再重新请求完整的数据、reload
方法二:先发送删除请求,再移除该行的DOM结构(推荐)
//删除
else if (layEvent == "del") {
layer.confirm('确认要删除吗?', {
title: '删除'
}, function(index) {
obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
$.ajax({
async: true,
type: "get",
url: creiUrl + delUrl + "/" + data.id,
dataType: 'json',
contentType: "application/json;charset=UTF-8",
success: function(res) {
if (res) {
layer.msg('已删除!', {
icon: 1,
time: 1000
});
}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {}
});
});
}
9、导出表格
导出全部数据:
var tableData = getData(creiUrl + listUrl); //表格数据
<script type="text/html" id="leftBar">
<a class="layui-btn layui-btn-primary layui-border-blue layui-btn-xs" lay-event="add">添加 </a>
<button class="layui-btn layui-btn-primary layui-border-orange layui-btn-xs" id="exportAll"> 导出全部数据</button>
</script>
var ins1 = table.render(tableOptions);
//导出全部数据
$("#exportAll").on('click', function() {
table.exportFile(ins1.config.id, tableData.data);
})
搜索框中的导出:
<button class="layui-btn layui-btn-primary layui-border-blue layui-btn-sm"
style="width: 100px;" id="exportSearch">导出搜索结果</button>
//监听搜索操作
form.on('submit(search)', function(data) {
var params = data.field;
var searchData = postApi(creiUrl + searchUrl, params); //搜索
table.reload('accountsTableReload', {
data: searchData.data,
method: 'post',
page: true,
limit: 10,
limits: [5, 10, 15]
});
var message = "搜索完成";
toast.info({title: '提示',message: message,position: 'topRight'});
//导出搜索结果数据
$("#exportSearch").on('click', function() {
table.exportFile(ins1.config.id, searchData.data);
})
return false;
});
四、问题
1、默认传递两个参数