layUI之DataTable元件V1.0(父子表管理傳值/資料表格與select&laydate結合等)
目錄
layUI之DataTable資料表格元件V1.0
概述
公司專案中對於表格操作的要求較多,比如“父子表格關聯進行資料傳遞”、“表格中使用select元件”、“表格中使用日期控制元件”、“表格輸入格式驗證”、“資料表格新增(刪除)一行”等等...
而這些內容在LayUI中都是不被支援的,迫於無奈自行進行了當前dataTable元件的封裝。後續有什麼功能再進行補充...
PS:元件程式碼是自己一行一行敲得,教程是自己一個字一個字擼的。有任何欠妥之處,多多擔待~
PS:這是最初版本的1.0。2.0程式碼已經更新完畢,文件後續在更新哦~
一、下載與引用
- 下載DataTable.js 下載連結 密碼:uzfh
- 在頁面中進行模組化引用
程式碼示例
<script>
layui.config({
base: '../../common/' //靜態資源所在路徑
}).extend({
dataTable:"../lib/extend/dataTable"
}).use(["dataTable"],function(){
var dt = layui.dataTable;
});
</script>
二、元件功能介紹
元件成功引入以後,就可以進行使用和開發了,使用主要分為這麼幾步:
- 父表格渲染(正常的列表顯示)
- 子表格渲染(子表格的資料主要用於父表格新增資料時彈窗選取)
- 元件其他特色功能(輸入資料驗證、新增刪除行、表格整合select/date元件等...)
下面就讓我們逐一開始講解吧....
三、父表格渲染
1. HTML中宣告空table一個(父表格):
這一步與往常使用layUI的table一致,沒什麼好額外強調的。
<table class="layui-hide" id="dataList" lay-filter="dataList"></table>
2. 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.資料格式需包含 totalCount 和list 兩項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原生編輯不同的是,本元件編輯時將進行輸入驗證,包括以下幾種:
- 新增
format
屬性,對對應的欄位進行輸入格式驗證,驗證不通過回退輸入 - 父表的
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"}
]]
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
欄位中:
當然,如果username
是compareKey
的話,也是不允許重複的哦~就是這麼毫無漏洞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元件:
話不多說,先看效果圖
這個元件,使用起來程式碼比較多,也比較複雜。 但是相對於js中封裝的那些DOM操作,大家還是忍忍吧~
a. 為表格需要使用select的欄位新增templet
和event
。注意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日期元件:
老規矩,效果圖鎮樓:
這個效果的實現思路,與整合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的欄位新增templet
和event
。
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、 願世界和平......