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 主表ID String 即主表HTML中的id,例:"#datalist"
data 主表渲染数据 Object 1.公司框架要求,主表只能使用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 设置表头 Array 1、二维数组,同layUI-table。
2、部分新增配置属性将在后续详细功能讲解。

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

父表展示效果

四、子表弹出渲染

1. HTML中声明空table(子表),并隐藏:
<div id="div1" style="display: none;">
    <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的id String 是包裹子表的弹层div哦,不是table
title 弹窗的标题 String
width 弹窗的宽度 String 要带px哦
height 弹窗的高度 String 要带px哦
table 子表table的配置 Object 在layUI的table属性基础上,拓展了很多,请看下表↓↓↓
>>> table属性详解:
属性名 作用 格式 备注
tableId 子表id String 这个是子表table的id哦
url 子表请求数据的url String 与父表不同的是,子表采用Ajax请求
where 请求数据其他参数 Object 同layUI,比如我司请求数据必备的token
page 子表是否分页 Boolean 同Layui
limits 子表分页列表 Array 同Layui
limit 子表每页条数 int 同Layui
compareKey 父子表比对字段 String 与父表的compareKey配合,共同判断数据字符重复
map 父子表字段映射 Array 1.父子表关联字段列表,数组格式
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、 愿世界和平......

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容