手记

layUI之DataTable组件(父子表管理传值/数据表格与select&laydate结合等)

layUI之DataTable数据表格组件


[TOC]

概述

   公司项目中对于表格操作的要求较多,比如“父子表格关联进行数据传递”、“表格中使用select组件”、“表格中使用日期控件”、“表格输入格式验证”、“数据表格新增(删除)一行”等等...
   而这些内容在LayUI中都是不被支持的,迫于无奈自行进行了当前dataTable组件的封装。后续有什么功能再进行补充...
   PS:组件代码是自己一行一行敲得,教程是自己一个字一个字撸的。有任何欠妥之处,多多担待~

一、下载与引用

  1. 下载DataTable.js   下载链接  密码:uzfh

  2. 在页面中进行模块化引用

代码示例

<script>
layui.config({    base: '../../common/' //静态资源所在路径
 }).extend({    dataTable:"../lib/extend/dataTable"}).use(["dataTable"],function(){    var dt = layui.dataTable;
});</script>

二、组件功能介绍

  组件成功引入以后,就可以进行使用和开发了,使用主要分为这么几步:

  1. 父表格渲染(正常的列表显示)

  2. 子表格渲染(子表格的数据主要用于父表格新增数据时弹窗选取)

  3. 组件其他特色功能(输入数据验证、新增删除行、表格集成select/date组件等...)

 下面就让我们逐一开始讲解吧....

三、父表格渲染

1. HTML中声明空table一个(父表格):

 这一步与往常使用layUI的table一致,没什么好额外强调的。

<table class="layui-hide" id="dataList" lay-filter="dataList"></table>
2. JS 中对父表格进行渲染:

 注: 在【一、下载与引用】中已对dataTable.js进行了引入,且声明组件对象为dt,则后续将不再引入声明,统一使用dt表示组件对象

