mirror of
https://gitee.com/layui/layui.git
synced 2026-01-28 11:11:21 +08:00
fix(table): 修复 2.9.9 table.setRowChecked 的参数中, index 选项为数组时,无法选中的问题 (#1914)
* revert: #1812 REVERT 由于 #1911 以及为了避免潜在的 BUG,恢复 #1812 全部改动和 #1760 中的部分改动。在 treeTable 中修复 #1815 * fix(treeTable): 节点移动后,行索引获取错误 * test(treeTable): 添加 crud 测试 * test(treeTable): 添加异步加载子节点测试 * chore: 添加测试文件来源 * update code
This commit is contained in:
226
examples/treeTable-async.html
Normal file
226
examples/treeTable-async.html
Normal file
@@ -0,0 +1,226 @@
|
||||
<!-- 引用自 https://gitee.com/layui/layui/issues/I6V5VY -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="../src/css/layui.css" href2="//cdn.staticfile.org/layui/2.9.6/css/layui.css"
|
||||
href3="https://cdn.jsdelivr.net/gh/layui/layui@879a9c629cc832f5b235d138adf164d74c34991b/src/css/layui.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="layui-fluid" style="padding: 15px;">
|
||||
<button class="layui-btn" lay-on="asyncLoad">asyncLoad</button>
|
||||
<button class="layui-btn" lay-on="flatData">flatData</button>
|
||||
<table id="demo"></table>
|
||||
</div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Mock.js/1.0.0/mock-min.js"></script>
|
||||
<script src="../src/layui.js" src1="//cdn.staticfile.org/layui/2.9.7/layui.js"
|
||||
src1="https://cdn.jsdelivr.net/gh/layui/layui@879a9c629cc832f5b235d138adf164d74c34991b/src/layui.js"></script>
|
||||
<script>
|
||||
layui.use(["treeTable", "util"], function () {
|
||||
var treeTable = layui.treeTable;
|
||||
var util = layui.util;
|
||||
|
||||
treeTable.set({
|
||||
|
||||
});
|
||||
|
||||
util.on({
|
||||
asyncLoad: function () {
|
||||
treeTable.reload('demo', {
|
||||
url: "/getDatas",
|
||||
tree: {
|
||||
data: {
|
||||
isSimpleData: false
|
||||
},
|
||||
async: {
|
||||
enable: true,
|
||||
autoParam: ["parentId=id"]
|
||||
}
|
||||
},
|
||||
}, true)
|
||||
},
|
||||
flatData: function () {
|
||||
treeTable.reload('demo', {
|
||||
data: testDatas,
|
||||
url: false,
|
||||
tree: {
|
||||
data: {
|
||||
isSimpleData: true
|
||||
},
|
||||
async: {
|
||||
enable: false,
|
||||
autoParam: ["parentId=id"]
|
||||
}
|
||||
},
|
||||
}, true)
|
||||
}
|
||||
})
|
||||
|
||||
// 生成随机ID函数
|
||||
const createId = (() => {
|
||||
let nextId = 1;
|
||||
return () => nextId++;
|
||||
})();
|
||||
|
||||
// 生成节点函数
|
||||
const createNode = (parentId = null, level = 0) => {
|
||||
const id = createId();
|
||||
const children =
|
||||
level < 3
|
||||
? Mock.mock({
|
||||
"array|0-5": [createNode.bind(null, id, level + 1)]
|
||||
}).array
|
||||
: [];
|
||||
|
||||
return {
|
||||
id,
|
||||
name: `User${id}`,
|
||||
type: Mock.mock("@d6"),
|
||||
status: Mock.Random.d4(),
|
||||
score: Mock.Random.d100(),
|
||||
experience: Mock.Random.integer(1000, 99999),
|
||||
sex: Mock.Random.cword("男女", 1),
|
||||
city: Mock.Random.city(),
|
||||
description: Mock.mock("@cparagraph"),
|
||||
createTime: Mock.mock("@datetime"),
|
||||
parentId,
|
||||
children,
|
||||
isParent: !!children.length
|
||||
};
|
||||
};
|
||||
|
||||
// 生成树
|
||||
const rootNodes = Mock.mock({
|
||||
"array|10-20": [createNode]
|
||||
}).array;
|
||||
|
||||
// 将树展开
|
||||
const flattenTree = (nodes, parentId = null) => {
|
||||
let result = [];
|
||||
nodes.forEach((node) => {
|
||||
result.push({
|
||||
...node,
|
||||
parentId,
|
||||
children: undefined
|
||||
});
|
||||
if (node.children.length > 0) {
|
||||
result = result.concat(flattenTree(node.children, node.id));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const getTreeData = function (nodes) {
|
||||
let result = [];
|
||||
nodes.forEach((node) => {
|
||||
result.push({
|
||||
...node,
|
||||
parentId: null,
|
||||
children: getTreeData(node.children)
|
||||
});
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
var testDatas = flattenTree(rootNodes);
|
||||
//var testDatas = getTreeData(rootNodes);
|
||||
|
||||
Mock.mock(/getDatas/, "get", (config) => {
|
||||
console.log(config);
|
||||
var params = layui.url(config.url);
|
||||
var search = params.search;
|
||||
var parentId = search.parentId;
|
||||
var dataRet = testDatas.filter(function (value, index, array) {
|
||||
return value.parentId == parentId;
|
||||
});
|
||||
|
||||
var sortColumn = search.sortColumn;
|
||||
var sortType = search.sortType;
|
||||
|
||||
dataRet = layui.sort(dataRet, sortColumn, sortType === "desc");
|
||||
|
||||
var curr = search.page;
|
||||
if (!curr) {
|
||||
curr = 1;
|
||||
} else {
|
||||
curr = parseInt(curr);
|
||||
curr = curr || 1;
|
||||
}
|
||||
var limit = search.limit;
|
||||
if (!limit) {
|
||||
limit = dataRet.length;
|
||||
} else {
|
||||
limit = parseInt(limit);
|
||||
limit = limit || dataRet.length;
|
||||
}
|
||||
var start = (curr - 1) * limit;
|
||||
|
||||
return {
|
||||
code: 0,
|
||||
data: dataRet.slice(start, start + limit),
|
||||
count: dataRet.length
|
||||
};
|
||||
});
|
||||
|
||||
treeTable.render({
|
||||
elem: "#demo",
|
||||
url: "/getDatas",
|
||||
totalRow: true,
|
||||
tree: {
|
||||
async: {
|
||||
enable: true,
|
||||
autoParam: ["parentId=id"]
|
||||
}
|
||||
},
|
||||
maxHeight: "full-95",
|
||||
cols: [
|
||||
[
|
||||
{ type: "numbers", fixed: "left" },
|
||||
{
|
||||
field: "id",
|
||||
title: "ID",
|
||||
width: 145,
|
||||
sort: true,
|
||||
fixed: "left",
|
||||
totalRow: "合计:"
|
||||
},
|
||||
{ field: "name", title: "用户名", width: 180, fixed: "left" },
|
||||
{
|
||||
field: "experience",
|
||||
title: "积分",
|
||||
width: 90,
|
||||
sort: true,
|
||||
totalRow: "{{= d.TOTAL_NUMS }}"
|
||||
},
|
||||
{ field: "sex", title: "性别", width: 80, sort: true },
|
||||
{
|
||||
field: "score",
|
||||
title: "评分",
|
||||
width: 80,
|
||||
sort: true,
|
||||
totalRow: true
|
||||
},
|
||||
{ field: "city", title: "城市", width: 150, templet: "#tpl1" },
|
||||
{
|
||||
field: "description",
|
||||
title: "描述信息",
|
||||
minWidth: 200,
|
||||
templet: "#tpl2"
|
||||
},
|
||||
{ field: "createTime", title: "创建时间", width: 170 }
|
||||
]
|
||||
],
|
||||
done: function (res, curr, count) {
|
||||
console.log('渲染完成', res, curr, count, this);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
285
examples/treeTable-crud.html
Normal file
285
examples/treeTable-crud.html
Normal file
@@ -0,0 +1,285 @@
|
||||
<!-- 引用自 https://github.com/layui/layui/issues/1815 -->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="../src/css/layui.css" href2="//cdn.staticfile.org/layui/2.9.6/css/layui.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table class="layui-table" id="MianTable" lay-filter="MianTable" lay-data="{id: 'MianTable'}"></table>
|
||||
<script type="text/html" id="toolbar">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm" lay-event="AddRowButton">
|
||||
新增主件
|
||||
</button>
|
||||
<button class="layui-btn layui-btn-sm" lay-event="InitTableButton">
|
||||
初始化数据
|
||||
</button>
|
||||
<button class="layui-btn layui-btn-sm" lay-event="SubmitButton">
|
||||
保存
|
||||
</button>
|
||||
<button class="layui-btn layui-btn-sm" lay-event="expandAll-true">
|
||||
expandAll-true
|
||||
</button>
|
||||
<button class="layui-btn layui-btn-sm" lay-event="expandAll-false">
|
||||
expandAll-false
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/html" id="TableItemTools">
|
||||
<div class="layui-btn-container">
|
||||
<a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="addChild"
|
||||
>新增子件</a
|
||||
>
|
||||
<a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="delChild"
|
||||
>删除</a
|
||||
>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/html" id="TableItemTools">
|
||||
<div class="layui-btn-container">
|
||||
<a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="addChild"
|
||||
>新增子件</a
|
||||
>
|
||||
<a class="layui-btn layui-btn-warm layui-btn-xs" lay-event="delChild"
|
||||
>删除</a
|
||||
>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="sexTpl">
|
||||
<select name="select-sex" class="layui-border select-sex" lay-ignore lay-filter="sex_{{d.rowid}}" id="sex_{{d.rowid}}">
|
||||
<option value="">请选择</option>
|
||||
<option value="男" {{d.sex=="男"?"selected":""}}>男</option>
|
||||
<option value="女" {{d.sex=="女"?"selected":""}}>女</option>
|
||||
</select>
|
||||
</script>
|
||||
<script type="text/html" id="provinceTpl">
|
||||
<select name="select-province" class="layui-border select-province" lay-ignore lay-filter="province_{{d.rowid}}" id="province_{{d.rowid}}">
|
||||
<option value="">请选择</option>
|
||||
{{# layui.each(d.provinceList, function(i, v){ }}
|
||||
<option value="{{v.id}}" {{d.province==v.id?"selected":""}}>{{v.name}}</option>
|
||||
{{# }); }}
|
||||
</select>
|
||||
</script>
|
||||
<script type="text/html" id="cityTpl">
|
||||
<select name="select-city" class="layui-border select-city" lay-ignore lay-filter="city_{{d.rowid}}" id="city_{{d.rowid}}">
|
||||
<option value="">请选择</option>
|
||||
{{# layui.each(d.cityList, function(i, v){ }}
|
||||
<option value="{{v.id}}" {{d.city==v.id?"selected":""}}>{{v.name}}</option>
|
||||
{{# }); }}
|
||||
</select>
|
||||
</script>
|
||||
<script type="text/html" id="districtTpl">
|
||||
<select name="select-district" class="layui-border select-district" lay-ignore lay-filter="district_{{d.rowid}}" id="district_{{d.rowid}}">
|
||||
<option value="">请选择</option>
|
||||
{{# layui.each(d.districtList, function(i, v){ }}
|
||||
<option value="{{v.id}}" {{d.district==v.id?"selected":""}}>{{v.name}}</option>
|
||||
{{# }); }}
|
||||
</select>
|
||||
</script>
|
||||
<script src="../src/layui.js" src1="//cdn.staticfile.org/layui/2.9.9/layui.js"></script>
|
||||
<script>
|
||||
layui.use(["jquery", "treeTable", "form"], function () {
|
||||
var $ = layui.jquery;
|
||||
var table = layui.table;
|
||||
var treeTable = layui.treeTable;
|
||||
var form = layui.form;
|
||||
|
||||
var provinceList = [
|
||||
{ id: "01", name: "湖北省" },
|
||||
{ id: "02", name: "湖南省" },
|
||||
{ id: "03", name: "广东省" },
|
||||
];
|
||||
var cityList = [
|
||||
{ id: "01.01", name: "武汉市" },
|
||||
{ id: "01.02", name: "黄石市" },
|
||||
|
||||
{ id: "02.01", name: "长沙市" },
|
||||
{ id: "02.02", name: "株洲市" },
|
||||
|
||||
{ id: "03.01", name: "广州市" },
|
||||
];
|
||||
var districtList = [
|
||||
{ id: "01.01.01", name: "江岸区" },
|
||||
{ id: "01.01.02", name: "江汉区" },
|
||||
{ id: "01.01.03", name: "武昌区" },
|
||||
{ id: "01.02.01", name: "下陆区" },
|
||||
{ id: "01.02.02", name: "铁山区" },
|
||||
|
||||
{ id: "02.01.01", name: "天心区" },
|
||||
{ id: "02.01.02", name: "芙蓉区" },
|
||||
{ id: "02.01.03", name: "浏阳市" },
|
||||
{ id: "02.02.01", name: "天元区" },
|
||||
{ id: "02.02.02", name: "石峰区" },
|
||||
|
||||
{ id: "03.01.01", name: "越秀区" },
|
||||
{ id: "03.01.02", name: "海珠区" },
|
||||
];
|
||||
|
||||
var isHtmlIcon = false;
|
||||
var genIcon = function (str, isHtml) {
|
||||
return isHtml ? normalizedIcon(str) : str
|
||||
}
|
||||
var icons = {
|
||||
flexIconClose: genIcon('layui-icon layui-icon-addition', isHtmlIcon),
|
||||
flexIconOpen: genIcon('layui-icon layui-icon-subtraction', isHtmlIcon),
|
||||
iconClose: genIcon('layui-icon layui-icon-add-circle', isHtmlIcon),
|
||||
iconOpen: genIcon('layui-icon layui-icon-reduce-circle', isHtmlIcon),
|
||||
iconLeaf: genIcon('layui-icon layui-icon-snowflake', isHtmlIcon),
|
||||
icon: genIcon('layui-icon layui-icon-addition', isHtmlIcon),
|
||||
}
|
||||
|
||||
treeTable.render({
|
||||
elem: "#MianTable",
|
||||
toolbar: "#toolbar",
|
||||
limit: 100,
|
||||
tree: {
|
||||
// customName: {
|
||||
// id: "id",
|
||||
// name: "id",
|
||||
// },
|
||||
view: {
|
||||
// showFlexIconIfNotParent: true,
|
||||
// flexIconClose: icons.flexIconClose,
|
||||
// flexIconOpen: icons.flexIconOpen,
|
||||
// iconClose: icons.iconClose,
|
||||
// iconOpen: icons.iconOpen,
|
||||
// iconLeaf: icons.iconLeaf,
|
||||
// icon: icons.icon
|
||||
},
|
||||
},
|
||||
cols: [
|
||||
[
|
||||
//标题栏
|
||||
{ checkbox: true, fixed: "left" },
|
||||
{ field: "id", title: "ID", width: 150 },
|
||||
{
|
||||
title: "操作",
|
||||
width: 150,
|
||||
align: "center",
|
||||
toolbar: "#TableItemTools",
|
||||
},
|
||||
{ field: "name", title: "用户名", width: 180, edit: "text" },
|
||||
{ field: "sex", title: "性别", templet: "#sexTpl" },
|
||||
{ field: "province", title: "省", templet: "#provinceTpl" },
|
||||
{ field: "city", title: "市", templet: "#cityTpl" },
|
||||
{ field: "district", title: "区", templet: "#districtTpl" },
|
||||
],
|
||||
],
|
||||
data: [],
|
||||
done: function () {
|
||||
var options = this;
|
||||
|
||||
// 获取当前行数据
|
||||
table.getRowData = function (tableId, elem) {
|
||||
var index = $(elem).closest("tr").data("index");
|
||||
return table.cache[tableId][index] || {};
|
||||
};
|
||||
|
||||
var tableViewElem = this.elem.next();
|
||||
tableViewElem.off("change.tbSelect");
|
||||
tableViewElem.on("change.tbSelect", ".select-sex", function () {
|
||||
var value = this.value; // 获取选中项 value
|
||||
var data = table.getRowData(options.id, this);
|
||||
data.sex = value;
|
||||
|
||||
var DATA_INDEX = data.LAY_DATA_INDEX; //此处需要内部字段更新行数据
|
||||
treeTable.updateNode("MianTable", DATA_INDEX, {
|
||||
province: "01",
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
treeTable.on("toolbar(MianTable)", function (obj) {
|
||||
var id = obj.config.id;
|
||||
var checkStatus = treeTable.checkStatus(id);
|
||||
|
||||
switch (obj.event) {
|
||||
case "AddRowButton":
|
||||
treeTable.addNodes(id, {
|
||||
parentIndex: null,
|
||||
index: -1,
|
||||
//index: 0,
|
||||
data: {
|
||||
id: Date.now(),
|
||||
provinceList: $.extend(true, [], provinceList),
|
||||
// icon: 'layui-icon layui-icon-github'
|
||||
},
|
||||
});
|
||||
console.log("add", table.cache["MianTable"]);
|
||||
|
||||
break;
|
||||
|
||||
case "InitTableButton":
|
||||
treeTable.reloadData("MianTable", {
|
||||
data: [
|
||||
{
|
||||
name: 1,
|
||||
provinceList: provinceList,
|
||||
children: [{ name: 2, provinceList: provinceList }],
|
||||
},
|
||||
{ name: 3, provinceList: provinceList },
|
||||
],
|
||||
});
|
||||
break;
|
||||
case "SubmitButton":
|
||||
console.log(treeTable.getData("MianTable"));
|
||||
case 'expandAll-true':
|
||||
treeTable.expandAll('MianTable', true);
|
||||
break;
|
||||
case 'expandAll-false':
|
||||
treeTable.expandAll('MianTable', false);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
treeTable.on("tool(MianTable)", function (obj) {
|
||||
var data = obj.data;
|
||||
var id = obj.config.id;
|
||||
var trElem = obj.tr;
|
||||
switch (obj.event) {
|
||||
case "addChild":
|
||||
let json = {
|
||||
id: Date.now(),
|
||||
provinceList: $.extend(true, [], provinceList),
|
||||
};
|
||||
|
||||
treeTable.addNodes(id, {
|
||||
parentIndex: data["LAY_DATA_INDEX"],
|
||||
index: -1,
|
||||
data: json,
|
||||
});
|
||||
|
||||
console.log("addChild", table.cache["MianTable"]);
|
||||
|
||||
break;
|
||||
case "delChild":
|
||||
// obj.del();
|
||||
// treeTable.removeNode(id, data["LAY_DATA_INDEX"]);
|
||||
treeTable.removeNode(id, trElem.attr("data-index"));
|
||||
console.log("del", table.cache["MianTable"]);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
});
|
||||
|
||||
function normalizedIcon(iconStr) {
|
||||
return iconStr
|
||||
? /<[^>]+?>/.test(iconStr) ? iconStr : '<i class="' + iconStr + '"></i>'
|
||||
: ''
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user