1. 程式人生 > >layUI之DataTable元件V1.0(父子表管理傳值/資料表格與select&laydate結合等)

layUI之DataTable元件V1.0(父子表管理傳值/資料表格與select&laydate結合等)

目錄

layUI之DataTable資料表格元件V1.0


概述

  公司專案中對於表格操作的要求較多,比如“父子表格關聯進行資料傳遞”、“表格中使用select元件”、“表格中使用日期控制元件”、“表格輸入格式驗證”、“資料表格新增(刪除)一行”等等...
  而這些內容在LayUI中都是不被支援的,迫於無奈自行進行了當前dataTable元件的封裝。後續有什麼功能再進行補充...
  PS:元件程式碼是自己一行一行敲得,教程是自己一個字一個字擼的。有任何欠妥之處,多多擔待~
  PS:這是最初版本的1.0。2.0程式碼已經更新完畢,文件後續在更新哦~

一、下載與引用

  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、 願世界和平......