dt.renderParentTable({    // 父表格配置属性});

 【郑重声明】
1、声明方法中支持传入绝大部分layUI数据表格的属性,详细支持属性请看下表。
2、暂时不支持的属性后续应该也会支持(本条不负法律责任,支不支持纯看心情,最终解释权归jh所有,不服打我呀略略略...)

3. 父表格渲染属性:

 先看一段史上最全的父表格声明渲染代码(保险起见,所有属性全部必填,不要随便省略):

dt.renderParentTable({    id:"#dataList",  // 主表id
    data:{totalCount:2,          list:[
                {"id":1,"username":"zhangsan","email":"zhangsan","sexvalue":"1","sextext":"男","time":"2018-08-22","mobile":13},
                {"id":2,"username":"lisi","email":"lisi","sexvalue":"2","sextext":"女","time":"2017-08-24","mobile":14},
                {"id":3,"username":"wanger","email":"wanger","sexvalue":"3","sextext":"未知","time":"2018-06-27","mobile":15},
                {"id":4,"username":"jianghao","email":"jianghao","sexvalue":"1","sextext":"男","time":"2018-08-22","mobile":16}
           ]
    },    compareKey:"username",    height: "full-100",    page:true,    limits: [1, 2, 3, 4],    limit: 1,    cols:[  // 主表列
        [{type: "checkbox",fixed: "left",width: 50}
        , {field: 'username',title: 'username',minWidth: 150,align: "center"/*,edit: 'text'*/,event:'chooseUser'}
        , {field: 'email',title: 'email', minWidth: 150,align: "center",edit: 'text',format:"mail"}
        , {field: 'sexvalue',style:"display:none;",type:"space",width:"0%"}
        , {field: 'sextext',title: 'sex', minWidth: 150,align: "center",templet:"#sexTpl",event:'select'}
        , {field: 'time',title: 'time', minWidth: 150,align: "center",templet:"#timeTpl",event:'chooseDate'}        /**
         * format:"int" 整形
         * format:"num" 数值
         * format:"tel" 手机号
         * format:"money" 金额
         * format:"mail" 邮箱
         */
        , {field: 'mobile',title: 'mobile',minWidth: 150,align: "center",edit: 'text',format:"tel"}
        ]
    ]
});

 大体知道怎么用了吧,接下来我们看看这些属性都是啥:

属性名作用格式备注
id主表IDString即主表HTML中的id,例:"#datalist"
data主表渲染数据Object1.公司框架要求,主表只能使用data渲染,不支持URL请求
2.数据格式需包含totalCountlist两项
3.例:
{
 totalCount:2,
 list:[
  //Array行数据
 ]
}
compareKey父子表比对字段String子表选择数据传入父表时,凭此字段queding
page是否开启分页Boolean同layUI-table
limits分页列表Array同layUI-table
limit每页行数int同layUI-table
cols设置表头Array1、二维数组,同layUI-table。
2、部分新增配置属性将在后续详细功能讲解。

 好了,经过这样的一通操作,父表就可以成功的渲染出来了,开心吗?

父表展示效果

四、子表弹出渲染

1. HTML中声明空table(子表),并隐藏:
<div id="div1" >
    <table class="layui-hide" id="dataList1" lay-filter="dataList1"></table></div>
2. 点击按钮渲染子表并弹出:

 看到上面父表效果图中,有一个【选择数据新增】了吗?我们要做的事点击这个按钮,弹出子表。(至于怎么做点击事件,不用我说吧~)
 点击事件函数中你需要写这些东西:

dt.renderDetaiTable({
    detailId:"#div1",  // 打开的弹出层id
    title: '添加新模型', // 打开的弹出层标题
    width:"850px",
    height:"450px",
    table:{ // 弹出层中表格配置
        tableId:"#dataList1", // 子表id
        url:setter.baseurl+"sys/user", // 子表请求的url
        where:{            "token":setter.token,
        }, // 需传递后台的其他参数
        page:true,
        limits: [1, 2, 3, 4],
        limit: 1,
        compareKey:"username",
        map:[ // 父子表映射字段
            {parent:"username",detail:"username"},
            {parent:"email",detail:"email"},
            {parent:"mobile",detail:"mobile"}
        ],
        cols:[
            [
            {type: "checkbox"}
            , {field: 'username',title: 'username',minWidth: 150,align: "center"}
            , {field: 'email',title: 'email', minWidth: 150,align: "center"}
            , {field: 'mobile',title: 'mobile',minWidth: 150,align: "center"}
            ]
        ]
    }
});

 子表的属性要比父表多很多!精华全部都在这里,接下来我们一个一个的分析,不要眨眼哦~

3. 子表属性详解:
属性名作用格式备注
detailId子表所在div的idString是包裹子表的弹层div哦,不是table
title弹窗的标题String
width弹窗的宽度String要带px哦
height弹窗的高度String要带px哦
table子表table的配置Object在layUI的table属性基础上,拓展了很多,请看下表
>>> table属性详解:
属性名作用格式备注
tableId子表idString这个是子表table的id哦
url子表请求数据的urlString与父表不同的是,子表采用Ajax请求
where请求数据其他参数Object同layUI,比如我司请求数据必备的token
page子表是否分页Boolean同Layui
limits子表分页列表Array同Layui
limit子表每页条数int同Layui
compareKey父子表比对字段String与父表的compareKey配合,共同判断数据字符重复
map父子表字段映射Array1.父子表关联字段列表,数组格式
2.数组每一项为一个对象,包含parent和detail两个属性
3.例:{parent:"mobile",detail:"mob"}
表示将把子表的mob字段,赋值给父表的mobile字段
4.不在数组中的字段将不会关联传递
cols子表表头配置Array二维数组,同Layui

 好了,经过这样的一通配置,点击按钮将弹出子表并加载数据:

子表弹出效果


 当你选中数据,点击确定时,将自动把子表所选数据添加到父表中。(当然,只能添加父子表compareKey不相同的字段


五、父表增/删/改/查

1. 父表开启编辑功能并进行输入验证:

 父表开启编辑功能的方式,采用layUI原生的编辑功能,即父表哪个字段需要编辑,可以在cols的对应列中,添加edit: 'text'属性开启编辑功能。

 与layUI原生编辑不同的是,本组件编辑时将进行输入验证,包括以下几种:

  1. 添加format属性,对对应的字段进行输入格式验证,验证不通过回退输入

  2. 父表的compareKey字段不可为空,且不可与已有的compareKey字段重复,验证不通过回退输入

cols:[[    /**
     * 本行未添加edit: 'text'属性,不允许编辑
     */
    {field: 'time',title: 'time'}    /**
     * 本行未添加edit: 'text'属性,允许编辑,且format属性支持格式验证,详细如下:
     * format:"int" 整形
     * format:"num" 数值
     * format:"tel" 手机号
     * format:"money" 金额
     * format:"mail" 邮箱
     */
    , {field: 'mobile',title: 'mobile',edit: 'text',format:"tel"}
]]

开启编辑功能的字段


不符合format要求的提示


compareKey字段不可重复不可为空

2. 父表新增空行数据:

 上述【二、子表弹出渲染】中,我们详细讲述了如何从子表中选择并新增数据。但很多时候,我们也需要新增空行数据自行编辑;
 本组件也为大家提供了这个功能,要新增之前需开启字段的编辑功能。当然,你不开启也行,只不过这个字段无法录入数据(后续通过弹出选择、select选择,date选择的除外)
 编辑时的验证对新增依然有效,再强调一遍,compareKey字段不可为空不可重复。

 好了,该强调的强调完了,新增空行非常简单,点击按钮调用组件提供的现场功能即可:

dt.addParentRow();
3. 删除表格数据:

 删除非常简单,选中你要删除的行,调用组件提供的现成方法即可。删除时将返回所有被删除的行:

var delRows = dt.delParentRow();console.log(delRows); // 所有被删除的行
4. 获取表格所有行数据:

 组件提供现成方法:

dt.getParentTableRows()
5. 根据指定条件,对表格进行搜索:

 调用组件现成方法,并传入你要搜索的所有值(键值对),当然传入空表示清空搜索:

dt.searchParentTable({    "username":$(".searchName").val(),    "mobile":$(".searchMob").val()
});

六、其他特色功能

1. 表格指定字段,支持弹窗选择:

 有这么一种情况,比如说:新增一行数据时,用户名字段不允许用户手动输入,必须选择数据库中已有的数据。
 【功能示例】
 下表新增一行空数据,当我点击用户名字段时,弹出一个选择窗:

此处输入图片的描述


 当点击选择时,会将指定字段填入主表的username字段中:

此处输入图片的描述


 当然,如果usernamecompareKey的话,也是不允许重复的哦就是这么毫无漏洞hiahiahia

此处输入图片的描述


 好了,功能了解完成后,我们开始操作吧!需要做的比较多,大家一步步的记清楚哦:
 ① 制作一个点击需要打开的HTML页面
 里面的html和js代码你可以随便写。但是当点击选择的时候,你必须要关闭当前弹窗,同时将所选数据存入localStorage中:


table.on('tool(dataList)', function (obj) {    var layEvent = obj.event;    if (layEvent === 'choose') { 
        // 将所选数据存入localStorage中,这里使用的是layUI提供的存储方式,不懂的可以去看文档
        layui.data(setter.tableName, {          key: 'chooseValue'
          ,value: obj.data
        });        // 存完以后关闭弹窗
        var index = parent.layer.getFrameIndex(window.name);
        setTimeout(function(){parent.layer.close(index)}, 300);
    }
});

 ② 主表中点击指定单元格,弹出HTML页面
主表的cols中为指定字段添加event属性:

cols:[[
    {field: 'username',title: 'username',event:'chooseUser'}
]]

event属性添加事件监听:
即,点击单元格弹窗,其他的都不重要,弹窗的end非常重要,在这个回调中你需要做这些事情:
 a. 取到我们存在localStorage中的数据

var chooseUser = layui.data(setter.tableName).chooseValue;

 b. 调用组件的updateParentTableRow()方法,并传入表格行对象、行this、选中数据的字段与表格字段的对应关系:

dt.updateParentTableRow(obj,this,chooseUser,{    chooseField:"username", // 选中对象的字段
    tableField:"username",  // 对应表格的字段});

 c. 用完即毁。 销毁存在localStorage中的数据! 这一步你必须要做,不然后果自负....

layui.data(setter.tableName, {    key: 'chooseValue'
    ,remove: true});

 最后,完整代码送给大家copy:

table.on('tool(dataList)',function(obj){    if(obj.event == 'chooseUser'){
        top.layer.open({            type: 2
            ,title: '选择用户'
            ,content: 'modules/common/chooseUser.html'
            ,area: ['1200px', '600px']
            ,success: function (layero, index) {},            end:function(){                var chooseUser = layui.data(setter.tableName).chooseValue;                /**
                 * param1 - 表格行对象
                 * param2- this
                 * param3 - 选中的数据
                 * param4 - 其他参数
                 */
                dt.updateParentTableRow(obj,this,chooseUser,{                    chooseField:"username", // 选中对象的字段
                    tableField:"username",  // 对应表格的字段
                });
                
                layui.data(setter.tableName, {                    key: 'chooseValue'
                    ,remove: true
                });
            }
        })
    }
});

 当然,你也可以将这个功能用在普通input的选择上,使用思路相同,将数据先存到localStorage中,在页面销毁的时候为输入框复制。 只不过就不用调用updateParentTableRow()方法了,用完即毁就行……

普通输入框点击弹出


2. 表格集成select组件:

 话不多说,先看效果图


表格集成select下拉框


  这个组件,使用起来代码比较多,也比较复杂。 但是相对于js中封装的那些DOM操作,大家还是忍忍吧~

  a. 为表格需要使用select的字段添加templetevent。注意field应为select的显示字段,即<option></option>之间的文字。
  同时添加一个空字段,表示select的value字段。
也就是说,数据表格加载的JSON数据中,必须包含value和显示的文字

/* 数据表格的JSON数据,已省略其他字段。
 * { 
 *   totalCount:2,
 *   list:[{sexvalue:'1',sextext:'男'},{sexvalue:'1',sextext:'男'}]
 * }
 */cols:[[    // select的value
    {field: 'sexvalue',style:"display:none;",type:"space",width:"0%"}    // select显示的文字
    ,{field: 'sextext',title: 'sex', minWidth: 150,align: "center",templet:"#sexTpl",event:'select'}
]]

  b. 为绑定的templet添加模板:

<script type="text/html" id="sexTpl">
    // d.sextext为后台数据中,select显示的文字,非value    {{d.sextext}}<i class="layui-icon table-select-icon"></i></script>

  c. 为绑定的event添加事件,使用Ajax请假select的数据,并调用组件的renderTableSelect()方法,并传入指定属性,详见注释:

var sexData = [];
admin.req({    url:"sex.json",    success:function(r){
        sexData = r;
    }
})
table.on('tool(dataList)',function(obj){    if(obj.event == 'select'){
        dt.renderTableSelect(obj,this,{            data:sexData,// select的数据
            value:"id", // select数据中表示value的字段
            text:"value", // select中表示显示的字段
            valueField:"sexvalue" , // 数据表格中表示value的字段
            textField:"sextext", // 数据表格中表示显示的字段
        });
    }
})

  后台返回的数据sexData的格式:

[
  {    "id": 1,    "value": "女"
  }
  。。。
]

  d. 由于select会被遮挡,所以需要把下面这段CSS放入到页面中。后续可能考虑放到通用css中:

.table-select-icon{position:absolute;right:10px;line-height:34px;color:#d3d3d3}.table-select-selected dl{display:block}.table-select dl{position:absolute;left:0;padding:5px 0;z-index:999;min-width:100%;border:1px solid #d2d2d2;max-height:300px;    overflow-y:auto;background-color:#fff;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12);box-sizing:border-box}.table-select dl dd{cursor:pointer}.table-select dl dd,.table-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.table-select dl dd.layui-this{background-color:#5FB878;color:#fff}.table-select dl dd,.table-select dl dt{padding:0 10px;line-height:36px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.table-select dl dd:hover{background-color:#f2f2f2}

好了,这样就可以愉快的使用啦.....

3. 表格集成laydate日期组件:

  老规矩,效果图镇楼:


表格集成laydate日期组件


  这个效果的实现思路,与集成select的思路类似,下面一步一步的来分析:

  a. 页面中导入laydate组件,这个大家都懂:

layui.config({    base: '../../common/' //静态资源所在路径
 }).extend({    index: 'lib/index', //主入口模块
    dataTable:"../lib/extend/dataTable"}).use(["dataTable",'laydate'],function(){    var dt = layui.dataTable,
        form = layui.form,
        laydate = layui.laydate;
})

  b. 为表格需要使用select的字段添加templetevent

cols:[[
    {field: 'time',title: 'time',templet:"#timeTpl",event:'chooseDate'}
]]

  c. 为绑定的templet添加模板:

<script type="text/html" id="timeTpl">
    <div id="test1">{{d.time}}</div></script>

  d. 为绑定的event添加事件(done回调函数中的内容非常重要哦~):

table.on('tool(dataList)',function(obj){    if(obj.event == 'chooseDate'){        var field = $(this).data("field");
        laydate.render({            elem: '#test1',            trigger:"click",            show:true,            closeStop: '#test1',//          type:"datetime",//          format:"yyyy-MM-dd HH:mm:ss",
            done:function(value){
                obj.data[field] = value;
                obj.update(obj.data);
            }
        }); 
    }
});

  截止现在,laydate组件也可以老老实实的展示在数据表格中啦~

七、最后说点啥

  1、 组件是针对我们公司需求进行设计的,可能其他人用起来不一定那么顺手,大家可以取其精华、去其糟粕。
  2、 时间能力有限,部分功能不算太完善,后续还会慢悠悠的进行完善,大家也不用太期待了~
  3、 愿世界和平......



作者:小风飞鱼
链接:https://www.jianshu.com/p/03ff654f17e5


2人推荐
随时随地看视频
慕课网APP

热门评论

有完整的实例吗? 可以用于快速理解上手

查看全部评论